write和read命令中的通道号指南
1.文件描述符(通道号)的概念
文件描述符是操作系统分配给已打开文件或 I/O 资源的整数标识符。
每个进程默认打开三个标准文件描述符:
0: 标准输入(stdin,只读)
1: 标准输出(stdout,只写)
2: 标准错误(stderr,只写)
2.如何使用文件描述符
打开文件
通过 open() 系统调用获取文件描述符:
c
#include <fcntl.h>
int fd = open("filename", O_RDWR); // 返回新的文件描述符(如 3,4,...)
模式需匹配操作(O_RDONLY, O_WRONLY, O_RDWR)。
读写操作
write 命令:向指定文件描述符写入数据。
c
ssize_t write(int fd, const void *buf, size_t count);
示例:向文件描述符 1(标准输出)写入数据:
c
write(1, "Hello\n", 6); // 输出 "Hello" 到终端
read 命令:从文件描述符读取数据。
c
ssize_t read(int fd, void *buf, size_t count);
示例:从文件描述符 0(标准输入)读取数据:
c
char buffer[100];
read(0, buffer, 100); // 从终端读取输入
3.关键注意事项
权限匹配
确保文件以正确的模式打开(读/写/追加)。
错误处理
检查系统调用返回值:
c
int fd = open("file.txt", O_RDONLY);
if (fd == -1) {
perror("open failed"); // 输出错误原因
exit(1);
}
关闭描述符
使用 close(fd) 释放资源,避免泄漏。
文件描述符限制
系统对每个进程的文件描述符数量有限制(可通过 ulimit -n 查看)。
4.示例代码(C语言)
c
#include <fcntl.h>
#include <unistd.h>
int main() {
// 打开文件,获取文件描述符
int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
if (fd == -1) {
perror("Error opening file");
return 1;
}
// 写入数据
char *msg = "Hello World";
write(fd, msg, 11);
// 重置文件偏移到开头
lseek(fd, 0, SEEK_SET);
// 读取数据
char buf[100];
ssize_t bytes_read = read(fd, buf, sizeof(buf));
if (bytes_read > 0) {
write(1, buf, bytes_read); // 输出到标准输出
}
close(fd); // 关闭文件
return 0;
}
5.其他场景
网络套接字
套接字通过 socket() 创建后,会返回一个文件描述符,用法与文件类似:
c
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
read(sockfd, buffer, sizeof(buffer)); // 从网络读取数据
管道(Pipe)
管道通过 pipe(int fds[2]) 创建两个文件描述符:
fds[0] 用于读,fds[1] 用于写。
常见问题
Q: 文件描述符与端口号的区别?
文件描述符是进程内资源标识符,端口号是网络通信中应用的逻辑地址。
Q: 子进程会继承父进程的文件描述符吗?
是的,但可通过 fcntl(fd, F_SETFD, FD_CLOEXEC) 设置关闭继承。
Q: 如何查看进程占用的文件描述符?
在 Linux 中,查看 /proc/<PID>/fd/ 目录。