我正在使用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);
}dummy.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;
}我有一种挥之不去的感觉,那就是我还不太明白利布夫管子的意义。
发布于 2013-02-07 22:06:55
我已经找到了解决方案:
我有错误的标志,他们应该是,而不是需要在uv_spawn之后调用UV_CREATE_PIPE | UV_READABLE_PIPE uv_read_start。我假设没有数据丢失的可能性,因为uv_run还没有被调用。
dummy的所有输出一次到达,而不是分成三个块(就像在命令行上一样)。dummy.c中的fflush修复了此问题。spawn_test:
#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);
}dummy.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;
}发布于 2013-07-29 01:27:24
看看他们如何在libuv单元测试libuv/test/test-stdio-over-pipes.c中做到这一点。
对于孩子的标准输出,不要调用uv_pipe_open
UV_CREATE_PIPE | UV_READABLE_PIPE
在Windows上还有一个issue,其中uv_spawn可能返回零,即使它遇到了错误,在这些情况下,您需要检查process.spawn_error,它只存在于Windows上。
https://stackoverflow.com/questions/14751504
复制相似问题