linux中,父进程fork出子进程,子进程本身会继承父进程的所有文件描述符。若子进程再调用exec系列函数转化为新的进程实体,其实父进程的描述符对其没有意义。此时文件上只需要设置FD_CLOEXEC即可。
下面是例子说明:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
// 以 r 方式打开文件
FILE *p = fopen("my.txt", "w");
if(p == NULL)
{
printf("File Open Failed !\n");
}else
{
fputs("includehelp", p);
printf("File Open Success !\n");
}
int fd = fileno(p);
printf("fd is %d\n", fd);
int val = fcntl(fd, F_GETFD);
int val2 = val | FD_CLOEXEC;
fcntl(fd, F_SETFD, val2);
int pid = fork();
if(pid > 0)
{
printf("child pid is %d\n", pid);
}
else if(pid == 0)
{
execl("/root/tusong/whiletest/whiletest", "whiletest", NULL, NULL);
}
while(1);
return 0;
}
其中可执行程序whiletest里面是个死循环,不会退出,读者可以自己构造这样的程序。
运行程序,程序名叫做fcntltest2,产生两个进程:
然后查看进程的fd信息,可以看到my.txt这个文件描述符没有继承下去。
将上面的代码做下修改,屏蔽掉代码:fcntl(fd, F_SETFD, val2);
再运行看看情况,如下所示,产生的两个进程号分别是64187,64188,可以看到文件描述符被子进程继承了。
注意,如果fork进程后,没有调用exec,则无论FD_CLOEXEC是否设置,子进程一定会继承父进程的全部文件描述符。