同步管道访问以进行双向读/写

时间:2017-03-20 15:30:11

标签: c linux embedded-linux

我有一段遗留代码,我将某些逻辑委托给子进程。要求是父级写入管道并且子级读取它。在阅读之后,孩子将东西写入新管道并且父母从中读取。

在下面的代码中,函数send()由父进程中的专用线程定期调用。

LaunchWorker()确保子进程仅在第一次调用时进行分叉。

1)我无法弄清楚如何关闭两个描述符的读写端,以便在每次写操作时刷新写入管道的旧数据。 2)还有两个描述符需要两次调用pipe()吗?

任何使此代码有效的输入将不胜感激。 谢谢!

typedef struct
{
    WebClient* wc; // user defined class
    string url;
    string data;
    size_t dataLen;
    DownloadObserver* downloadCallback; // user defined class
    string* token;
}Payload;

PayLoad pl;

static pid_t worker_pid = 0;
int fd1[2];
int fd2[2];

bool done = false;

void LaunchWorker()
{
    if (worker_pid != 0)
    {
        return;
    }
    pipe(fd1);
    pipe(fd2);

    worker_pid = fork();

}

void send()
{
    //populate pl;

    LaunchWorker();

    if (worker_pid == 0)
    {
        while(true)
        {
            close(fd1[1]);
            close(fd2[0]);

            int cr = read(fd1[0], &pl, sizeof(Payload));
            if (cr > 0)
            {
                // Upload some data to a remote http endpoint - uses libcurl
                //if upload success, done = true

                int cw = write(fd2[1], &done, sizeof(bool));
                if (cw > 0)
                {
                    // success
                }
                else
                {
                    // failure
                }
            }
            else
            {
                // failure
            }
        }
    }
    else if (workper_pid > 0)
    {
        close(fd1[0]);
        close(fd2[1]);
        int pw = write(fd1[1], &pl, sizeof(Payload));
        if (pw > 0)
        {
            int pr = read(fd2[0], &done, sizeof(bool));
            if (pr > 0) 
            {
                // do something with value read
            }
            else
            {
                // failure
            }
        }
        else
        {
            failure
        }
    }
}

1 个答案:

答案 0 :(得分:0)

首先,您需要在fork之后立即关闭管道的未使用端,因此父级应该关闭fd1的读取结束和fd2的写入结束,子应该关闭写入fd1的结束和fd2的读取结束。如果不这样做,完成后管道将不会关闭。

然后,当你想要停止一切时,我会让每个管道的编写器关闭管道的写入端。即

  • parent关闭写入fd1的结尾
  • 孩子在fd1上阅读eof并关闭它
  • child关闭fd2的写入结束
  • parent在fd2上读取eof并关闭它。

如果孩子开始关闭,反之亦然。

最后,父进程应发出wait系统调用以收集子进程的退出结果。

是的,你确实需要两个管道。管道是单向的。