在该计划中:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pid;
int status;
pid = fork();
if (pid < 0)
{
return -1;
}
else if (pid == 0)
{
printf("I am the child\n");
exit(0);
}
else if (pid > 0)
{
pid = wait(&status);
printf("I am the parent\n");
printf("My pid is %i\nMy childs's pid is %i\nMy childs's exit status is %i\n", getpid(), pid, status);
}
}
该程序返回:
I am the child
I am the parent
My pid is 16269
My childs's pid is -1
My childs's exit status is 32767
1)为什么孩子的pid = -1而不是实际的子进程号?
2)为什么孩子的退出状态!= 0,如我所愿?
答案 0 :(得分:3)
关于子进程ID,因为您重新分配了pid
变量,并且wait
会在出错时返回-1
。
关于退出状态,由于wait
失败,它无效。但除此之外,它只包含包含实际状态的八个最低位。首先,您需要确保wait
调用确实成功,然后您需要使用WIFEXITED
宏检查进程是否正常退出,然后使用WEXITSTATUS
获取实际退出状态宏。
我建议您阅读wait
和<sys/wait.h>
标头文件的参考资料。
答案 1 :(得分:2)
我认为您必须在忽略SIGCHLD信号的情况下运行该过程。
当我正常运行你的代码时,我得到输出,如:
$ ./wp0
I am the child
I am the parent
My pid is 80161
My childs's pid is 80162
My childs's exit status is 0
$
但是,如果我在忽略SIGCHLD信号的情况下运行它,我会得到:
$ (trap '' CHLD; ./wp0)
I am the child
I am the parent
My pid is 80435
My childs's pid is -1
My childs's exit status is 0
$
您可以通过在shell命令行运行'trap'来检查这一点。例如,我得到:
$ (trap '' CHLD; trap)
trap -- '' SIGCHLD
$
如果使用trap
(没有参数)没有产生类似的答案,那么您可能需要编写一个程序来询问SIGCHLD状态。
顺便提一下,我做的第一件事(在回到原始代码之前)是将父代码更改为:
int corpse = wait(&status);
printf("I am the parent\n");
printf("My pid is %i\nMy child's pid was %i\nMy child's exit status is %i\n", getpid(), pid, status);
printf("My child's corpse was %i\n", corpse);
它从wait()
的返回值中单独捕获fork()
的返回值。此外,我通常使用0x%.4X
打印退出状态 - 部分原因是因为我对十六进制值的格式保持肛门,但主要是因为十六进制值更容易理解。您可以尝试使用不同的值(可能解释命令行参数)退出子项,甚至可以使用不同的信号自杀。虽然WIFEXITED
,WEXITSTATUS
,WIFSIGNALED
,WTERMSIG
等宏都很好,但它们也非常简单,您可以通过查看十字架{{{{{{ 1}}。
我扩展了您的程序以创建一个有效的测试工具,允许您尝试退出值和信号处理,如下所示:
status
我打电话给程序#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int c_status = 0;
int c_signal = 0;
int opt;
while ((opt = getopt(argc, argv, "s:e:")) != EOF)
{
switch (opt)
{
case 's':
c_signal = atoi(optarg);
break;
case 'e':
c_status = atoi(optarg);
break;
default:
fprintf(stderr, "Usage: %s [-e status][-s signal]", argv[0]);
exit(EXIT_FAILURE);
}
}
sigset_t oset;
if (pthread_sigmask(SIG_BLOCK, 0, &oset) != 0)
{
fprintf(stderr, "%s: pthread_sigmask() failed (%d: %s)\n",
argv[0], errno, strerror(errno));
exit(EXIT_FAILURE);
}
if (sigismember(&oset, SIGCHLD))
printf("SIGCHLD is listed in the signal mask\n");
struct sigaction oact;
if (sigaction(SIGCHLD, 0, &oact) != 0)
{
fprintf(stderr, "%s: pthread_sigmask() failed (%d: %s)\n",
argv[0], errno, strerror(errno));
exit(EXIT_FAILURE);
}
if (oact.sa_handler == SIG_DFL)
printf("SIGCHLD handling is the default\n");
else if (oact.sa_handler == SIG_IGN)
printf("SIGCHLD handling is ignoring the signal\n");
else
printf("SIGCHLD has a signal handler installed (%p)\n", (void *)oact.sa_handler);
if (oact.sa_flags & SA_NOCLDSTOP)
printf("SA_NOCLDSTOP is set\n");
if (oact.sa_flags & SA_NOCLDWAIT)
printf("SA_NOCLDWAIT is set\n");
int pid = fork();
if (pid < 0)
{
return -1;
}
else if (pid == 0)
{
printf("I am the child - PID %d\n", (int)getpid());
if (c_signal == 0)
{
printf("I am exiting with status %d\n", c_status);
exit(c_status);
}
else
{
printf("I am committing suicide with signal %d\n", c_signal);
raise(c_signal);
printf("That didn't work - I'm still here. Oh well!\n");
exit(EXIT_FAILURE);
}
}
else if (pid > 0)
{
int status;
int corpse = wait(&status);
printf("I am the parent\n");
printf("My pid is %i\n", getpid());
printf("My child's pid was %i\n", pid);
printf("My child's corpse was %i\n", corpse);
printf("My child's exit status is 0x%.4X\n", status);
if (WIFEXITED(status))
printf("My child exited normally with status %d\n", WEXITSTATUS(status));
if (WIFSIGNALED(status))
{
printf("My child died from signal %d\n", WTERMSIG(status));
#ifdef WCOREDUMP
if (WCOREDUMP(status))
printf("My child produced a core dump\n");
#endif
}
}
return 0;
}
。用不同的选项运行它几次给出如下输出:
wp2
易于解释原始状态这一事实并不是避免使用POSIX提供的宏的借口。请注意,POSIX未指定$ ulimit -c unlimited
$ ./wp2 -s 4
SIGCHLD handling is the default
I am the child - PID 81188
I am committing suicide with signal 4
I am the parent
My pid is 81187
My child's pid was 81188
My child's corpse was 81188
My child's exit status is 0x0004
My child died from signal 4
$ ./wp2 -s 6
SIGCHLD handling is the default
I am the child - PID 81224
I am committing suicide with signal 6
I am the parent
My pid is 81223
My child's pid was 81224
My child's corpse was 81224
My child's exit status is 0x0086
My child died from signal 6
My child produced a core dump
$ ulimit -c 0
$ ./wp2 -s 6
SIGCHLD handling is the default
I am the child - PID 81489
I am committing suicide with signal 6
I am the parent
My pid is 81488
My child's pid was 81489
My child's corpse was 81489
My child's exit status is 0x0006
My child died from signal 6
$ (trap '' CHLD; ./wp2 -s 6)
SIGCHLD handling is ignoring the signal
SA_NOCLDWAIT is set
I am the child - PID 82300
I am committing suicide with signal 6
I am the parent
My pid is 82299
My child's pid was 82300
My child's corpse was -1
My child's exit status is 0x0000
My child exited normally with status 0
$ ./wp2 -e 6
SIGCHLD handling is the default
I am the child - PID 82434
I am exiting with status 6
I am the parent
My pid is 82433
My child's pid was 82434
My child's corpse was 82434
My child's exit status is 0x0600
My child exited normally with status 6
$
,但通常可用。