Linux I/O函数(beta)

原创 2017年01月03日 16:06:18

在学习使用C语言的时候,我们总会遇到各种各样的输入输出函数。fopen,open,read,write,scanf,printf等等。那么到底什么时候应该用什么,我么该如何选择呢,我之前总是有疑问。在认真学习了《csapp》《apue》之后,总算是有点眉目了。下面做一个记录。

首先明确一下什么是输入输出,输入输出是在主存和外部设备之间拷贝数据的过程。输入输出是相对主存而言的。在编写C语言程序的时候,我们可能会遇到两类I/O函数,一类是系统I/O,一类是标准I/O。

系统I/O:
open,read, write,lseek,stat,close等
标准I/O:
fopen, fdopen, fread, fwrite, fscanf, fprintf, sscanf, sprintf,fgets,fputs
fflush, fseek, fclose等

标准I/O是系统I/O带缓冲的替代品,主要用来克服系统I/O的性能不足,是磁盘和终端设备I/O之选。
大多数C程序员在他们的职业生涯中只使用标准I/O,而从不涉及低级I/O函数。

标准I/O有一些限制:
限制一:
跟在输出函数之后的输入函数,如果中间没有插入对fflush/fseek/fsetpos或者rewind的调用,一个输入函数不能跟随在一个输出函数之后。fflush函数清空输出流的缓冲区,实际就是写入文件,这样的话,输入的数据就不会和因为输出而填在输入缓冲区的数据弄混了。后三个函数通过使用lseek函数来重置当前的文件位置。
限制二:
跟在输入函数之后的输出函数,如果中间没有插入fseek/fsetpos或者rewind的调用,一个输出函数不能跟随在一个输入函数之后,除非该输入函数遇上了一个EOF。因为这样的话,输出函数会连带缓冲区中的数据一起输出到文件中。

fseek,fsetpos和rewind都是改变文件表的当前位置指针,很好理解。
在这里的关键是fflush函数的理解,为什么对于限制二不能用fflush。
根据Linux man手册,
fflush有以下原型
int fflush(FILE *stream)
对于输出流,fflush将用户缓冲区的数据写到输出对象,或者通过流的写函数来更新流。对于可定位文件相对应的输入流(磁盘文件,但不能是管道或者终端设备),fflush抛弃
从对应文件中取出到缓冲区中但是还没有被应用所用的数据。
如果stream参数是NULL, fflush flush所有打开的输出流。
fflush并不会改变文件表的当前位置。
在对网络使用标准I/O的时候会遇到问题。因为对套接字使用lseek函数是非法的。
对流I/O的第一个限制能够通过采用在每个输入操作前刷新缓冲区来满足(实验验证ubuntu16.04,无论是否使用fflush效果是一样的,相信在fread实现中有内置的fflush),然而要满足第二个限制
唯一的办法是,对同一个打开的套接字描述符打开两个流,一个用来读一个用来写。但是fclose(fpin)和fclose(fout),试图关闭同一个底层的套接字描述符,所以第二个close会失败,对于顺序程序来说不是问题,但是对于线程化的程序来说关闭一个已经关闭的描述符会导致灾难(为什么会导致灾难)。

因此《csapp》建议使用健壮的rio函数,如果需要格式化的输出,使用sprintf函数在存储器中格式化一个字符串,然后用rio_writen把它发送到套接字接口(直接不用缓冲区,相比原始接口仅仅重启中断的系统调用)。如果需要格式化输入,使用rio_readlineb来读一个完整的文本行,然后用sscanf从文本行中提取不同的字段。实际上就是说输出就不要用buffer了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

linux系统编程之文件与I/O(六):fcntl 函数与文件锁

一、fcntl函数 功能:操纵文件描述符,改变已打开的文件的属性 int fcntl(int fd, int cmd, ... /* arg */ ); cmd的取值可以如下: 复制文件描述符...

linux网络编程之socket(八):五种I/O模型和select函数简介

一、五种I/O模型 1、阻塞I/O 我们在前面所说的I/O模型都是阻塞I/O,即调用recv系统调用,如果没有数据则阻塞等待,当数据到来则将数据从内核空间(套接口缓冲区)拷贝到用户空间(recv...

Linux I/O复用之select函数详解

select函数的功能和调用顺序使用select函数时统一监视多个文件描述符的: 1、 是否存在套接字接收数据? 2、 无需阻塞传输数据的套接字有哪些? 3、 哪些套接字发生了异常?sel...

Linux 高级I/O函数

一、pipe()函数 1.1、pipe函数创建一个管道,以实现进程间通信。 1.2、int pipe(int fd[2]),pipe函数的参数是一个包含两个int型整数的数组指针。函数成功时返回0...

Linux标准I/O库常用函数总结(二)

6.fgetc,getc和getchar 函数原型: #include int fgetc(FILE *stream); int getc(FILE *stream); int getchar(...

Linux 文件I/O(二)之 fcntl函数讲解

Linux下 fcntl函数讲解    见名知意          fcntl()属于系统调用,根据你提供的文件描述符操作文件的特性。    头文件及函数原型    #include    #inc...

Linux C 环境下不带缓冲的I/O操作函数

摘要:本文主要介绍Linux C 环境下不带缓冲的文件I/O操作函数——open(),creat(),read(),write(),lseek(),close()。结合实例,简单地利用单进程和多进程对...

linux高性能服务器编程学习笔记五:高级I/O函数

1、linux提供了一些高级I/O函数,在特定的情况下表现出优秀的性能。这些函数大致分为3类 (1)用于创建文件描述符的函数,包括pipe、dup/dup2函数 (2)用于读写数据的函数,包括re...

Linux系统文件I/O编程(二)---文件锁函数

文件锁     上一节:http://blog.csdn.net/mybelief321/article/details/8989755讲述的5个基本函数函数open()、read()、write(...

linux系统编程之文件与I/O(五):fcntl 函数与文件锁

#include #include #include #include #include #include #include #include #define ERR_EXIT(m) \ d...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux I/O函数(beta)
举报原因:
原因补充:

(最多只允许输入30个字)