APUE第三章 文件I/O

来源:互联网 发布:cnabs数据库全称 编辑:程序博客网 时间:2024/05/16 13:43

APUE第三章 文件I/O

1、文件描述符

对于内核而言,所有打开的文件都通过文件描述符引用。文件描述符是打开或者创建文件的时候,内核向进程返回的一个非负整数。UNIX系统中,一般用0,1,2分别表示标准输入,标准输出和标准出错。一个系统的文件描述符变换范围在0~OPEN_MAX。在linux系统中,可以使用

cat /proc/sys/fs/file-max
查看最大描述符数量,并且可以根据需要修改这个数值。

2、open函数

#include <fcntl.h>int open(const char *filename, int oflag);int open(const char *filename, int oflag, mode_t mode);
描述:该函数根据oflag模式打开文件名为filename的文件,并返回打开的文件描述符。

其中oflag来说明此函数的多个选项,有以下取值:

O_RDONLY 只读打开

O_WRONLY只写打开

O_RDWR 读写打开

这三个常量必须指定且只能指定一个,下面的常量是可选的:

O_APPEND 写时追加

O_CREAT 文件若不存在,就创建

O_EXCL 如果指定了O_CREAT,且文件已经存在,就会出错,用来测试一个文件是否存在

O_TRUNC 文件存在,而且只写或读写打开成功,就将其长度截断为0

O_NOCTTY 若pathname是终端设备,则不将该设备分配作为此进程的控制终端


O_DSYNC 使每次write等待物理I/O操作完成,但是如果写操作并不影响读取刚写入的数据,则不等待文件属性更新

O_RSYNC 使每一个文件描述符作为参数的read操作等待,直至任何对文件同一部分进行的未决写操作都完成


3、creat函数

#include <fcntl.h>int creat(const char *filename, mode_t mode);
描述:以只写方式打开一个创建的新文件

如果要以可读写方式打开一个创建的新文件,可以使用

open(pathname,O_RDONLY | O_CREAT | O_TRUNC,mode)

4、close函数

#include <unistd.h>int close(int filedes);

关闭指定的文件描述符。同时,如果进程在此文件上加有记录锁,将释放。在进程终止时,内核将自动关闭进程打开的文件。

5、lseek函数

#include <unistd.h>off_t lseek(int filedes, off_t offset, int whence);
描述:每个打开的文件都有一个与之相关的文件偏移量,用于度量从文件开始处的字节数,可以用lseek显式的为一个打开的文件设置偏移量。三个参数分别是文件描述符,偏移,和设置偏移方式。执行成功返回新的文件偏移量。

其中偏移方式有一下选项:

  • 若whence是SEEK_SET,则文件偏移量是从开始到距文件开始处offset个字节。
  • 若whence是SEEK_CUR,则改文件的偏移量设置为当前值加offset,offset可正可负。
  • 若whence是SEEK_END,则该文件的偏移量设置为文件长度加上offset,offset可正可负。
可以用一下方式确定当前文件偏移量:

off_t currpos;currpos = lseek(fd,0,SEEL_CUR)
文件偏移量可以大于文件长度,在这种情况下,下次对该文件的读写将会形成空洞,并用0填充,但是对于空洞部分不占用磁盘块。

6、read函数

#include <unistd.h>ssize_t read(int filedes, void *buf, size_t nbytes);
描述:根据文件描述符读取文件,read成功,返回读到的字节数。

7、write函数

#include <unistd.h>ssize_t write(int filedes, const void *buf, size_t nbytes);
描述:根据文件描述符往文件里写,对于普通文件,写从当前偏移处开始,若打开指定了O_APPEND选项,则文件偏移量设置在文件的结尾处。

8、pread和pwrite函数

#include <unistd.h>ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset);ssize_t pwrite(int filedes, const void *buf, size_t nbytes, off_t offset);
描述:相当于顺序执行lseek和read或者write操作,但是这两个操作是原子操作。

9、dup和dup2函数 

#include <unistd.h>int dup(int filedes);int dup2(int filedes, int filedes2);

描述:复制文件描述符,dup使用当前可用文件描述符表中的最小值引用需要复制文件描述符的文件。dup2使filedes2指定新描述符的数值。如果filees已经打开,则先将其关闭。若filedes2==fildes,则返回filedes2,但是不关闭它。

10、sync、fsync和fdatasync函数

#include <unistd.h>int fsync(int filedes);int fdatasync(int filedes);void sync(void);
描述:sync将所有的块缓冲区排入写队列然后返回,不等待实际磁盘写结束。

fsync只对指定的filedes文件描述符起作用,并且等待磁盘操作结束。

11、fcntl函数

#include <fcntl.h>int fcntl(int filedes, int cmd, /* int arg*/);
描述:改变打开文件的性质。包括:

  1. 复制一个现有的文件描述符
  2. 获得/设置文件描述符
  3. 获得/设置文件状态标记
  4. 获得/设置异步I/O所有权
  5. 获得/设置记录锁

其中cmd具有以下选项:

  • F_DUPFD 赋值文件描述符filedes,返回新的可用文件描述符中的最小值。新的描述符与filedes共享同一文件表项,但是新的描述符在进程表里有自己的文件描述符标志,其FD_CLOEXEC文件描述符标志被清除。
  • F_GETFD 返回文件描述符
  • F_SETFD 设置文件描述符,新的参数按照第三个参数设置
  • F_GETFL 返回文件状态标志
  • F_SETFL 设置文件状态标志
  • F_GETOWN 返回当前接收SIGIO和SIGURG信号的进程ID或者进程组ID
  • F_SETOWN 设置当前接收SIGIO和SIGURG信号的进程ID或者进程组ID
若出错,所有命令都返回-1
12、ioctl函数
使用很少,不介绍
13、其他
用于I/O的数据结构,内核使用3中数据结构表示打开的文件
(1)打开文件描述符表。每个进程的在进程表里都会有一个记录项,记录项里包含了一张打开文件描述符表,每个描述符占用一项。每个文件描述符项包括
  1. 文件描述符标志(close_on_exec)
  2. 指向一个文件表项的指针
(2)文件表。内核为所有打开文件维持一张文件表,每个文件表项包括:
  1. 文件状态标志(读、写、添加、同步和非阻塞等)
  2. 当前文件偏移量
  3. 指向该文件v节点表项的指针
(3)v节点。每个打开文件都有一个v节点,v节点包括文件类型和对此文件进行各种操作函数的指针。例如:文件所有者、文件长度、文件所在设备、指向文件实际数据库块在磁盘所在位置的指针。
它们之间的关系如下:


习题答案:3.1.系统调用没有缓冲机制
3.2.
3.3.
3.4.
3.5.第一条命令是将命令 输出重定向到文件outfile,然后把标准出错重定向至标准输出。
3.6.




0 0
原创粉丝点击