文件描述符标志
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件描述符标志相关的知识,希望对你有一定的参考价值。
文件描述符标志(目前就只有一个close-on-exec):
它仅仅是一个标志,当进程fork一个子进程的时候,在子进程中调用了exec函数时就用到了这个标志。意义是执行exec前是否要关闭这个文件描述符。
close-on-exec是一个进程所有文件描述符(文件句柄)的位图标志,每个比特位代表一个打开的文件描述符的标志位,用于确定在调用系统调用exec()时是否需要关闭文件的句柄。当一个进程使用fork()函数创建了一个子进程时,通常在该子进程中调用execve()函数来加载执行另一个新的程序。此时子程序讲完全被新程序替换掉,并在子进程中开始执行新程序。若一个文件描述符在close-on-exec中的对应比特位被设置,那么在执行execve()时,该描述符将被关闭,否则该描述符将始终处于打开的状态,也就是说close-on-exec的默认状态是没有被设置的。
close-on-exec标志由如下用途:
1. 如果调用了exec(),应该关闭指定的套接字。
2. 一般会调用exec执行另一个程序,此时会用全新的程序替换子进程的正文、数据、堆和栈等数据。此时保存文件描述符的变量当然也不存在了,我们就无法关闭无用的文件描述符了。所以通常我们会fork进程后在子进程中执行close关掉无用的文件描述符,然后在执行exec。
例:父进程代码
/* Parent Process */ #include <fcntl.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <sys/wait.h> int main() { int fd = open("test.txt", O_RDWR | O_APPEND); if(fd == -1) { printf("the file test.txt open failed! the fd = %d\\n", fd); execl("/bin/touch", "touch", "test.txt", (char *)NULL); return 0; } else { printf("the file test.txt open success! the fd = %d\\n", fd); } printf("fork...\\n"); //什么也不写,相当于默认fcntl(fd, F_SETFD, 0),即用execl执行子进程时 //不打开“执行时关闭”标志位FD_CLOEXEC,此时子进程可以向test.txt写入字符串 //下面的三句话控制父进程的文件描述符在子进程中是否被关闭 //fcntl(fd, F_SETFD, 1); int flags = fcntl(fd, F_FETFD); fcntl(fd, F_SETFD, flags | FD_CLOEXEC); char *str = "The Parent Process Writted!\\n"; pid_t pid = fork(); if(pid == 0) { printf("***execl child***\\n"); execl("child", "./child", &fd, NULL); printf("*****************\\n"); } //等待子进程结束 wait(NULL); ssize_t write_bytes = write(fd, (void *)str, strlen(str)); if(write_bytes == -1) { printf("The Parent Process Write To fd: %d Failed!\\n", fd); } close(fd); return 0; }
子进程代码:
/* Child Process */ #include <stdio.h> #include <unistd.h> #include <string.h> int main(int argc, char *argv[]) { printf("argc = %d\\n", argc); if(argv[1] == NULL) { printf("There is no Parameter!\\n"); return 0; } int fd = *argv[1]; printf("child fd = %d\\n", fd); char *str = "Child Process Writted!\\n"; ssize_t write_bytes = write(fd, (void *)str, strlslen(str)); if(write_bytes == -1) { printf("The child Process write To fd: %d Failed\\n", fd); } close(fd); return 0; }
两段代码通过fcntl函数设置fd的文件描述标志位,控制父进程中的文件描述符在子进程中是否被关闭。同时注意,这里的FD_CLOEXEC标识符,只针对exec系列的函数有效,如果子进程直接在当前例程的pid == 0的判断里面write,而不是通过execl一个新的例程write文件,这是FD_CLOEXEC标识符是不起作用的。
转载:http://www.cnblogs.com/stemon/p/5242547.html
以上是关于文件描述符标志的主要内容,如果未能解决你的问题,请参考以下文章
Java 虚拟机原理Class 字节码二进制文件分析 四 ( 字段表数据结构 | 字段表详细分析 | 访问标志 | 字段名称 | 字段描述符 | 属性项目 )
如何使用带有 Ninja 生成器的 CMake 将修饰符标志传递给存档文件(ar)