Rob*_*ert 1 c unix fork pipe waitpid
希望是一个简单的问题.我正在尝试同时学习fork(),pipe()和waitpid()并遇到一些问题.
if (pipe(myout)<0 || pipe(myin)<0 || pipe(myerr)<0) { perror("Couldn't make pipes"); return; }
int childpid=fork();
if (childpid==0) { //child
fdopen(myout[1], "w");
fdopen(myin[1], "r");
fdopen(myerr[1], "w");
dup2(myout[1], 1);
dup2(myin[1], 0);
dup2(myerr[1], 2);
printf("This should be seen\n");
fclose(stdout); fclose(stdin); fclose(stderr);
sleep(10);
_exit(0);
} else { //parent, wait on child
printf("parent, monitoring\n");
sim_out=fdopen(myout[0], "r");
sim_in=fdopen(myin[0], "w");
sim_err=fdopen(myerr[0], "r");
printf("have my fds\n");
int status;
do {
int ch;
if (read(myout[0], &ch, 1)>0)
write(1, &ch, 1);
else printf("no go\n");
waitpid(childpid, &status, WNOHANG);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
Run Code Online (Sandbox Code Playgroud)
我越来越:
父母,监视我的fds T.
在程序退出之前 - 也就是说,循环只运行一次.我在下面有一个检查,它正在WIFEXITED(),因此该过程应该正常退出.但困扰我的是,在发生这种情况之前会有一个睡眠(10),这会立即发生 - 更不用说子进程在剩余的等待时间内保持运行状态.
我明显地从根本上误解了一些东西.我的期望是父循环会阻塞,直到它看到孩子的一个角色,读取它,然后检查它是否还活着.我当然不希望waitpid()在孩子还活着的时候设置WIFEXITED.
我哪里错了?
我想我可以看到几个问题.我会尝试按照外观顺序提及它们.
fork的返回值-1(在这种情况下不会分叉子项).fdopen泄漏资源的调用(取决于实现; RHEL4上的泄漏).他们返回一个FILE*你可以在其中使用的东西fwrite,然后通过fclose对它们进行关闭.但是你抛弃了这个价值.您无需打开管道进行读/写操作.管道在创建时适用于此.close (myin [1]); myin [1] = -1; close (myout [0]); myout [0] = -1; close (myerr [0]); myerr [0] = -1;dup2技术上是罚款,所有Linux版本我知道,但它是习惯使用管道的第一FD阅读和其他写作.因此,你的dup2s最好改为dup2 (myin [0], STDIN_FILENO); dup2 (myout [1], STDOUT_FILENO); dup2 (myerr [1], STDERR_FILENO);close (myin [0]); myin [0] = -1; close (myout [1]); myout [1] = -1; close (myerr [1]); myerr [1] = -1;status孩子的退出代码可能未初始化.但waitpid尚未被召唤.您应该检查waitpid退出代码,而不是评估status它是否返回其他内容childpid.由于现在只打开您实际需要的管道末端,操作系统会为您检测到管道损坏.当孩子这样做时,管道会断裂fclose (stdout).父进程仍然可以继续读取管道中可能存在的所有数据,但之后read将返回零,表示管道已损坏.
因此,你实际上可以免去电话waitpid.你可以简单地等待read返回零.但是,这并非100%等效,因为您的孩子在进入之前关闭管道的末端sleep(导致父项在读取所有数据后继续),而waitpid版本当然只在孩子实际死亡时才进行.
| 归档时间: |
|
| 查看次数: |
3083 次 |
| 最近记录: |