fcntl的FD_CLOEXEC标志位与exec族

CLOEXEC:close on exec, not on-fork, 意为如果对描述符设置了FD_CLOEXEC,使用execl执行的程序里,此描述符被关闭,不能再使用它,但是在使用fork调用的子进程中,此描述符并不关闭,仍可使用。
eg:
jamie@jamie-laptop:~$ cat test.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
        int fd,pid;
        char buffer[20];
        fd=open("wo.txt",O_RDONLY);
        printf("%d/n",fd);
        int val=fcntl(fd,F_GETFD);
        val|=FD_CLOEXEC;
        fcntl(fd,F_SETFD,val);

        pid=fork();
        if(pid==0)
        {
                //子进程中,此描述符并不关闭,仍可使用
                char child_buf[2];
                memset(child_buf,0,sizeof(child_buf) );
                ssize_t bytes = read(fd,child_buf,sizeof(child_buf)-1 );
                printf("child, bytes:%d,%s/n/n",bytes,child_buf);

                //execl执行的程序里,此描述符被关闭,不能再使用它
                char fd_str[5];
                memset(fd_str,0,sizeof(fd_str));
                sprintf(fd_str,"%d",fd);
                int ret = execl("./exe1","exe1",fd_str,NULL);
                if(-1 == ret)
                        perror("ececl fail:");
        }       

        waitpid(pid,NULL,0);
        memset(buffer,0,sizeof(buffer) );
        ssize_t bytes = read(fd,buffer,sizeof(buffer)-1 );
        printf("parent, bytes:%d,%s/n/n",bytes,buffer);
}

jamie@jamie-laptop:~$ cat exe1.c

 

系统调用exec族是用来执行一个可执行文件来代替当前进程的执行映像。需要注意的是,该调用并没有生成新的进程,而是在原有进程的基础上,替换原有进程的正文,调用前后是同一个进程,进程号PID不变。但执行的程序变了(执行的指令序列改变了)。因其在执行可执行文件的时候,在可执行文件结束有运行return 0,所以以下程序就不会再执行下边的printf("AH!!!!!/n");

加上FD_CLOEXEC后是关闭文件描述符1,也就是标准输出1,所以ls运行的结果不会显示出来了。

不加FD_CLOEXEC就会打印出ls的运行结果。


#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>

int main(int argc, char **args)
{
        char buffer[20];
        int fd = atoi(args[1]);
        memset(buffer,0,sizeof(buffer) );
        ssize_t bytes = read(fd,buffer,sizeof(buffer)-1);
        if(bytes < 0)
        {
                perror("exe1: read fail:");
                return -1;
        }
        else
        {
                printf("exe1: read %d,%s/n/n",bytes,buffer);
        }
        return 0;
}

jamie@jamie-laptop:~$ gcc -o exe1 exe1.c
jamie@jamie-laptop:~$ gcc -o test test.c
jamie@jamie-laptop:~$ cat wo.txt
this is a test
jamie@jamie-laptop:~$ ./test
3
child, bytes:1,t                               //子进程中可使用fd

exe1: read fail:: Bad file descriptor  //execl调用的程序中不能使用fd
parent, bytes:14,his is a test          //父进程中当然能使用fd

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

extern char **environ;

int main(int argc,char *argv[])
{
    int flag;
    int ret;

    flag = fcntl(1,F_GETFD,0);
    printf("close-on-exec is %d/n",flag);

    fcntl(1,F_SETFD,flag|FD_CLOEXEC);
    flag = fcntl(1,F_GETFD,0);
    printf("close-on-exec is %d/n",flag);

    //system("ls -l");
    ret = execve("/bin/ls",argv,environ);
    if(ret == -1)
    {
        printf("FAULT!/n");
    }
    printf("AH!!!!!/n");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值