使用管道和epoll与子进程通信

时间:2016-05-22 13:34:39

标签: c linux pipe epoll

我正在编写一个应用程序,它将根据用户输入启动某些进程(fork和exec),并且应该告知用户这些进程中的每个错误(打印一些内部ID +由进程写入stderr的消息)。我也想检测现有流程。我遇到问题,执行execl()命令后无法接收数据。在epoll_wait循环中接收测试数据,但exec调用的进程似乎没有向stderr写任何东西,甚至没有结束(我不知道我是否正确,但我希望管道在它之后可读“#39 ;当进程退出时,s写入结束已经关闭)。一些代码重现了我的问题:

#include <unistd.h>
#include <sys/epoll.h>
#include <stdio.h>
#include <thread>
#include <stdlib.h>
#include <sys/wait.h>

thread_local int epoll;

int do_fork()
{
    int pip[2];
    pipe(pip);
    int pid = fork();
    if (pid == 0)
    {
        dup2(pip[1], STDERR_FILENO);
        close(pip[0]);  
        close(pip[1]);  
        write(STDERR_FILENO, "test data", 10);
        sleep(3);
        //exit(1);
        execl("tr", "tr", NULL); //this process will end immediately and write error on stderr
    }
    else
    {
        printf("PID %d\n", pid);
        close(pip[1]);
        epoll_event ev;
        ev.data.fd = pip[0];
        ev.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP;
        printf("pipe %d\n", pip[0]);
        epoll_ctl(epoll, EPOLL_CTL_ADD, pip[0], &ev);
    }
}

int thread()
{
    epoll_event events[10];
    epoll = epoll_create1(0);

    epoll_event ev;
    ev.data.fd = STDIN_FILENO;
    ev.events = EPOLLIN;
    epoll_ctl(epoll, EPOLL_CTL_ADD, STDIN_FILENO, &ev);

    char buf[1000];
    while(true)
    {
        int r = epoll_wait(epoll, events, 10, -1);
        printf("r = %d\n", r);
        for (int i = 0; i < r; ++i)
        {
            if(events[i].data.fd == STDIN_FILENO)
            {
                int t = read(events[i].data.fd, buf, 1000);
                do_fork();
            }
            else
            {
                printf("event? %d\n", events[i].events);
                printf("pipe %d\n", events[i].data.fd);
                int t = read(events[i].data.fd, buf, 1000);
                printf("t == %d\n", t);
                if(t == -1)
                    printf("errno: %d\n", errno);
                if(events[i].events & EPOLLHUP || t == 0)
                {
                    epoll_ctl(epoll, EPOLL_CTL_DEL, events[i].data.fd, NULL);
                    if(close(events[i].data.fd) == -1)
                        printf("cannot close fd\n");
                }
            }
        }

    }
    return 0;
}

int main()
{
    std::thread t{thread};
    t.detach();
    while(true);
}

0 个答案:

没有答案