gpt4 book ai didi

使用 libuv 捕获子进程的标准输出

转载 作者:太空狗 更新时间:2023-10-29 16:53:48 32 4
gpt4 key购买 nike

我正在使用 libuv。我读过 http://nikhilm.github.com/uvbook/processes.html并且仍然无法弄清楚如何捕获子进程的标准输出,以便它在父进程中可用(但不能代替父进程的标准输入)。

我的代码目前是:

#include <stdio.h>
#include <stdlib.h>
#include "../../libuv/include/uv.h"

uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
uv_pipe_t apipe;

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

uv_buf_t alloc_buffer(uv_handle_t *handle, size_t len) {
printf("alloc_buffer called\n");
uv_buf_t buf;
buf.base = malloc(len);
buf.len = len;
return buf;
}

void read_apipe(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
printf("read %li bytes from the child process\n", nread);
}

int main(int argc, char *argv[]) {
printf("spawn_test\n");
loop = uv_default_loop();

char* args[3];
args[0] = "dummy";
args[1] = NULL;
args[2] = NULL;

uv_pipe_init(loop, &apipe, 0);
uv_pipe_open(&apipe, 0);

options.stdio_count = 3;
uv_stdio_container_t child_stdio[3];
child_stdio[0].flags = UV_IGNORE;
child_stdio[1].flags = UV_INHERIT_STREAM;
child_stdio[1].data.stream = (uv_stream_t *) &apipe;
child_stdio[2].flags = UV_IGNORE;
options.stdio = child_stdio;

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

uv_read_start((uv_stream_t*)&apipe, alloc_buffer, read_apipe);
if (uv_spawn(loop, &child_req, options)) {
fprintf(stderr, "%s\n", uv_strerror(uv_last_error(loop)));
return 1;
}

return uv_run(loop, UV_RUN_DEFAULT);
}

虚拟.c:

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

int main() {
printf("child starting\n");
sleep(1);
printf("child running\n");
sleep(2);
printf("child ending\n");
return 0;
}

我有一种挥之不去的感觉,我还不太明白 libuv 管道的意义。

最佳答案

我找到了解决方案:

  1. 我有错误的标记,它们应该是 UV_CREATE_PIPE | UV_READABLE_PIPE 不是 UV_INHERIT_STREAM
  2. 我需要在 uv_spawn 之后调用 uv_read_start。我假设没有数据丢失的可能性,因为尚未调用 uv_run。
  3. 以上两个修复显示了 dummy 的所有输出同时到达,而不是分成三 block (就像在命令行上那样)。 dummy.c 中的 fflush 解决了这个问题。

生成测试:

#include <stdio.h>
#include <stdlib.h>
#include "../../libuv/include/uv.h"

uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
uv_pipe_t apipe;

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

uv_buf_t alloc_buffer(uv_handle_t *handle, size_t len) {
printf("alloc_buffer called, requesting a %lu byte buffer\n");
uv_buf_t buf;
buf.base = malloc(len);
buf.len = len;
return buf;
}

void read_apipe(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
printf("read %li bytes in a %lu byte buffer\n", nread, buf.len);
if (nread + 1 > buf.len) return;
buf.base[nread] = '\0'; // turn it into a cstring
printf("read: |%s|", buf.base);
}

int main(int argc, char *argv[]) {
printf("spawn_test\n");
loop = uv_default_loop();

char* args[3];
args[0] = "dummy";
args[1] = NULL;
args[2] = NULL;

uv_pipe_init(loop, &apipe, 0);
uv_pipe_open(&apipe, 0);

options.stdio_count = 3;
uv_stdio_container_t child_stdio[3];
child_stdio[0].flags = UV_IGNORE;
child_stdio[1].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
child_stdio[1].data.stream = (uv_stream_t *) &apipe;
child_stdio[2].flags = UV_IGNORE;
options.stdio = child_stdio;

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

if (uv_spawn(loop, &child_req, options)) {
fprintf(stderr, "%s\n", uv_strerror(uv_last_error(loop)));
return 1;
}
uv_read_start((uv_stream_t*)&apipe, alloc_buffer, read_apipe);

return uv_run(loop, UV_RUN_DEFAULT);
}

虚拟.c:

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

int main() {
printf("child starting\n");
fflush(stdout);
sleep(1);
printf("child running\n");
fflush(stdout);
sleep(2);
printf("child ending\n");
fflush(stdout);
return 0;
}

关于使用 libuv 捕获子进程的标准输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14751504/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com