第三章 文件I/O 一
一,名词说明文件描述符
针对内核,所有打开文件都是文件描述符引用.文件描述符是一个非负数整数.当打开一个现存文件或创建一个新的文件时,内核向进程返回一个文件描述符.
按照惯例,UNIX shell使用描述符0与进程的标准输入相结合,文件描述符1与标准输出相结合,文件描述符2与标准出错输出相结合.这些是UNIX shell以及很多应用程序的惯例,与内核无关.不遵照这种惯例,很多UNIX应用程序就不能工作.
magic number(幻数)
幻数检查用来检查文件中是否有特殊的固定格式的数据.规范的例子如二进制可执行文件(编译后的程序)a.out,该文件格式在标准include目录下的a.out.h文件中定义,也可能在exec.h中定义.这些文件在文件开始部分附近的一个特殊位置保存有一个'幻数',通过幻数告诉UNIX操作系统此文件是二进制可执行文件,和其中包含的其它类型.幻数的概念已经扩展到数据文件.任何在文件固定位置有与文件类型相关的不变标识符的文件都可以这样表示.这些文件中的信息可以从幻数文件/usr/share/magic中读取.
二,常数说明
O_RDONLY只读打开O_WRONLY只写打开O_RDWR读,写打开O_APPEND每次写时都加到文件尾端O_CREAT若文件不存在则创建它O_EXCL测试文件存不存在.与O_CREAT同时使用时,文件存在会报错O_TRUNC如果文件存在,而且为只读或只写成功打开,则将其程度截短为0O_NOCITY如果pathname指的是终端设备,则不将此设备分配作为此进程的控制终端O_SYNC使每次write都等到物理I/O操作完成
注意:很多实现将O_RDONLY定义为0,O_WRONLY定义为1,O_RDWR定义为2.
三,函数
open函数:打开或创建一个文件
int open(const char* pathname, int oflag, ... /*, mode_t mode */) 返回:成功 文件描述符,出错 -1
creat函数:创建一个新的文件
int creat(const char* pathname, mode_t )返回:成功为只写描述符,出错为-1
注意:open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode);creat函数只以只写方式打开所创建的文件
close函数:关闭一个打开文件
int close(int filedes)返回:成功 0,出错 -1
关闭一个文件时也释放该进程加在该文件上的所有记录锁.当一个进程终止时,它所有的打开文件都由内核自动关闭.很多程序都使用这一功能而不显示地用close关闭打开的文件.
lseek函数
off_t lseek(int filedes, off_t offset, int whence)返回:成功 新的文件位移,出错 -1
whence
SEEK_SET将该文件的位移量设置为距文件开始处offset个字节SEEK_CUR将该文件的位移量设置为其当前值加offset,offset可为+/-SEEK_END将文件的位移量设置为文件长度加offset,offset可为+/-
每个打开文件都有一个与其相关联的"当前文件位移量".它是一个非负整数,用一度量从文件开始处计算的字节数.通常,读写操作都从当前文件位移量处开始,并事位移量增加所读或写的字节数.
off_t currpos;currpos = lseek(fd, 0, SEEK_CUR);
以上方式可以确定一个打开文件的当前位移量,也可以用这种方法来确定所涉及的文件是否可以设置位移量.如果文件描述符引用的是一个管道或FIFO,则lseek返回-1,并将errno设置为EPIPE.
eg.
#include <sys/types.h>#include "ourhdr.h"int mian(void){ if(lseek(STDIN_FIFENO, 0, SEEK_CUR) == -1) //必须用==-1,而不能用是否小于0,因为某些设备允许负值 printf("cannot seek\n"); else printf("seek OK\n"); exit(0);}
lseek仅将当前位移量记录在内核内,并不引起任何I/O操作.然后位移量用于下一个读或写操作.
当文件位移量大于当前文件的长度时,该文件的下一次写将延长该文件,并在文件种构成一个空调,该文件没有写过的字节都被读为0.
eg.
#include <sys/types.h>#include <sys/stat.h>#include "ourhdr.h"char buf1[] = "abcdefghijklmnopqrstuvwxyz";char buf2[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";int main(void){ int fd; if((fd = creat("file.hole", FILE_MODE)) < 0) err_sys("creat error"); if (write(fd, buf1, 10) != 10) err_sys("buf1 write error"); if(lseek(fd, 40, SEEK_SET) == -1) err_sys("lseek error"); if(write(fd, buf2, 10) != 10) err_sys("buf2 write error"); exit(0);}
read函数:从打开文件中读数据
ssize_t rea(int filedes, void buff, size_t nbytes)返回:读到的字节数,文件结尾 0,出错 -1
际读到的字节数少于要求读字节数的情况:
• 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之前还有30个字节,而要求读 100个字节,则read返回30,下一次再调用read时,它将返回0(文件尾端)。
• 当从终端设备读时,通常一次最多读一行。
• 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
• 某些面向记录的设备,例如磁带,一次最多返回一个记录。
write函数:向打开文件写数据
ssize_t write(int filedes, const void buff, size_t nbytes返回:成功 以写的字节数 出错 -1
其返回值通常与参数nbytes的值相同,否则表示出错.write出错的常见原因:磁盘已写满,或者超过了对一个给定进程的文件长度限制.
页:
[1]