一、文件描述符介绍
每个进程都有一张文件描述符的表,程序运行起来后标准输入、标准输出、标准错误输出设备是默认打开的,对应的文件描述符 0、1、2
记录在表中
在打开其他文件时,系统会返回该进程文件描述符表中最小可用的文件描述符,并将此文件描述符记录在表中
Linux 中一个进程最多只能打开 NR_OPEN_DEFAULT
(1024)个文件,故当文件不再使用时应及时调用 close()
函数关闭文件,释放文件描述符资源
二、int dup(int oldfd);
1. 复制文件描述符
新的文件描述符是调用进程文件描述符表中最小可用的文件描述符,最终 oldfd 和新的文件描述符指向同一个文件,分派最小文件描述符:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
int fd1, fd2;
fd1 = open("1.txt", O_CREAT|O_WRONLY, 0666);
fd2 = dup(fd1); // 通过 fd1 复制 fd2, 最终 fd1 和 fd2 都指向 1.txt
printf("fd1 ============== %d\n", fd1);
printf("fd2 ============== %d\n", fd2);
char *buf1 = "this is a test for fd1\n";
char *buf2 = "this is a test for fd2\n";
write(fd1, buf1, strlen(buf1));
write(fd2, buf2, strlen(buf2));
close(fd1); // 关闭文件描述符,两个都需要关闭
close(fd2);
return 0;
}
2. 文件描述符重定向
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd1, fd2;
fd1 = open("1.txt", O_CREAT|O_WRONLY, 0666);
printf("fd1 ============== %d\n", fd1);
// 描述符 1 默认指向标准输出(显示屏),关闭该描述符就空闲了,就不再指向标准输出,成为最小可用文件描述符
close(1);
// fd1, fd2 都指向 1.txt,系统会给 fd2 分配最小可用的文件描述符,即 fd2 = 1
fd2 = dup(fd1);
// printf() 最终调用 write(1,xxx),默认文件描述符 1 指向标准输出,所以 printf() 内容默认显示到屏幕
// 现在文件描述符 1 指向 1.txt,所以此时 printf() 的内容不会打印到屏幕上,而是写入文件 1.txt
printf("fd2 ============== %d\n", fd2);
close(fd1);
close(fd2);
return 0;
}
三、int dup2(int oldfd, int newfd);
功能和 dup()
完全一样,但是 dup2()
复制出来的新文件描述符可以指定任意一个合法的数字
如果指定的数字已经被占用(和某个文件有关联),此函数会自动 close()
断开这个数字和那个文件的关联,再来使用这个合法数字
这两个系统调用都是用来复制一个文件描述符,使新文件描述符和旧文件描述符标识同一个文件。操作这两个文件描述符的任何一个,都能操作所对应的文件