【发布时间】:2021-12-29 00:15:49
【问题描述】:
我正在尝试通过在父程序中分叉子程序来在两个程序之间创建一些通信。
当我单独执行子程序时,它可以工作。这样做的目的是,如果有人在输入 1、2 或 3 后输入,则该程序将该数字打印为一个单词。但是如果按0并进入,程序就会退出。
现在我试图让父程序以一种方式执行子程序,它所做的只是退出程序,同时显示操作的进度。
当我执行我的程序时,我看到:
Child to start
Parent running OK
这表明子程序正在运行,否则我会看到:
Exec failed
因此,系统没有让我看到任何实际有用的输出,而是决定逐渐放慢速度,直到我移动鼠标时鼠标光标移动不顺畅,然后它到达了它不会移动的地步'对键盘没有反应,所以我不得不按住电源按钮来重置我的电脑。
我该如何解决这个问题,以便它可以与任何可以在我按 0 并从其中进入时退出的程序(我小时候使用的)一起工作?
这是我的父母代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
//Setup child read and write file handle named parr and parw respectively
//and parent read and write file handle named to parr and parw respectively
#define kidr wrp[0]
#define kidw rdp[1]
#define parw wrp[1]
#define parr rdp[0]
int main(){
int cmd=0;
//setup and start pipes
int wrp[2],rdp[2];
if (pipe(wrp) == -1 || pipe(rdp) == -1){printf("ERROR: cant run pipes.\n");return -1;}
//Start fork
pid_t f=fork();
if (f > 0){
int wstat; //wait state data
char buff[100]; //our data buffer
close(kidr); //we are parent so close child handles
close(kidw);
struct timeval tv;
fd_set readfds;
tv.tv_sec = 1;
tv.tv_usec = 0;
printf("Parent running OK\n");
while(1){
//process other async events here
pid_t wpid=waitpid(-1,&wstat,WNOHANG);
if (wpid==-1){printf("Wait PID error\n");break;}
if (wpid > 0){printf("Children closed OK\n");break;}
//Process data only when child data is readable via pipe
FD_ZERO(&readfds);FD_SET(parr, &readfds);
select(parr+1, &readfds, NULL, NULL, &tv);
if(FD_ISSET(parr, &readfds)){
memset(buff,0,99);
int rd=read(parr, buff, 50);
//doesnt seem to reach this point...
if (rd > 0){
printf("Got: %s\n", buff);
}else{
if (cmd==0){
printf("sending data...\n");
char*dat="0\n"; //parent sends 0 and the enter button.
cmd++; //so this doesn't get called again
write(parw,dat,strlen(dat));
}
}
}
}
//close everything and exit
close(parr);
close(parw);
return 0;
}
if (f==0){
printf("Child to start\n");
//Child mode.
//Close parents
close(parr);close(parw);
//make stdio as child handles
dup2(kidr,STDIN_FILENO);dup2(kidw,STDOUT_FILENO);
//close old child handles
close(kidw);close(kidr);
execlp("/path/to/forkt","forkt",NULL);
//We shouldn't get here unless 'ls' command isnt found
printf("Exec failed\n");
_exit(-1);
}
if (f==-1){
//If fork() doesnt work...
printf("Fork error\n");
}
return 0;
}
这是我为孩子编写的代码,我对其进行了编译,因此将其命名为 forkt。
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("The child has started\n\n");
char c[100];
while (1){
printf("Enter number or 0 to exit: \n>");
scanf("%s",c);
if (c[0]=='1'){printf("one\n");}
if (c[0]=='2'){printf("two\n");}
if (c[0]=='3'){printf("three\n");}
if (c[0]=='0'){return 0;}
}
}
更新
我接受了通过 gdb 调试器运行我的父代码的建议。
我使用 gcc -g 开关编译了我的代码,然后使用 gdb a.out 执行它
然后在 gdb 中,我为第一行代码设置了一个断点,然后使用“run”命令,然后我继续使用“step”命令,直到找到此处的崩溃点:
pid_t f=fork();
if (f > 0){ // <- right here
这表明,如果孩子在没有父母的情况下自行运行,即使孩子运行良好,孩子也会以某种方式创建锁定(?)?
【问题讨论】:
-
使用调试器准确找出进程在做什么。其中一个可能处于紧密循环中。一个问题是
tv没有在每个循环中被重置。 -
我添加了一个更新来显示调试结果,尽管我单步执行每条指令,但在我的代码的子进程中执行 fork() 后系统崩溃,对我来说没有任何建议无限循环
-
“崩溃点”是什么意思。之前没有提到任何崩溃。调试器中究竟显示了什么?请注意,您还可以让 gdb 调试子价格以查看它在做什么。
-
“崩溃点”是指系统刚刚锁定的点。它显示了每一行代码,直到上面显示的 pid 比较,然后它显示了与我手动执行程序相同的结果。我会在管道处理方面做错吗?
标签: c io fork child-process stdio