9. 进阶输入输出 - <fcntl.h>
和 <unistd.h>
在高级的 C 语言编程中,处理文件描述符和执行文件控制操作是常见的任务。通过深入理解文件描述符以及如何执行文件控制,我们可以提高程序对文件操作的效率和灵活性。下面将详细讲解文件描述符的基本操作和文件控制的使用。
9.1. 文件描述符
文件描述符是应用程序与操作系统文件接口的桥梁。每个被打开的文件都关联着一个文件描述符,通常以整数表示。文件描述符充当了文件对象的标识,使操作系统能够管理和跟踪对文件的访问。
- 作用:管理文件操作的句柄,用于读写打开的文件。
- 特点:
- 整数表示:通过整数标识文件和其他 I/O 资源(如套接字)。
- 自动分配:文件打开时由操作系统自动分配。
- 标准描述符:常见如标准输入(0)、标准输出(1)、标准错误(2)。
- 基础操作示例:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 打开文件以只读模式,返回文件描述符
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
char buffer[100];
// 读取文件中的内容
ssize_t bytesRead = read(fd, buffer, sizeof(buffer) - 1);
if (bytesRead == -1) {
perror("read");
close(fd);
return 1;
}
buffer[bytesRead] = '\0'; // 确保缓冲区以 NULL 终止
// 输出读取的内容
printf("Content: %s\n", buffer);
// 关闭文件描述符
if (close(fd) == -1) {
perror("close");
return 1;
}
return 0;
}
- 文件描述符操作:
- open: 打开一个文件以获得文件描述符。
- read: 从文件描述符中读取数据。
- write: 向文件描述符中写入数据。
- close: 关闭文件描述符以释放资源。
9.2. 文件控制操作
文件控制操作允许程序对文件描述符的行为进行更细粒度的操作和设置,如状态标志、更改文件属性等。
-
文件状态获取和设置:
fcntl
- 用于获取和设置文件描述符的状态和属性。
- 通过
fcntl
可以修改文件描述符为非阻塞模式。
-
非阻塞 I/O 示例:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
// 获取当前文件描述符的标志
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
perror("fcntl");
close(fd);
return 1;
}
// 设置文件描述符为非阻塞模式
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl");
close(fd);
return 1;
}
char buffer[100];
ssize_t bytesRead = read(fd, buffer, sizeof(buffer) - 1);
if (bytesRead == -1) {
perror("read");
close(fd);
return 1;
}
buffer[bytesRead] = '\0';
printf("Non-Blocking Content: %s\n", buffer);
if (close(fd) == -1) {
perror("close");
return 1;
}
return 0;
}
- 非阻塞 I/O:
- 非阻塞模式下的文件描述符允许程序在资源不可用时立即继续执行,而不被阻塞。
- 使用
fcntl
能有效将文件描述符修改为非阻塞状态,实现对 I/O 操作的更灵活控制。
通过深入了解和应用这些文件描述符基础操作和高级文件控制技巧,可以更有效地管理对文件的输入和输出,提高程序的效率和灵活性。