c++ libuv:通过管道的父子进程通信

xzv2uavs  于 2022-12-15  发布在  其他
关注(0)|答案(2)|浏览(143)

我试图写一个程序,一个父进程通过管道从两个子进程接收一些数据。当我有一个子进程时,程序运行良好,父进程从子进程接收数据。但是,当我有两个子进程时,父进程不能从子进程接收数据。下面是我的代码:子进程:test.cpp

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

using namespace std;

int main(int argc, char **argv) {
    if (argc <= 1) {
        printf("params error !\n");
        return -1;
    }
    string index = argv[1];
    if (index.empty()) {
        printf("params error !\n");
        return -1;
    }
    int num = 0;
    string s1 = "fourth stdio! " + index + "\n";
    while (num < 100) {
        num++;
        ssize_t r;

        do
            r = write(3, s1.c_str(), sizeof(s1) - 1);
        while (r == -1);

        fsync(3);
        sleep(1);
    }
    return 0;
}

父进程:main.cpp

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string>
#include <uv.h>

using namespace std;
uv_loop_t *loop;

void on_exit(uv_process_t *req, int64_t exit_status, int term_signal) {
    fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
    uv_close((uv_handle_t *) req, NULL);
}

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
    *buf = uv_buf_init((char *) malloc(suggested_size), suggested_size);
}

void on_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
    if (nread < 0) {
        if (nread != UV_EOF)
            fprintf(stderr, "Read error %s\n", uv_err_name(nread));
        uv_close((uv_handle_t *) client, NULL);
        free(buf->base);
        return;
    }

    char *data = (char *) malloc(sizeof(char) * (nread + 1));
    data[nread] = '\0';
    strncpy(data, buf->base, nread);

    fprintf(stdout, "%s", data);
    free(data);
    free(buf->base);
}

int main() {
    loop = uv_default_loop();

    for (int i = 0; i < 2; i++) {// The variable i controls the number of child processes
        uv_process_t child_req;
        string path = "/home/kanong/code/test_project/test";

        char *args[3];
        args[0] = (char *) path.c_str();
        args[1] = (char *) to_string(i).c_str();
        args[2] = NULL;

        /* ... */
        uv_pipe_t pipe;
        uv_pipe_init(loop, &pipe, 0);
        uv_stdio_container_t child_stdio[4];
        uv_process_options_t options = {0};
        options.stdio_count = 4;
        options.stdio = child_stdio;

        child_stdio[0].flags = UV_IGNORE;
        child_stdio[1].flags = UV_INHERIT_FD;
        child_stdio[1].data.fd = 1;
        child_stdio[2].flags = UV_INHERIT_FD;
        child_stdio[2].data.fd = 2;
        child_stdio[3].flags = (uv_stdio_flags) (UV_CREATE_PIPE | UV_WRITABLE_PIPE);
        child_stdio[3].data.stream = (uv_stream_t *) &pipe;

        options.exit_cb = on_exit;
        options.file = args[0];
        options.args = args;

        int r;
        if ((r = uv_spawn(loop, &child_req, &options))) {
            fprintf(stderr, "%s\n", uv_strerror(r));
            return 1;
        }
        if ((r = uv_read_start((uv_stream_t *) &pipe, alloc_buffer, on_read))) {
            fprintf(stderr, "%s\n", uv_strerror(r));
            return 1;
        }

    }

    return uv_run(loop, UV_RUN_DEFAULT);
}

如何解决这个问题?请帮助.非常感谢.

bfnvny8b

bfnvny8b1#

使用小的struct将每个子级的状态存储在单独的位置:

struct child_process {
        uv_process_t child_req;
        uv_pipe_t pipe;
        std::string num;
} children[CHILDREN_COUNT];

然后主循环只引用children的元素:

for (int i = 0; i < CHILDREN_COUNT; i++) {
        child_process &proc = children[i];
        proc.num = std::to_string(i);
        std::string path = "/home/kanong/code/test_project/test";

        char *args[3];
        args[0] = (char *) path.c_str();
        args[1] = (char *) proc.num.c_str();
        args[2] = NULL;

        /* ... */
        uv_pipe_init(loop, &proc.pipe, 0);
        uv_stdio_container_t child_stdio[4];
        uv_process_options_t options = {0};
        options.stdio_count = 4;
        options.stdio = child_stdio;

        child_stdio[0].flags = UV_IGNORE;
        child_stdio[1].flags = UV_INHERIT_FD;
        child_stdio[1].data.fd = 1;
        child_stdio[2].flags = UV_INHERIT_FD;
        child_stdio[2].data.fd = 2;
        child_stdio[3].flags = (uv_stdio_flags) (UV_CREATE_PIPE | UV_WRITABLE_PIPE);
        child_stdio[3].data.stream = (uv_stream_t *) &proc.pipe;

        options.exit_cb = on_exit;
        options.file = args[0];
        options.args = args;

        int r;
        if ((r = uv_spawn(loop, &proc.child_req, &options))) {
                fprintf(stderr, "%s\n", uv_strerror(r));
                return 1;
        }
        if ((r = uv_read_start((uv_stream_t *) &proc.pipe, alloc_buffer, on_read))) {
                fprintf(stderr, "%s\n", uv_strerror(r));
                return 1;
        }
}

4zcjmb1e

4zcjmb1e2#

在窗口上
1.使管道标志可写
1.子进程每次都必须使用管道调用fflush()

相关问题