一、系统I/O
1、打开、关闭文件
int open(const char* path,int oflags);
int open(const char* path,int oflags,mode_t mode);
flags参数指明了进程打算如何访问这个文件:O_RDONLY 只读,O_WRONLY 只写,O_RDWR 可读可写
mode指定了新文件的访问权限位。当进程通过带某个mode参数的open函数调用来创建一个新文件时,文件的访问权限被设置成mode&~umask。(每个进程都有一个umask,它是通过调用umask函数来设置的)
2、读、写文件
size_t read(int fd,void *buf,size_t n);
size_t write(int fd,const void *buf,size_t n);
某些情况下,read和write传送的字节比应用程序要求的要少,出现这些不足值的原因如下:
读时遇到EOF。假设我们准备读取一个文件,该文件从当前位置开始只含有20个字节,而我们以50个字节的片进行读取。导致read返回的不足值为20,此后的read将通过返回不足值0来发出EOF信号;
从终端读文本行。如果打开的文件与终端相关联(如键盘和显示器),那么每个read函数将一次传送一个文本行,返回不足值等于文本行的大小;
读和写网络套接字。内部缓冲约束和较长的网络延迟会引起read和write返回不足值。对管道调用read和write也有可能出现不足值。
3、用RIO包健壮地读写
RIO的无缓冲的输入输出函数
ssize_t rio_readn(int fd,void *usrbuf,size_t n);
ssize_t rio_writen(int fd,void *usrbuf,size_t n);
rio_readn在遇到EOF时会返回不足值,rio_writen不会返回不足值。对同一个描述符,这两个函数可以任意交错的使用。
RIO的带缓冲的输入函数
void rio_readinitb(rio_t *rp , int fd); // 初始化缓冲区,把缓冲区和文件描述符联系起来
ssize_t rio_readlineb(rio_t *rp,void *usrbuf,size_t maxlen);
ssize_t rio_readnb(rio_t *rp,void *usrbuf,size_t n);
rio_readlineb函数从文件rp读出一个文本行(包括结尾的换行符),将它拷贝到结尾的存储器位置,并用空(零)字符来结束这个文本行。rio_readlineb函数从文件rp最多读n个字节到存储器位置usrbuf。对于同一描述符,这两个函数可以任意交叉使用。但是对于同一描述符,这两个函数不能和无缓冲的交叉使用。
二、读取文件元数据
获取文件元数据的函数为:
元数据数据结构:
三、共享文件
记住如下三幅图即可:
四、I/O重定向
函数为:
函数解释:
(即:让描述符oldfd实现newfd的功能)
eg,dup2(field,1) 将标准描述符输出重定向到field描述符
解析图如下:
五、以上是一些系统调用,实际上还定义了一些标准I/O
六、选择
建议在网络套接字上不要使用标准I/O函数来进行输入和输出。而要使用健壮的RIO函数。
原因如下:
限制一:跟在输出函数之后的输入函数。中间必须有fflush、fseek。fsetpos或者rewind的调用。
限制二:跟在输入函数之后的输出函数。中间必须有fseek、fsetpos或者rewind的调用。
但是,对套接字使用lseek违法,所以第一个限制,可以采用刷新缓冲区满足;第二个限制的解决办法是,对同一个套接字打开两个流,一个写,一个读: