使用execl创建的子进程不接受任何输入

时间:2017-01-04 19:20:22

标签: c operating-system parent-child child-process

我编写了一个程序,它首先复制当前进程(使用App),然后使用using Xamarin.Forms; namespace PersistWebViewSample { public class StartPage : ContentPage { public StartPage() { var navigateToWebViewButton = new Button { Text = "Open Persistent Web View" }; navigateToWebViewButton.Clicked += async (sender, e) => await Navigation.PushAsync(App.PersistentWebView); Title = "Start"; Content = navigateToWebViewButton; } } public class App : Application { static readonly string xamarinUrl = "https://www.xamarin.com/"; public App() { MainPage = new NavigationPage(new StartPage()); } public static ContentPage PersistentWebView { get; } = new ContentPage { Title = "Persistent Web View", Content = new WebView { Source = xamarinUrl } }; } } 创建子进程。

现在的问题是子进程无法接受任何输入。

fork()计划:

execl()

我使用命令child.c编译我的child.c以生成名称为#include<stdio.h> #include<unistd.h> int main(int argc, char *argv[]) { int p, pp; int a; char dummy; printf("\n enter value of a \n"); //fflush(0); // was using to clean STDIN, STDOUT //fflush(1); scanf("%c",&dummy); // simply using to accept any new line character if present any. scanf("%c",&dummy); // simply using to accept any new line character if present any. scanf("%d",&a); p = getpid(); pp = getppid(); printf("\nI m child with pid %d and ppid %d \n", p, pp); char *msg = argv[1]; printf("\n Message from parent is %s \n",msg); printf("\n The value of a is %d ",a); return 0; } 的目标文件,我在gcc child.c -o child文件中使用该文件

我的child计划:

parent.c

我尝试在孤儿状态和僵尸状态下运行程序,但在这两种情况下,子进程都没有接受输入。

当我运行父程序的./a.out时,我得到以下输出:

  

我是父母的pid 6801和ppid 4136

     

再见[aupadhyay @ localhost practice] $输入一个

的值      

我是pid 6802和ppid 1的孩子

     

来自父母的消息是你好

     

a的值为0

控制台不接受任何输入,而是打印默认值a。

有关如何在子进程中获得输入的任何信息/帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

注意:根据@Gilles的编辑和评论,答案得到了彻底改革。

虽然我可以复制您描述的行为,但我也可以通过I / O重定向向孩子提供输入:

./parent <<EOF


12345
EOF

...导致:

  

我是父母的pid 4430和ppid 2515

     

再见

     

$

     

输入

的值      

我是pid 4431和ppid 1的孩子

     

来自父母的消息是你好

     

a的值是12345

请注意,重定向到父标准输入的数据已成功读取并由孩子回显,因此问题不在于孩子无法接受输入。在某些情况下,它等待或成功读取输入,而是继续读取尝试,只能通过在这些条件下失败的scanf()调用来解释。

对此类失败的最合理的解释是,在尝试读取时,进程组已移至后台。通常,尝试从其控制终端读取的后台进程将导致其整个进程组停止(不终止)。但是,在您的情况下,进程组是孤立:组中没有进程在会话内但在组外部有父进程。在本案例和其他一些特殊情况下,来自其控制终端的后台流程read(),例如scanf()来电are required to fail, setting errno to EIO下的scanf

在该事件中,EOF反过来返回errno以指示错误,将EIO设置为scanf。测试perror的返回值并调用wait()来观察此情况。读取失败是一种明智的行为,因为它们有助于孤立组中的进程运行到完成和终止,而不是挂起,或者操作系统会立即杀死它们。 POSIX的目标似乎是为通过终止作为作业控制shell的父级而孤立的进程组提供优雅的处理,不让任何进程重新启动进程组。

你的情况并非如此,POSIX似乎意图迎合,但规范也支持观察到的行为:当其领导者死亡时,shell将前台进程组转移到后台,但(似乎)没有将其置于工作之下控制作为后台作业。据我所知,POSIX没有强制shell表现出这样的行为,但它也不需要。结果是一个孤立的进程组,其情况类似于POSIX构思的那些,同样也受到孤立进程组的特殊规定的支持。

如果您希望孩子保留对父母控制终端的完全访问权限,那么您应确保父母在孩子出生之前不会终止。如果父母在此期间没有其他任何事情要做,那么确保孩子首先终止的适当方式是父母waitpid()#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main() { int p, pp; p = getpid(); pp = getppid(); printf("\nI m parent with pid %d and ppid %d \n", p, pp); int b = fork(); if (b == 0) { execl("./child", "child", "hello", 0); } else { printf("\nBye\n"); wait(NULL); } return 0; }

order_by