【发布时间】:2015-04-03 01:05:41
【问题描述】:
我只是想编写一个简单的环回函数,该函数在设置管道并使用 dup2() 复制到标准输入和标准输出后在子进程中运行。但是环回在它试图从管道中读取时挂起。管道的写入端——在父进程中——是一个使用 fputs() 的 C 函数。我知道父进程可以工作,因为如果将子环回函数替换为在 C 中使用 read() 的另一个函数,它就可以工作。
一旦我得到这个工作,我就可以用 exec() 替换环回函数,我希望它可以与用 C++ 编写的程序一起工作。
有很多类似的问题,但是像调用 setvbuf() 这样的解决方案对我不起作用(你可以看到我确实在父环回函数中调用它)。其他提问者直接在管道文件描述符上使用 read() (当我这样做时有效——但我想用 C++ 中的 std::cin 测试它)。
所以主函数看起来是这样的:-
int pipeIn[2]; // To be read by child process
int pipeOut[2]; // To be written by child process
#define PARENT_TO_CHILD_READ_END pipeIn[0]
#define PARENT_TO_CHILD_WRITE_END pipeIn[1]
#define CHILD_TO_PARENT_READ_END pipeOut[0]
#define CHILD_TO_PARENT_WRITE_END pipeOut[1]
int main(int argc, char** argv) {
pipe(pipeIn);
pipe(pipeOut);
pid_t hijo = fork();
if (hijo == 0) {
// CHILD
dup2(PARENT_TO_CHILD_READ_END, STDIN_FILENO);
dup2(CHILD_TO_PARENT_WRITE_END, STDOUT_FILENO);
close(PARENT_TO_CHILD_READ_END);
close(CHILD_TO_PARENT_WRITE_END);
close(PARENT_TO_CHILD_WRITE_END);
close(CHILD_TO_PARENT_READ_END);
Child_plusplus_Loopback();
} else if (hijo == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else {
// PARENT
close(PARENT_TO_CHILD_READ_END);
close(CHILD_TO_PARENT_WRITE_END);
Parent_FILE_Loopback(
PARENT_TO_CHILD_WRITE_END,
CHILD_TO_PARENT_READ_END);
close(PARENT_TO_CHILD_WRITE_END);
close(CHILD_TO_PARENT_READ_END);
wait(NULL);
}
return 0;
}
回送函数如下所示:-
void
Parent_FILE_Loopback(const int outPipe, const int inPipe) {
FILE * toChild = fdopen(outPipe, "w");
FILE * fromChild = fdopen(inPipe, "r");
setvbuf(toChild, NULL, _IONBF, 0);
fputs("Hello", toChild);
const size_t bufferSize(256);
char buffer[ bufferSize ];
fgets(buffer, bufferSize, fromChild);
printf("PARENT : %s\n\n", buffer);
}
void
Child_plusplus_Loopback(void) {
string buffer;
cin >> buffer; // this hangs
string message("CHILD : ");
message += buffer;
cout << message;
}
strace -f 的输出如下所示:-
clone(Process 6989 attached (waiting for parent)
Process 6989 resumed (parent 6988 ready)
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb74e5768) = 6989
[pid 6989] dup2(3, 0 <unfinished ...>
[pid 6988] close(3) = 0
[pid 6989] <... dup2 resumed> ) = 0
[pid 6988] close(6 <unfinished ...>
[pid 6989] dup2(6, 1 <unfinished ...>
[pid 6988] <... close resumed> ) = 0
[pid 6989] <... dup2 resumed> ) = 1
[pid 6988] fcntl64(4, F_GETFL <unfinished ...>
[pid 6989] close(3 <unfinished ...>
[pid 6988] <... fcntl64 resumed> ) = 0x1 (flags O_WRONLY)
[pid 6989] <... close resumed> ) = 0
[pid 6989] close(6 <unfinished ...>
[pid 6988] brk(0 <unfinished ...>
[pid 6989] <... close resumed> ) = 0
[pid 6988] <... brk resumed> ) = 0x848f000
[pid 6989] close(4 <unfinished ...>
[pid 6988] brk(0x84b0000 <unfinished ...>
[pid 6989] <... close resumed> ) = 0
[pid 6988] <... brk resumed> ) = 0x84b0000
[pid 6989] close(5) = 0
[pid 6988] fstat64(4, <unfinished ...>
[pid 6989] fstat64(0, <unfinished ...>
[pid 6988] <... fstat64 resumed> {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
[pid 6989] <... fstat64 resumed> {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
[pid 6988] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
[pid 6989] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
[pid 6988] <... mmap2 resumed> ) = 0xb77d3000
[pid 6989] <... mmap2 resumed> ) = 0xb77d3000
[pid 6988] _llseek(4, 0, <unfinished ...>
[pid 6989] read(0, <unfinished ...>
[pid 6988] <... _llseek resumed> 0xbfefde40, SEEK_CUR) = -1 ESPIPE (Illegal seek)
[pid 6988] fcntl64(5, F_GETFL) = 0 (flags O_RDONLY)
[pid 6988] fstat64(5, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
[pid 6988] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d2000
[pid 6988] _llseek(5, 0, 0xbfefde40, SEEK_CUR) = -1 ESPIPE (Illegal seek)
[pid 6988] munmap(0xb77d3000, 4096) = 0
[pid 6988] write(4, "Hello", 5) = 5
[pid 6989] <... read resumed> "Hello", 4096) = 5
[pid 6988] read(5, <unfinished ...>
[pid 6989] brk(0) = 0x848f000
[pid 6989] brk(0x84b0000) = 0x84b0000
[pid 6989] read(0, 0xb77d3000, 4096) = ? ERESTARTSYS (To be restarted)
[pid 6988] <... read resumed> 0xb77d2000, 4096) = ? ERESTARTSYS (To be restarted)
[pid 6989] --- SIGWINCH (Window changed) @ 0 (0) ---
[pid 6988] --- SIGWINCH (Window changed) @ 0 (0) ---
[pid 6989] read(0, <unfinished ...>
[pid 6988] read(5,
【问题讨论】: