本文共 2684 字,大约阅读时间需要 8 分钟。
在 Linux 系统中,文件 I/O 是操作系统最基础的功能之一。程序与文件交互的方式主要有两种:文件 I/O 和 标准 I/O。这两种方式各有特点,理解它们的区别对于高效编程至关重要。
文件 I/O 是一种不带缓存的操作方式。每次调用 read 或 write 时,都直接执行系统调用,操作速度非常快。这种方式不适合大量数据处理,因为频繁的系统调用会增加开销。
标准 I/O 是 ANSI C 标准库中的实现,带有缓存机制。库函数如 fopen、fclose 等会在需要时执行实际的文件操作,减少了系统调用的频率。适用于大部分常规文件操作。
文件描述符是内核用来标识打开文件的关键结构。每个进程打开的文件都有一个唯一的描述符(非负整数)。以下是文件描述符的重要性和用法:
文件描述符的常用值:
这些值是 POSIX 标准定义的,通常由 <unistd.h> 中的宏定义表示。
文件 I/O 的核心操作包括 open、close、read、write 和 lseek。这些函数直接与内核交互,适合需要低延迟和高效率的场景。
open 函数用于打开或创建文件,返回文件描述符。函数参数包括文件路径和操作模式。常见模式选项有:
O_RDONLY:只读模式O_WRONLY:只写模式O_RDWR:读写模式O_CREAT:创建文件O_TRUNC:截断文件O_APPEND:追加模式read 从文件中读取数据,返回读取的字节数。write 向文件中写入数据,返回写入的字节数。lseek 用于定位文件的当前位置,支持三种定位方式:
SEEK_SET:从文件开始位置SEEK_CUR:从当前位置SEEK_END:从文件末尾Linux 支持文件空洞(空文件中存在逻辑空隙),通过 lseek 定位到空洞位置后写入数据,中间的空洞部分读取时会返回 0。
为了保证文件操作的原子性,Linux 提供了 pread 和 pwrite 函数。这些函数确保在定位和读写操作期间,其他进程无法干扰,避免数据竞争。
dup 和 dup2 用于复制文件描述符。dup 返回当前可用最小的描述符,而 dup2 允许指定特定描述符,可能需要先关闭目标描述符。
int main() { int fd = open("file.txt", O_RDWR); int new_fd = dup(fd); close(fd); // new_fd 继续使用原文件} int main() { int fd = open("file.txt", O_RDWR); int new_fd = dup2(fd, 5); close(5); // new_fd 和 5 都指向同一文件} fcntl 用于改变文件描述符的属性,包括文件状态标志和锁设置。常见用途包括设置非阻塞模式和获取文件状态。
int main() { int flags; if (fcntl(STDIN_FILENO, F_GETFL) == -1) { perror("fcntl F_GETFL"); exit(1); } flags |= O_NONBLOCK; if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1) { perror("fcntl F_SETFL"); exit(1); } // 现在 STDIN_FILENO 是非阻塞的} /dev/fd 提供了对标准输入、输出和错误的便捷访问。通过 /dev/fd/0 等路径,可以复制现有的文件描述符,避免了命令行特殊处理。
通过 readdir 和 lstat 函数,可以遍历目录并统计普通文件数量。递归处理子目录,并排除 . 和 ..。
int count(char *root) { DIR *dp = opendir(root); if (dp == NULL) { perror("opendir"); exit(1); } int n = 0; while ((struct dirent *item = readdir(dp)) != NULL) { if (strcmp(item->d_name, ".") == 0 || strcmp(item->d_name, "..") == 0) { continue; } struct stat statbuf; if (lstat(item->d_name, &statbuf) == -1) { perror("lstat"); exit(1); } if (S_ISREG(statbuf.st_mode)) { n++; } else if (S_ISDIR(statbuf.st_mode)) { n += count(item->d_name); } } closedir(dp); return n;} 文件 I/O 是 Linux 系统操作的核心,理解 open、read、write 等函数的使用,能够有效地进行文件操作。通过合理使用文件描述符和同步机制,可以确保文件操作的高效和安全。
转载地址:http://ptavz.baihongyu.com/