轉自:http://blog.csdn.net/sunlylorn/article/details/6363727
close_on_exec 是一個進程所有文件描述符(文件句柄)的位圖標志,每個比特位代表一個打開的文件描述符,用於確定在調用系統調用execve()時需要關閉的文件句柄(參見include/fcntl.h)。當一個程序使用fork()函數創建了一個子進程時,
通常會在該子進程中調用execve()函數加載執行另一個新程序。此時子進程將完全被新程序替換掉,並在子進程中開始執行新程序。
若一個文件描述符在close_on_exec中的對應比特位被設置,那么在執行execve()時該描述符將被關閉,否則該描述符將始終處於打開狀態。
當打開一個文件時,默認情況下文件句柄在子進程中也處於打開狀態。因此sys_open()中要復位對應比特位。
//執行execve()時該描述符將被關閉
int fd;
fd = open("test.txt",O_RDWR|O_APPEND);
fcntl(fd, F_SETFD, 1);
//執行execve()時該描述符將被打開
int fd;
fd = open("test.txt",O_RDWR|O_APPEND);
fcntl(fd, F_SETFD, 0);
//測試代碼:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/wait.h> #include <string.h> int main() { printf("--------------\n"); pid_t pid; int fd; fd = open("test.txt",O_RDWR|O_APPEND); printf("fd = %d\n",fd); fcntl(fd, F_SETFD, 1); char *s="ooooooooooooooooooo"; pid = fork(); if(pid == 0) execl("ass", "./ass", &fd, NULL); wait(NULL); write(fd, s, strlen(s)); close(fd); return 0; } #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/wait.h> #include <string.h> int main(int argc, char *argv[]) { int fd; int len; printf("argc = %d ",argc); fd = *argv[1]; printf("fd = %d\n",fd); char *s = "zzzzzzzzzzzzzzzzzzz"; len = write(fd, (void *)s, strlen(s)); if(-1 == len) { printf("write fail\n"); } close(fd); return 0; }
fcntl(fd, F_SETFD, 1) 此句將fd的close-on-exec 標志設置為1,開啟此標志。那么當子進程調用execl函數時,execl執行ass,ass是不能向fd內寫入的,因為在調用execl函數之前系統已經講子進程的此文件描述符關閉了。(attention:這里是子進程!)
但是如果將 fcntl(fd, F_SETFD, 1)改為fcntl(fd, F_SETFD, 0),或者直接將此句注釋掉,那么,ass便可以向這個文件描述符中任意添寫東西了~~
PS:如果將fcntl設置為開啟,即設置為1,那么,此文件描述符依然是可以被主進程操作的。