Unix环境高级编程学习笔记(一)

第二章 文件I/O

1、文件描述符
  对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数。
  Unix shell使用文件描述符0表示标准输入,1表示标准输出,2表示标准出错输出,为了避免在代码中出现魔数,在<unixtd.h>头文件中,1,2,3替换为符号常量STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO,文件描述符的变化范围是0~OPEN_MAX。

2、open函数
原型:#include<fcntl.h>
    int open(const char *pathname, int oflag, ...)   /*仅当创建新文件时才使用第三个参数*/
 pathname是要打开或创建的文件名字,oflag是参数选项,可选值有:O_RDONLY(只读打开,0),O_WRONLY(只写打开,1),O_RDWR(读写打开,2),这些常量定义在<fcntl.h>头文件中,这3个常量必须指定一个且只能指定一个。下列常量是可选的,O_APPEND(写时追加尾部),O_CREAT(若不存在则创建,需指定第三个参数说明文件访问权限),O_EXCL(若和O_CREAT一起使用,当要创建的文件已经存在就会失败),O_TRUNC(文件截短为0,需文件存在,且为只写或读写打开),O_NOCTTY(pathname指向终端设备,不将它作为控制终端),O_NONBLOCK(pathname指向FIFO、块或字符特殊文件时,设置非阻塞模式)、O_DSYNC(使每次write等待物理IO操作完成,不包括文件属性IO的更新),O_RSYNC(读操作等待写操作完成)、O_SYNC(每次write等待物理IO操作完成,包括文件属性IO的更新)     注意:Linux将O_DSYNC、O_RSYNC、O_SYNC等同与O_SYNC(其实这些知识点应该是自己做实验发现,而不是等着书本来教你~~)              返回最小的未使用描述符数值。

3、creat函数
原型:#include<fcntl.h>
    int create(const char* pathname, mode_t mode);等效于open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode),可以完全用open函数取代creat函数

4、close函数
原型:#include<unistd.h>
    int close(int filedes);关闭一个文件时还会释放该进程加在该文件上的记录锁。

5、lseek函数
作用:显示的为一个文件设置偏移量
原型:#include<unistd.h>
     off_t lseek(int fileds, off_t offset, int whence);
  对offset的解释与whence的值有关,当whence为SEEK_SET,则该文件的偏移量为距文件开头处offset字节处; 当whence为SEEK_CUR,则该文件的偏移量为当前值加上offset,offset可以为正或负;  当whence为SEEK_END,则文件偏移量为文件长度加offset,offset可以为正或负。      返回新的文件偏移量。
应用:1、确定打开文件当前偏移量:off_t currpos;       currpos = lseek(fd, 0, SEEK_CUR);
     2、确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将errno设置为ESPIPE。
     3、lseek允许定位到文件长度之后,这样就会造成文件空洞。使用od(1)命令可以观察文件的实际内容。

6、read函数
原型:#include<unistd.h>
     ssize_t read(int filedes, void *buf, size_t nbytes);   成功返回读到的字节数,到文件尾返回0,失败返回-1

7、write函数
原型:#include<unistd.h>
     ssize write(int filedes, const void* buf, size_t nbytes);   成功返回已写字节数,若出错返回-1

8、关于文件共享
 内核使用3种数据结构表示打开的文件:(1)每个进程都有一个打开文件描述符表;(2)内核为所有打开文件维持一张文件表(每个表项包括文件状态标志,当前文件偏移量,指向该节点v节点指针),(3)一个v节点结构包括文件类型及i节点信息(如文件所有者、文件长度、文件所在设备等等)                 注:linux没有v节点,使用的就是i节点

9、使用原子操作的场合:1)、lseek+write -> 使用O_APPEND标志 或 使用pread函数和pwrite函数

10、dup和dup2函数:用于复制一个现存的文件描述符
原型:#include<unistd.h>    int dup(int filedes);      int dup2(int filedes1, int filedes2);    dup返回当前可用的最小文件描述符,dup2可用filedes2指定文件描述符,如果filedes已经打开则先将其关闭,这些函数返回的新文件描述符与filedes共享同一个个文件描述符。

11、sync、fsync、fdatasync函数
 文件io的传统实现使用延迟写策略,增加了性能却降低了文件跟新速度,这3个函数的作用就是保证磁盘里实际的文件内容和缓冲区里内容一致。   注意:系统会周期的自动调用sync函数。
原型:#include<unistd.h>    int fsync(int filedes);    int fdatasync(int filedes);     void sync(void);

12、fcntl函数:可以改变已打开文件的性质。
原型:#include<fcntl.h>        int fcntl(int filedes, int cmd, ...)     出错返回-1
功能:(1)、复制现有文件描述符(cmd=F_DUPFD)    (2)、获得设置文件描述符标志(cmd=F_GETFD或cmd=F_SETFD)  (3)、获得或设置文件状态标志(cmd=F_GETFL或cmd=F_SETFL)   (4)、获得设置异步IO所有权(cmd=F_GETOWN或F_SETOWN)   (5)、获得设置记录锁(cmd=F_GETLK、F_SETLK、F_SETLKW)
注意:dup(filedes);等价于fcntl(filedes, F_DUPFD, 0);         dup2(filedes1, filedes2);等价于close(filedes2);    fcntl(filedes1, F_DUPFD, filedes2);

13、ioctl函数:是IO操作的杂物箱,不能用本章中其他函数表示的IO操作通常都能用ioctl表示。
原型:#include<unistd.h>   #include<sys/ioctl.h>     #include<stropts.h>
int  ioctl(int filedes, int request, ...)         若出错,返回-1

14、/dev/fd:该目录下为Linux打开文件描述符的映射。

posted @ 2011-07-30 13:52  name_110  阅读(1608)  评论(0编辑  收藏  举报