博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Chapter 3: File I/O

Posted on 2011-04-29 22:05  天地玄黄  阅读(208)  评论(0编辑  收藏  举报

     1. 我目前在Linux中运行的程序通常是在Shell 之上运行的,Shell 已经设定好了 standard input(键盘) 和 standard output(显示器).

     2. 许多程序都默认 standard input 的 file descriptor 是 0, standard output 的 file descriptor 是 1。在<unistd.h>中定义了两个常量来表示这两个 file descriptor,一个是STDIN_FILENO,另一个是STDOUT_FILENO.

     3. 当一个进程结束的时候,由这个进程所打开的所有 file 都会由 kernel 自动关闭。

     4. read() 和 write() 这两个函数是 unbuffered I/O,而 standered I/O 是 buffered I/O.

     5. Unix中的所有东西都是文件。对于一个打开的文件,Unix 内核使用三种数据结构联合起来描述一个打开的文件:

         · 每个进程在进程表(process table)中都会占有一个条目,在这里面就放着打开的file 的 descriptor。对于每一个descriptor,有两个描述它的东西:

             一个是file descriptor flag(说明这个file的状态,是close 、on 或者 exec);

             还有一个是指向file table entry的指针。

         · 对于所有打开的文件,内核维护着一个 file table,这里面每一个条目包括三个部分:

             file satus flags(read, write, append, sync, nonblocking);

             current file offset

             执行v-node table的指针

         · 每一个打开的文件有一个v-node talbe表示这个文件的一些信息。

image

     6. lseek()这个函数就是设置file table 的current file offset。它也仅仅只是对这个值进行设置,并不会进行真正的I/O操作。

     7. 如果使用write() 对文件进行写操作,写入多少bytes, current file offset 就会加上多少。当current file offset 的值要比i-node 中的current file size还大的时候,这个值就会变得和current file offset一样大。

     8. 这里稍微讲到了一些原子操作的东西。如果一个操作需要两个函数来完成,那么多个进程进行这个操作就有可能出问题。比如“查找一个文件的末尾”和“往文件中写入”这两个操作,需要使用lseek() 和 write()这两个函数。如果这不是一个原子操作,那么很可能会出问题。原子操作就表明,这两个函数,要么全部执行,要么不执行,不会出现只执行lseek()这一个函数的情形出现。

     9. 当使用open() 函数打开一个文件的时候,这个函数所返回的file descriptor保证是系统之中可以使用的最小的file descriptor。

         使用dup() 函数复制一个 file descriptor的时候,它所返回的 file descriptor 也能保证是系统之中可以使用的最小的file descriptor的值。

     10. Unix系统中一般都会有buffer cache 或者 page cache,当向磁盘读写的时候,大部分I/O都要经过这些cache。这样一些数据就会以queue的形式保存在 kernel中,就需要一种方法来把cache中的东西和磁盘中的文件进行同步。这就需要使用sync() 函数 或者 fsync() 函数。

     11. 使用F_GETFL找出file status flags:

val = fcntl(atoi(argv[1]), F_GETFL, 0)


     12. Normally in the UNIX System, a write only queues the data for writing; the actual disk write operation can take place sometime later. IF WE SET O_SYNC, this causes each write to wait for the data to be written to disk before returning.