使用fork(), pipe() 实现linux的popen, pclose功能

4 篇文章 0 订阅

为什么要自己实现一个popen\pclose函数功能呢?因为,有时系统popen打开的文件,有时会出现pclose时一直阻塞着,导致整个应用程序无法正常结束,此时使用我们自己实现的popen,则可以获得进程ID,然后通过kill该进程ID来结束popen开启的文件;

FILE*    Popen(const char* commandstr, const char* mode)
{
    pid_t pid;
    int pfd[2];
    int nRet = pipe(pfd); // 创建管道(pfd[0] 读管道,pfd[1] 写管道)
    if (-1 == nRet)
    {
        printf("error: pipe() call fails\n");
        WriteLog(LOG_INFO, "[LogFileMonitor] error: pipe() call fails");
        return NULL;
    }

    pid = fork();
    if (pid < 0)
    {
        printf("error: fork() call fails.\n");
        WriteLog(LOG_INFO, "[LogFileMonitor] error: fork() call fails");
        return NULL;
    }
    else if (pid == 0)
    {
        printf("I am child process, pid = %d\n", getpid());
        WriteLog(LOG_INFO, "[LogFileMonitor] I am child process, pid = %d", getpid());
        // 负责写数据 --- 写管道
        close(pfd[0]);
        if (pfd[1] != STDOUT_FILENO)
        {
            dup2(pfd[1], STDOUT_FILENO); // 标准输出 指向 管道的输出文件描述符
            close(pfd[1]);
        }

        execl(SHELL, "sh", "-c", commandstr, (char *)0);
        _exit(127);
    }
    else
    {
        printf("I am parent process, pid = %d\n", getpid());
        WriteLog(LOG_INFO, "[LogFileMonitor] I am parent process, pid = %d", getpid());
        // 负责读数据 --- 读管道
        close(pfd[1]);
        FILE *fp = NULL;
        if ((fp = fdopen(pfd[0], "r")) == NULL)
        {
            return NULL;
        }
        return fp;
    }
}

int     Pclose(FILE* fp)
{
    //使用非阻塞io
    int flags = 0;
    int nfd = fileno(fp);
    if (flags = fcntl(nfd, F_GETFL, 0) < 0)
    {
        LOG(LERROR) << "fcntl() get failed";
        WriteLog(LOG_ERROR, "[LogFileMonitor] fcntl() get failed");
        return false;
    }

    flags &= ~O_NONBLOCK;
    if (fcntl(nfd, F_SETFL, flags) < 0)
    {
        LOG(LERROR) << "fcntl() set noblock failed";
        WriteLog(LOG_ERROR, "[LogFileMonitor] set noblock failed");
        return false;
    }

    if (fclose(fp) == EOF)
    {
        return -1;
    }

    WriteLog(LOG_INFO, "[LogFileMonitor] Pclose() _exit(128)");
    _exit(128);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值