C 标准IO 库函数与Unbuffered IO函数

先来看看C标准I/O库函数是如何用系统调用实现的。 


fopen(3) 

调用open(2)打开指定的文件,返回一个文件描述符(就是一个int 类型的编号),分配一 个FILE 结构体, 通常里面包含了:

  • 文件fd
  • 缓冲区指针
  • 缓冲区长度
  • 当前缓冲区读取长度
  • 出错标志

返回这 个FILE 结构体的地址。 



fgetc(3) 
通过传入的FILE *参数找到该文件的描述符、I/O缓冲区和当前读写位置,判断能否从I/O缓冲 区中读到下一个字符,如果能读到就直接返回该字符,否则调用read(2),把文件描述符传进 去,让内核读取该文件的数据到I/O缓冲区,然后返回下一个字符。注意,对于C标准I/O库来 说,打开的文件由FILE *指针标识,而对于内核来说,打开的文件由文件描述符标识,文件描述符从open 系统调用获得,在使用read 、write 、close 系统调用时都需要传文件描述符。 


fputc(3) 
判断该文件的I/O缓冲区是否有空间再存放一个字符,如果有空间则直接保存在I/O缓冲区中并 返回,如果I/O缓冲区已满就调用write(2) ,让内核把I/O缓冲区的内容写回文件。 


fclose(3) 
如果I/O缓冲区中还有数据没写回文件,就调用write(2) 写回文件,然后调用close(2) 关闭文 件,释放FILE 结构体和I/O缓冲区。


以写文件为例,C标准I/O库函数(printf(3) 、putchar(3) 、fputs(3) )与系统调用write(2) 的关 系如下图所示。

  库函数与系统调用的层次关系




open 、read 、write 、close 等系统函数称为无缓冲I/O(Unbuffered I/O)函数,因为它们位于C标 准库的I/O缓冲区的底层。用户程序在读写文件时既可以调用C标准I/O库函数,也可以直接调用 底层的Unbuffered I/O函数,那么用哪一组函数好呢? 


用Unbuffered I/O函数每次读写都要进内核,调一个系统调用比调一个用户空间的函数要慢很 多,所以在用户空间开辟I/O缓冲区还是必要的,用C标准I/O库函数就比较方便,省去了自己 管理I/O缓冲区的麻烦。 


用c标准I/O库函数要时刻注意I/O缓冲区和实际文件有可能不一致,在必要时需调 用fflush(3) 。 


我们知道UNIX的传统是Everything is a file,I/O函数不仅用于读写常规文件,也用于读写设 备,比如终端或网络设备。在读写设备时通常是不希望有缓冲的,例如向代表网络设备的文 件写数据就是希望数据通过网络设备发送出去,而不希望只写到缓冲区里就算完事儿了,当网络设备接收到数据时应用程序也希望第一时间被通知到,所以网络编程通常直接调 用Unbuffered I/O函数。 


C标准库函数是C标准的一部分,而Unbuffered I/O函数是UNIX标准的一部分,在所有支持C语言的 平台上应该都可以用C标准库函数(除了有些平台的C编译器没有完全符合C标准之外),而只有 在UNIX平台上才能使用Unbuffered I/O函数,所以C标准I/O库函数在头文件stdio.h中声明, 而read 、write 等函数在头文件unistd.h 中声明。在支持C语言的非UNIX操作系统上,标准I/O库的 底层可能由另外一组系统函数支持,例如Windows系统的底层是Win32 API,其中读写文件的系统 函数是ReadFile 、WriteFile 。


参考: 《linux c 编程一站式学习》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
常用的五个函数(I/O) 1. 图像载入函数 函数cvLoadImage载入指定图像文件,并返回指向该文件的IplImage指针。函数支持bmp、jpg、 png、 tiff等格式的图像。其函数原型如下: IplImage* cvLoadImage( const char* filename, int iscolor); 其中,filename 是待载入图像的名称,包括图像的扩展名;iscolor是一个辅助参数项,可选正数、零和负数三种值,正数表示作为三通道图像载入,零表示该图像作为单通道图像,负数表示载入图像的通道数由图像文件自身决定。 2. 窗定义函数 函数cvNamedWindow定义一个窗,用于显示图像。其函数原型如下: int cvNamedWindow( const char* name, unsigned long flags ); 其中,name是窗名,flags是窗属性指标值,可以选择CV_WINDOW_AUTOSIZE和0两种值。CV_WINDOW_AUTOSIZE表示窗尺寸与图像原始尺寸相同,0表示以固定的窗尺寸显示图像。 函数 cvDestroyWindow(const char* name);销毁以上定义的窗。 name是窗名 3. 图像显示函数 函数cvShowImage是在指定的窗中显示图像,其函数原型如下: void cvShowImage( const char* name, const CvArr* image ); 其中,name是窗名称,image是图像类型指针,一般是IplImage指针。 4. 图像保存函数 函数cvSaveImage以指定的文件名保存IplImage类型的指针变量,其函数原型如下: int cvSaveImage( const char* filename, const CvArr* image ); 其中,filename是图像保存路径和名称,image是IplImage指针变量。 5. 图像销毁函数 函数cvReleaseImage销毁已定义的IplImage指针变量,释放占用内存空间。其函数原型如下: void cvReleaseImage( IplImage** image ); 其中,image为已定义的IplImage指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值