logo资料库

Unix文件IO汇总.pdf

第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
资料共15页,剩余部分请下载后查看
Unix 文件 IO 1 系统 IO 本章所说明的函数经常被称为不带缓冲的 I/O ,术语不带缓冲指的是每个 read 和 write 都调用内核中的一个系统调用。这些不带缓冲的 IO 不是 ISO C 的组成部分,但是,它们是 POSIX.1 和 Single UNIX Specification 的组成部分。 1.1 文件描述符 对于内核而言,所有打开的文件都通过文件描述符引用。文件描述符是一个非负整数。 按照惯例,UNIX 系统 shell 使用文件描述符 0 与进程的标准输入相关联,文件描述符 1- 与标准输出相关联,文件描述符 2 与标准出错输出相关联。这是各种 shell 以及很多应用程 序使用的惯例,而与 UNIX 内核无关。尽管如此,如果不遵照这种惯例,那么很多 UNIX 系 统应用程序就不能正常工作。 1.2 函数 open pathname 是要打开或创建文件的名字。大多数的现代文件系统支持文件名的最大长度 为 255;如果超过了该长度,根据 POSIX.1 标准,若 POSIX_NO_TRUNC 有效,则报错;否则, 将文件名截短。 oflag 参数可用来说明此函数的多个选项。用下列一个或多个常量进行“或”运算构成 of lag 参数(这些常量定义在头文件中):  O_RDONLY: 只读打开。  O_WRONLY: 只写打开。  O_RDWR: 读、写打开。  O_EXEC:只执行打开  O_SEARCH:只搜索打开,对应于目录 在这五个常量中必须指定一个且只能指定一个。下列常量则是可选择的:  O_APPEND:每次写时都追加到文件的尾端。  FD_ CLOEXEC:自进程中调用 exec 时,关闭文件描述符  O_CREAT 若此文件不存在,则创建它。使用此选项时,需要第三个参数 mode,用 其指定该新文件的访问权限位  O_DIRECTORY:如果 pathname 不是目录,则出错  O_ EXCL 如果同时指定了 O_CREAT,而文件已经存在,则会出错。用此可以测试 一个文件是否存在,如果不存在,则创建此文件,这使测试和创建两者成为一个原
子操作。  O_ TRUNC:如果此文件存在,而且为只写或读写成功打开,则将其长度截短为 0  O_NOCTTY 如果 pathname。指的是终端设备,则不将该设备分配作为此进程的控 制终端。  O_NONBLOCK 如果 pathname 指的是一个 FIFO、一个块特殊文件或一个字符特殊文 件,则此选项为文件的本次打开操作和后续的 I/O 操作设置非阻塞模式。  O_ DSYNC:使每次 write 等待物理 I/O 操作完成,但是如果写操作并不影响读取刚 写入的数据,则不等待文件属性被更新。  O_RSYNC: 使每一个以文件描述符作为参数的 read 操作等待,直至任何对文件同一 部分挂起的写操作都完成。  O_ SYNC:使每次 write 都等到物理 1/O 操作完成,包括由 write 操作引起的文件属 性更新所需的 IO。 mode:只在创建时使用,指定文件权限位 1.3 函数 creat 等价于: open (pathname,O_WRONLY|O _CREAT|O_ TRUNC,mode); 1.4 函数 close 关闭一个文件时还会释放该进程加在该文件上的所有记录锁。 当一个进程终止时,内核自动关闭它所有打开的文件。很多程序都利用了这一功能而不 显式地用 close 关闭打开文件。 1.5 函数 lseek 每个打开的文件都有一个与其相关联的“当前文件偏移量”(current file offset)。它通常 是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件偏 移量处开始,并使偏移量增加所读写的字节数。按系统默认的情况,当打开一个文件时,除 非指定。O_APPEND 选项,否则该偏移量被设置为 0。
若 whence 是 SEEK_SET,则将该文件的偏移量设置为距文件开始处 offset 个字节。 若 whence 是 SEEK_CUR,则将该文件的偏移量设置为其当前值加 offset, offset 可为正或负。 若 whence 是 SEEK_END,则将该文件的偏移量设置为文件长度加 offset, offset 可为正或负。 1.6 函数 read  读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之  前还有 30 个字节,而要求读 100 个字节,则 read 返回 30,下一次再调用 read 时,它 将返回 0。  当从终端设备读时,通常一次最多读一行。  当从网络读时,网络中的缓冲机制可能造成返回值小于所要求读的字节数。  当从管道或 FIFO 读时,如若管道包含的字节少于所需的数量,那么 read 将只返回实际 可用的字节数。  当从某些面向记录的设备(例如磁带)读时,一次最多返回一个记录。 1.7 函数 write 其返回值通常与参数 nbytes 的值相同,否则表示出错。write 出错的一个常见原因是: 磁盘已写满,或者超过了一个给定进程的文件长度限制
1.8 IO 效率 标准输出重定向到/dev/null 上,测试用的文件系统为 linux ext4,其磁盘块长度为 4096 字节。 1.9 文件共享 内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进 程对另一个进程可能产生的影响。 (1) 每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,可将其 视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
a) 文件描述符标志 b) 指向一个文件表项的指针。 (2) 内核为所有打开文件维持一张文件表。每个文件表项包含: a) 文件状态标志(读、写、添写、同步和非阻塞等)。 b) 当前文件偏移量。 c) 指向该文件 v 节点表项的指针。 (3) 每个打开文件(或设备)都有一个 v 节点(v-node)结构。v 节点包含了文件类型和对此文件 进行各种操作的函数的指针。对于大多数文件,v 节点还包含了该文件的 i 节点(i-node , 索引节点)。这些信息是在打开文件时从磁盘上读入内存的,所以所有关于文件的信息 都是快速可供使用的。例如,i 节点包含了文件的所有者、文件长度、文件所在的设备、 指向文件实际数据块在磁盘上所在位置的指针等等 如果两个独立进程各自打开了同一个文件,则有如下图的关系:
1.10 原子操作 调用 pread 相当于顺序调用 lseek 和 read,但是调用 pread 时,无法中断其定位和读操 作。 1.11 函数 dup 和 dup2 由 dup 返回的新文件描述符一定是当前可用文件描述符中的最小数值。用 dup2 则可以 用 filedes2 参数指定新描述符的数值。如果 filedes2 已经打开,则先将其关闭。如若 filedes 等于 filedes2,则 dup2 返回 filedes2,而不关闭它。 1.12 函数 sync、fsync、fdatasync
sync 函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁 盘操作结束。通常称为 update 的系统守护进程会周期性地(一般每隔 30 秒)调用 sync 函 数。这就保证了定期冲洗内核的块缓冲区。 fsync 函数只对由文件描述符 filedes 指定的单一文件起作用,并且等待写磁盘操作结束, 然后返回。fsync 可用于数据库这样的应用程序,这种应用程序需要确保将修改过的块立即 写到磁盘上。 fdatasync 函数类似干 fsync,但它只影响文件的数据部分。而除数据外,f sync 还会同步 更新文件的属性。 1.13 函数 fcntl fcntl 函数可以用来修改已经打开的文件的属性 在本节的各实例中,第二个参数总是一个整数,与上面所示函数原型中的注释部分相对 应。但是在使用记录锁时,第三个参数则是指向一个结构的指针。 fcntl 函数有 5 种功能:  复制一个现有的描述符(cmd=F_ DUPFD 或 F_ DUPFD_CLOEXEC)  获得/设置文件描述符标记(( cmd=F_ GETFD 或 F_ SETFD)  获得/设置文件状态标志(cmd=F_GETFL 或 F_SETFL)  获得/设置异步 IO 所有权(cmd = F_GETOWN 或 F _SETOWN)  获得/设置记录锁(cmd=F _GETLK, F_ SETLK 或 F_ SETLKW) (1) F_DUPFD:复制文件描述符 filedes。新文件描述符作为函数值返回。它是尚未打开的各 描述符中大于或等于第三个参数值(取为整型值)中各值的最小值。新描述符与 filedes 共 享同一文件表项(见图 3-3)。但是,新描述符有它自己的一套文件描述符标志,其 FD_ CLOEXEC 文件描述符标志被清除。 (2) F_ DUPFD_CLOEXEC:复制文件描述符 filedes,设置与新描述符关联的 FD_ CLOEXEC,返 回新描述符 (3) F_GETFD:对应于 filedes 的文件描述符标志作为函数值返回。当前只定义了一个文件描 述符标志 FD_CLOEXEC (4) F_SETFD:对于 filedes 设置文件描述符标志。新标志值按第 3 个参数(取为整型值)设置 (5) F_GETFL:对应于 filedes 的文件状态标志作为函数值返回。在说明 open 函数时,已说 明了文件状态标志。不幸的是,五个访问方式标志并不各占 1 位(前三种标志的值分别 是 0, 1 和 2,由于历史原因。这 5 个值互斥,一个文件只能有这 5 种值之一)。因此首 先必须用屏蔽字 O_ACCMODE 取得访问模式位,然后将结果与这三种值中的任一种作比 较。 (6) F_SETFL:将文件状态标志设置为第三个参数的值(取为整型值)。可以更改的几个标志 是:O_ APPEND, O_ NONBLOCK、O_SYNC, O_DSYNC、O_RSYNC、O_ FSYNC 和 O_ASYNC。 (7) F_GETOWN:获取当前接收 SIGIO 和 SIGURG 信号的进程 ID 或进程组 ID (8) F_SETOWN:设置接收 SIGIO 和 SIGURG 信号的进程 ID 或进程组 ID。正的 arg 指定一个 进程 ID,负的 arg 表示等于 arg 绝对值的一个进程组 ID
2 标准库 IO 本章说明标淮 vo 库。因为不仅在 UNIX 上,而且在很多操作系统上都实现了此库,所以 它由 ISOC 标淮说明。Single UNIX Specification 对 ISO C 标淮进行了扩展,定义了另外一些接 口。标堆 Io 库处理很多细节,例如缓冲区分配,以优化长度执行 IO 等。这些处理使用户不 必担心如何选择使用正确的块长度(如 1.8 节中所述)。 2.1 流和 FILE 对象 系统 IO 中,所有函数都是针对文件描述符的。当打开一个文件时,即返回一个文件描 述符,然后该文件描述符就用于后续的 I/O 操作。而对于标淮 I/O 库,它们的操作则是围绕 流( stream)进行的,当用标淮库 IO 打开或创建一个文件时,我们已使一个流与一个文件相 关联。 对于 ASCII 字符集,一个字符用一个字节表示。对于国际字符集,一个字符可用多个字 节表示。标淮 IO 文件流可用于单字节或多字节(“宽”)字符集。流的定向(streram's orientation) 决定了所读、写的字符是单字节还是多字节的,freopen 可以清除流的定向,fwide 可以设置 流的定向。 mode 为负,设置流为字节定向;mode 为正,设置流为宽定向;mode 为 0,返回当前 定向。 2.2 标准输入、标准输出、标准错误 对一个进程预定义了三个流,并且这三个流可以自动地被进程使用,它们是:标准输入、 标准输出和标准出错。这些流引用的文件与系统 IO 中提到的文件描述符定义的标准 IO 引用 的文件相同。 这三个标准 I/O 流通过预定义文件指针 stdin, stdout 和 stderr 加以引用。这三个文件 指针同样定义在头文件中。 2.3 缓冲 标准 IO 库提供缓冲的目的是尽可能减少使用 read 和 write 调用的次数(见表 3-2,其中 显示了在不同缓冲区长度情况下,为执行 IO 所需的 CPU 时间量)。它也对每个 IO 流自动地 进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦。不幸的是,标准 IO 库 最令人迷惑的也是它的缓冲。标准 IO 提供了三种类型的缓冲: (1) 全缓冲:这种情况下,在填满标准 I/O 缓冲区后才进行实际 I/O 操作。缓冲区可由标准
分享到:
收藏