gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 23:20:19 26 4
gpt4 key购买 nike

我编写了一个程序,它首先复制当前进程(使用 fork()),然后我使用 execl() 创建一个子进程。

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

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

我正在使用以下命令编译我的 child.c:gcc child.c -o child 以生成名称为 child 的目标文件,我在 parent.c文件

我的parent.c程序:

#include<stdio.h>
#include<unistd.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)
{
sleep(1);// for orphan state
execl("./child", "child", "hello", 0);
}
else
{
printf("\nBye\n");
}
return 0;
}

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

当我在父程序之外运行这个 ./a.out 时,我得到以下输出:

I m parent with pid 6801 and ppid 4136

Bye [aupadhyay@localhost practice]$ enter value of a

I m child with pid 6802 and ppid 1

Message from parent is hello

The value of a is 0

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

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

最佳答案

注意:根据@Gilles 的编辑和评论对答案进行了重大修改。

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

./parent <<EOF


12345
EOF

...导致:

I m parent with pid 4430 and ppid 2515

Bye

$

enter value of a

I m child with pid 4431 and ppid 1

Message from parent is hello

The value of a is 12345

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

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

在这种情况下,scanf 依次返回 EOF 以指示错误,将 errno 设置为 EIO .测试scanf的返回值,调用perror观察。读取失败是一种明智的行为,因为它们有助于孤立组中的进程运行完成并终止,而不是挂起或操作系统立即终止它们。 POSIX 的目标似乎是为因作为作业控制 shell 的父进程终止而孤立的进程组提供优雅的处理,不让任何进程期望或负责重新启动进程组。

你的情况不是 POSIX 似乎有意迎合的,但规范也支持观察到的行为:shell 在其领导者死亡时将前台进程组转移到后台,但(似乎)没有将其置于工作之下控制作为后台作业。据我所知,POSIX 不要求 shell 表现出这种行为,但也没有其他要求。结果是一个孤儿进程组,其情况与 POSIX 设想的情况相似,并且同样受到针对孤儿进程组的特殊规定的支持。

如果您希望子进程保留对父进程控制终端的完全访问权限,那么您应该确保父进程不会在子进程终止之前终止。如果在此期间父级没有其他事情可做,确保子级先终止的适当方法是让父级为其 wait()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;
}

关于使用 execl 创建的子进程不接受任何输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41471682/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com