文件I/O
3.2 文件描述符
  对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数。
  UNIX系统shell把文件描述符0与进程的标准输入关联,1与标准输出关联,2与标准错误关联
通常 把0,1,2 这三个幻数替换成常量 STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO
- 0 标准输入
- 1 标准输出
- 2 标准错误输出
3.3 函数open和openat
1 | #include <fcntl.h> |
path 参数是要打开或创建文件的名字。oflag参数 用来说明该函数的多个选项。
有以下一个或多个常亮进行 “或”运算构成oflag参数 (这些常量定义在<fcntl.h>)
下面这些常量是必须的
- O_RDONLY Open for reading only.
- O_WRONLY Open for writing only.
- O_RDWR Open for reading and writing.
- O_EXEC Open for execute only.
- O_SEARCH Open for search only(applies to directories).
这5个常量中必须指定一个且只能指定一个。还有一些常量是可选的(慢慢补充)
- O_APPEND 每次写都追加到文件末尾
- O_CLOEXEC
- O_CREAT 若此文件不存在则创建它,用mode指定该文件的访问权限位
- O_TRUNC 如果此文件存在,并且为只写或读-写成功打开,则将其长度截断为0
3.6 函数lseek
1 | #include <unistd.h> |
whence 参数
- whence是 SEEK_SET,将文件偏移量设置为据文件开始处offset个字节
- whence是 SEEK_CUR,将文件偏移量设置为当前值加上offset,offset可为正或负
- whence是 SEEK_END,将文件偏移量设置为文件长度加上offset,offset可为正或负
在比较lseek的返回值时要谨慎,不要测试它是否小于0,而应该测试是否等于-1
1 | #include "apue.h" |
3.7 函数read
1 | //read 函数从打开的文件中读取数据 |
3.8 函数write
调用write函数向打开的文件写数据
1 | #include <unistd.h> |
write 出错的一个常见原因是磁盘已写满 或者超过了一个给定进程的文件长度限制
普通文件 写操作从当前文件偏移量开始。打开文件时指定了O_APPEND选项(O_APPEND每次写都追加到文件末尾),
每次写操作将文件偏移量设置在文件的当前结尾处,在一次写成功后,该文件偏移量增加实际写的字节数
3.9 I/O的效率
1 | //只使用read 和 write函数 复制文件 |
3.11 原子操作
- 追加文件时如果使用lseek设置文件偏移量到末尾 然后使用write函数写入文件,会出现问题.
- 有两个进程的话 可能会发生覆盖数据的情况
UNIX系统为这样的操作提供了一种原子操作,即在打开文件时时设置O_APPEND标志,使得进程每次write时都将文件偏移量设置到文件末尾处,也就不需要lseek函数。
- 函数pread和pwrite
原子定位读和原子定位写1
2
3#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
- 参数:
- fd: 文件描述符
- buf: 文件缓冲区
- nbytes: 预计读或写的数据字节数
- offset: 文件偏移
- 返回:
- 成功: pread返回读到的字节数,write返回已写的字节数
- 失败: 返回-1
调用pread/pwrite相当于先调用lseek再调用read/write,但又与这种调用有所区别
- 调用pread/pwrite时无法中断其定位读/写操作
- 不更新当前文件偏移量
3.12 dup和dup2函数(未更新完)
用来复制文件描述符
1 | #include <unistd.h> |
- 参数:
- fd: 描述符的值
- fd2: 新的描述符的值。
- 返回:
- 成功: 返回新的文件描述符
- 失败: 返回-1
如果 fd == fd2 则返回fd2的文件描述符,不关闭它。否则fd2的FD_CLOEXEC文件描述符标志被清除,这样fd2在进程调用exec时是打开状态
返回的新的文件描述符与参数fd共享同一个文件表项
3.13 sync,fsync,fdatasync 函数
函数原型
1 | #include <unistd.h> |
- sync: 将所有修改过的块缓存写入到队列,然后返回
- fsync: 只针对由文件描述符fd指定的一个文件起作用,等待磁盘写操作完成后才结束(waits for the disk writes to complete before returning)。可用于数据库这样的应用程序
- fdatasync: 除了数据部分,还会同步更新文件属性
3.14 fcntl函数
1 | // 改变已打开的文件属性 |