Ion*_*utC 5 c linux stdin fork scanf
我试着看看如果我用键盘读取东西会发生什么,而我有多个进程使用fork()(在我的情况下有两个孩子和一个父亲)我发现了以下问题:我需要告诉父母等待孩子的进程,否则程序行为奇怪.
我做了一个研究,我发现问题在于父母,他需要等待孩子的过程结束,因为如果父母的过程首先以某种方式结束他关闭了STDIN,我是对的吗?但我也发现每个进程都有一个STDIN的副本,所以我的问题是:
为什么它以这种方式工作,为什么只有父有STDIN的问题和孩子没有,我的意思是为什么如果孩子的过程先结束不影响STDIN但是如果父进程首先结束它会影响STDIN吗?
这是我的测试:
我跑的程序,而不等待()后,我输入了一些程序停止,但后来我按下输入从printf的两次,另两个消息()出现了.

当我用wait()运行程序时,一切正常,每个进程分别调用scanf()并读取不同的数字. 
嗯,这里有很多东西.我将尝试逐步解释它.
当您启动终端时,终端会创建一个具有路径的特殊文件/dev/pts/<some number>.然后,它开始你的shell(这是bash在这种情况下)和链接STDIN,STDOUT并STDERR在bash进程这个特殊的文件.此文件称为特殊文件,因为它实际上不存在于您的硬盘上.相反,无论你write对这个文件,它直接进入终端,终端在屏幕上呈现它.(同样,每当你尝试read从这个文件,read块,直到有人在终端输入内容).
现在,当您通过键入启动程序时./main,bash调用该fork函数以创建新进程.子进程exec是您的可执行文件,而父进程则是子进程wait终止.然后你的程序调用fork两次,我们有三个进程试图读取它们的STDINs,即同一个文件/dev/pts/something.(请记住,分别调用fork和exec复制并保留文件描述符).
这三个过程处于竞争状态.当您在终端输入内容时,三个进程中的一个将接收它(100个中的99个将是父进程,因为孩子在到达scanf语句之前必须做更多的工作).
因此,父进程打印数字并首先退出.bash进程正在等待父进程完成,恢复puts the STDIN into a so called "non-canonical" mode和调用read以便读取下一个命令.现在,三个进程(Child1,Child2和bash)正在尝试读取STDIN.
由于孩子们试图长时间阅读STDIN,下次你输入的东西会被其中一个孩子收到,而不是bash.所以你想要打字,比如说23.但是哎呀!按下2按键后,就可以了Your number is: 2.你甚至没有按Enter键!这是因为这种所谓的"非规范"模式.我不会进入什么,为什么会这样.但是现在,为了简化操作,使用可以运行程序sh而不是bash,因为sh不会将STDIN置于非规范模式.这将使图片清晰.
不,父进程关闭其STDIN并不意味着其子进程或其他进程将无法使用它.
您看到的奇怪行为是因为当父进程退出时,bash将pty(伪终端)置于非规范模式.如果您使用sh,则不会看到该行为.如果你想要明确的下划线,请阅读伪终端和线路规则.
父进程退出后,shell进程将立即恢复.
如果您使用wait以确保父级退出最后,您将不会有任何问题,因为shell将无法与您的程序一起运行.
通常,bash确保没有两个前台进程同时从STDIN读取,因此您不会看到这种奇怪的行为.它通过将一个程序的STDOUT传递给另一个程序,或者通过使一个进程成为后台进程来实现.
琐事:当后台进程尝试从其中读取时STDIN,会发送一个信号SIGTTIN,从而停止进程.虽然,这与这种情况并不真正相关.