我想在Linux上实现类似CreateProcess的功能 . 我做了很多研究,发现"Fork off and die"方法使用双叉在init下运行子进程 . 也就是说,允许孩子独立于父母进行操作 .
因为父级需要返回有关新创建的子进程的信息(即pid,name等),所以我需要知道我的代码中是否遇到了竞争条件 . 目前,我通过管道fork并检索第二个fork的pid,然后等待第一个fork退出 .
int child = 0;
int fd[2] = { 0, 0 };
if (pipe (fd) != 0)
return Process();
int pid = fork();
if (pid < 0)
return Process();
if (pid == 0) // Child
{
if (setsid() != -1)
{
child = fork();
if (child == 0)
{
umask (0); // Reset umask
close (0); // Close stdin
close (1); // Close stdout
close (2); // Close stderr
execvp ( ... );
_exit (0);
}
// Do I need waitpid (child) here?
}
// Write the child PID using the pipe
write (fd[1], &child, sizeof (child));
_exit (0);
}
else // Parent
{
// Read the child PID using the pipe
read (fd[0], &child, sizeof (child));
// Remove zombie process
waitpid (pid, nullptr, 0);
// Child must finish exec by this point
return Process (child);
// Also gets name
}
Questions:
-
我是否需要第二个waitpid等待孩子完成执行?
-
waitpid是否在调用exec时返回?
-
即使在waitpid之前调用exit或exec,waitpid也会返回吗?
2 回答
你不需要在第二个孩子身上
waitpid()
. 当进程的父进程终止时,子进程将被init
进程采用,因此不会有僵尸进程 .waitpid()
仅在退出时等待的孩子返回 . 在孩子中调用execvp()
意味着服务员等待直到执行的程序死亡,因为那时孩子会死 .waitpid()
将获得进程的退出状态 . 该过程何时实际退出并不重要 .(稍微澄清一下:你所谓的孩子,实际上是你的孙子 . 这个过程的孩子刚刚分手并且死了 . )
你不能 . 这是你的孙子,你只能等待你的直接孩子 . 另外,因为你的孙子的父母已经去世了,你的孙子现在已经被重新归属于init(所以它实际上是你的前孙子女) .
Waitpid在给定的pid死亡/退出时返回,或者如果它已经是僵尸则立即返回 . 该孙女在孙子中被召唤 . 您的waitpid调用根本不关心不是您的直接孩子的进程(除非您使用的是仅限Linux的子子区域功能) .
等待pid(必须是你的直接孩子)已经死了,Waitpid才会返回 . 如果情况不是这样,它将会阻止 .