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;
}