Linux / POSIX中是否有方法或C api来确定当前进程是否为fork?即如果是通过调用fork()
创建的,而不是后续调用execve()
系列?
我不控制导致这一点的代码(它在高级语言绑定中运行)。我只需要知道当前进程是在运行顶级程序,还是在其中。
我提出的最好的方法是测试该进程是否与其父进程具有相同的gid:
int is_fork = getpgid(0) == getpgid(getppid());
但是,这仅在父母已调用setpgid()
时才有效,显然execve()
默认情况下不会这样做。所以这会导致许多误报。
答案 0 :(得分:1)
在Linux上,一个有点不精确的检查是查看进程的可执行文件(/proc/$pid/exe
)是否与其父进程相同。但是,如果进程exec
是自己的可执行文件,那么它将无法工作,这在某些环境中可能很常见(例如shell)。
答案 1 :(得分:0)
也许您可以使用tms_utime
,tms_stime
,tms_cutime
或tms_cstime
(请参阅http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)。这些变量在子进程中设置为0
。
未测试
答案 2 :(得分:0)
如果您可以控制顶级可执行文件的环境,则可以使用LD_PRELOAD
预加载安装pthread_atfork
处理程序的共享库,该处理程序通过设置全局可见来将子项标记为分叉。然后,您的测试代码可以检查变量的值,以确定过程是否已经分叉而没有介入exec
。
答案 3 :(得分:-1)
/* ppid.c
cc -Wall ppid.c -o ppid
*/
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int pid, ppid, pgid;
pid = getpid();
ppid = getppid();
pgid = getpgid(0);
printf("[%s] Pid=%d Ppid=%d Pgid=%d\n"
, argv[0], pid, ppid, pgid);
return 0;
}
/* testppid.c
cc -Wall testppid.c -c testppid
*/
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int pid, pid2;
pid = fork();
if (pid == -1) return 1;
if (pid) { /* parent */
char *args[] = { "Parent", NULL};
sleep(3);
execve("./ppid", args, NULL);
} else { /* child */
pid = getpid();
setpgid(pid,pid);
pid2 = fork();
if (pid2 == -1) return 1;
if (pid2) { /* child1 */
char *args[] = { "Child1", NULL};
sleep(2);
execve("./ppid", args, NULL);
} else { /* grandchild */
char *args[] = { "Child2", NULL};
sleep(1);
execve("./ppid", args, NULL);
}
}
return 0;
}
输出:
$ ./testppid
[Child2] Pid=6220 Ppid=6219 Pgid=6219
[Child1] Pid=6219 Ppid=6218 Pgid=6219
[Parent] Pid=6218 Ppid=27410 Pgid=6218
$
这表明shell(pid = 27410)与Child1在调用Child2:{fork,setpgid,exec}之前的做法基本相同。 Child1是自己和Child2(孙子)的过程组负责人