Linux/Unix 系统编程 — 文件I/0

尊重作者劳动成果,转载请注明出处,谢谢!

1.概述

所有执行 I/O 操作的系统调用都以文件描述符(一个非负整数)来指代打开的文件,如普通文件、套接字、目录文件、符号链接等。

标准文件描述符:

  • 0:标准输入,POSIX 名称:STDIN_FILENO,stdio 流:stdin
  • 1:标准输出,POSIX 名称:STDOUT_FILENO,stdio 流:stdout
  • 2:标准错误,POSIX 名称:STDERR_FILENO,stdio 流:stderr

执行文件 I/O 操作的主要系统调用:

#include <fcntl.h>
int open (const char *path, int oflag, ... /* mode_t mode */); //打开或创建一个文件,成功返回文件描述符,失败返回 -1
int fcntl (int fd, int cmd, ... /* int arg */); //改变已打开文件的属性

#include <unistd.h>
int close (int fd); //关闭一个打开文件,成功返回,失败返回 -1
ssize_t read (int fd, void *buf, size_t nbytes); //从打开文件中读数据,成功返回读取的字节数,若已到达文件尾则返回 0,失败返回 -1
ssize_t  write (int fd, const void *buf, size_t nbytes); //向打开文件写数据,成功返回写入的字节数,失败返回 -1
off_t lseek (int fd, off_t offset, int whence); //设置文件偏移量,成功返回新的文件偏移量,失败返回 -1

 2.使用 open 函数打开或创建文件

用下列一个或多个常量进行“或”运算构成 open() 函数中的 oflag 参数,这些常量在头文件 <fcntl.h> 中定义:

①文件访问模式

  • O_RDONLY(0):以只读方式打开文件
  • O_WRONLY(1):以只写方式打开文件
  • O_RDWR(2):以读写方式打开文件

如下代码以只读的方式打开 path 指定的文件,返回的文件描述符赋值给变量 fd:

int fd;
fd = open(path, O_RDONLY);

②文件创建标志

  • O_CLOEXEC:把 FD_CLOEXEC 常量设置为文件描述符标志,当该标志打开时,子进程从父进程继承的该文件描述符将被关闭
  • O_CREAT:若文件不存在,则创建它,使用该选项时,需要同时指定 mode 参数(文件访问权限)
  • O_EXCL:如果同时指定了 O_CREAT,而文件已经存在,则出错(errno 为 EEXIST)
  • O_TRUNC:截断已有文件,使其长度为零
  • O_NOCTTY:不要让 path (所指向的终端设备)成为控制终端
  • O_DIRECTORY:如果 path 不是目录,则出错

③文件状态标志

  • O_APPEND:总在文件尾部追加数据
  • O_ASYNC:当 I/O 操作可行时,产生信号通知进程
  • O_SYNC:以同步方式写入文件,使每次 write 等待物理 I/O 操作完成,包括由该 write 操作引起的文件属性更新所需的 I/O
  • O_NONBLOCK:若文件是一个 FIFO、一个块特殊文件或一个字符特殊文件,则此选项的本次打开操作和后序的 I/O 操作设置非阻塞方式

 3.使用 lseek 函数改变文件偏移量

对于每个打开的文件,系统内核会记录其文件偏移量。当文件打开时,会将文件偏移量设置为指向文件的开始,以后每次 read 或 write 时将自动对其进行调整,以指向已读或已写数据后的下一字节。

offset 参数指定了一个以字节为单位的数值,whence 参数则表明应参照哪个位置来解释 offset 参数,whence 参数取值如下:

  • SEEK_SET:从文件头部起始点开始的 offset 个字节
  • SEEK_CUR:相对于当前文件偏移量,将文件偏移量调整 offset 个字节
  • SEEK_END:将文件偏移量设置为起始于文件尾部的 offset 个字节

4.使用 fctnl 函数改变打开文件的属性

fcntl 函数有以下 5 种功能:

  • 复制一个已有的描述符(cmd = F_DUPFD 或 F_DUPFD_CLOEXEC)
  • 获取/设置文件描述符标志(cmd = F_GETFD 或 F_SETFD)
  • 获取/设置文件状态标志(cmd = F_GETFL 或 F_SETFL)
  • 获取/设置异步 I/O 所有权(cmd = F_GETOWN 或 F_SETOWN)
  • 获取/设置记录锁(cmd = F_GETLK、F_SETLK 或 F_SETLKW)
posted @ 2021-01-07 23:03  chenyuxin  阅读(106)  评论(0编辑  收藏  举报