C:带scanf的叉子
我试过这个密码C:带scanf的叉子,c,linux,fork,scanf,C,Linux,Fork,Scanf,我试过这个密码 #include <stdio.h> #include <sys/types.h> int main(){ int x=3; pid_t pid0=getpid(); pid_t pid1=0; if(fork()==0){ pid1=getpid(); } if(getpid()==pid1){ scanf("%d",&x); printf("%d",x); } return 0;
#include <stdio.h>
#include <sys/types.h>
int main(){
int x=3;
pid_t pid0=getpid();
pid_t pid1=0;
if(fork()==0){
pid1=getpid();
}
if(getpid()==pid1){
scanf("%d",&x);
printf("%d",x);
}
return 0;
}
#包括
#包括
int main(){
int x=3;
pid_t pid0=getpid();
pid_t pid1=0;
如果(fork()==0){
pid1=getpid();
}
if(getpid()==pid1){
scanf(“%d”和&x);
printf(“%d”,x);
}
返回0;
}
而
scanf
指令被完全忽略。它只打印旧的x,即3。有人能给我解释一下这里发生了什么吗?我不明白为什么你会认为它被忽视了
具体发生什么取决于使用什么。让我们来看看BASH。
如有疑问,请使用strace(例如strace-fo-meh bash+./a.out)
24852 ioctl(255,TIOCSPGRP
24909读(0,
24852 , [24852]) = 0
24909 0xb774a000,1024)=-1 EIO(输入/输出错误)
24852 rt_sigprocmask(SIG_SETMASK,[CHLD],
24909 fstat64(1,
24852空,8)=0
24909{st_mode=S_IFCHR | 0620,st_rdev=makedev(136,2),…}=0
24852 ioctl(255,SNDCTL\u TMR\u时基或TCGET
24909 mmap2(空,4096,保护读取,保护写入,映射私有,映射匿名,-1,0
24852,{B38400 opost isig icanon echo…})=0
24909)=0xb7749000
24852 ioctl(255,TIOCGWINSZ
24909写入(1,[7]\n],4
24852显然是外壳。255是与终端关联的fd,与执行程序过程中的0相同。如您所见,发出ioctl以重新获得对终端的控制,这导致读取操作失败。如果您实际检查错误,您会了解到这一点
有一个旁注,我修改了数字并将其括在[]内,这样就不会与键入的字符混淆
找出其他shell(例如zsh)的情况留给读者作为练习。这里对代码进行了一个小的修改。它检查
scanf()
是否工作,调用getpid()
频率会降低一点,报告的时候会更仔细一点。此外,家长在退出之前会等待孩子退出
示例运行(我调用了程序fork7
):
这是因为
scanf
将失败。您可以通过做这个简单的实验来确保这一点,只需检查代码段中scanf
的返回值
if(getpid() == pid1) {
printf("return value of scanf %d\n",scanf("%d",&x));
printf("%d",x);
}
您必须获得的输出:
return value of scanf -1 //that means scanf got failed ?
3
现在的问题是为什么扫描失败
一旦父母退出,孩子就会被新的父母收养(通常是
我认为PID为1的-/etc/init或类似)。并且stdin
控件也被禁用。如果您确实想在子进程中获取输入(使用scanf
),请强制您的父进程等待其子进程成功返回。这可以通过以下方式实现:
else {
waitpid(-1,&status, WCONTINUED);
return 0;
}
还请确保您的孩子也应返回。
有关waitpid
的更多详细信息,请查看
注意
:始终建议您使用scanf
。如果您觉得必须使用scanf
,您确实应该检查返回值以确定在转换之前是否发生了输入错误。并且请始终检查fork
的返回值。,因为您没有无论终端上提供了什么作为输入,也没有证明scanf()
通过返回1
成功,您都没有理由抱怨太多。
if(getpid() == pid1) {
printf("return value of scanf %d\n",scanf("%d",&x));
printf("%d",x);
}
return value of scanf -1 //that means scanf got failed ?
3
else {
waitpid(-1,&status, WCONTINUED);
return 0;
}