如何测试调用进程是否为fork

时间:2020-12-05 00:03:40

Is there a method or C api in Linux/POSIX to determine if the current process is a fork? I.e. if it has been created by calling fork() without a subsequent call to the execve() family?

Linux/POSIX中是否有方法或C api来确定当前进程是否是fork?例如,如果它是通过调用fork()创建的,而没有随后调用execve()家族?

I do not control the code leading up to this point (it runs within a high-level language binding). I just need to know if the current process is running the top level program, or in a fork thereof.

我不控制导致这一点的代码(它在高级语言绑定中运行)。我只需要知道当前进程是运行*程序,还是在其分支中运行。

The best I have come up with is testing if the process has the same gid as it's parent:

我想到的最好的方法是测试这个过程是否与它的父进程具有相同的gid:

int is_fork = getpgid(0) == getpgid(getppid());

However this only works if the parent has called setpgid() which apparently execve() does not do by default. So that results in a lot of false positives.

然而,只有当父类调用setpgid()时,它才会起作用。这导致了很多假阳性。

4 个解决方案

#1


1  

On Linux, one somewhat imprecise check would be to see if the process's executable (/proc/$pid/exe) is the same as that of its parent. However, that won't work if a process execs its own executable, which might be common in some environments (eg. shells).

在Linux上,一个有点不精确的检查是看看进程的可执行文件(/proc/$pid/exe)是否与其父进程相同。但是,如果进程执行自己的可执行文件(这在某些环境中可能是常见的),那么这将不起作用。壳)。

#2


0  

Maybe you can use tms_utime, tms_stime, tms_cutime, or tms_cstime (see http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html). These variables are set to 0 in the child process.

也许您可以使用tms_utime、tms_stime、tms_cutime或tms_cstime(参见http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)。这些变量在子进程中被设置为0。

untested

未测试的

#3


0  

If you can control the environment of the top-level executable, you can use LD_PRELOAD to preload a shared library that installs a pthread_atfork handler that marks the child as forked by setting a globally visible. Your test code can then check the value of the variable to find out if the process has been forked without an intervening exec.

如果可以控制*可执行文件的环境,那么可以使用LD_PRELOAD预加载一个共享库,该库安装一个pthread_atfork处理器,通过设置全局可见性将子程序标记为fork。然后,您的测试代码可以检查变量的值,以查明进程是否在没有插入执行程序的情况下被分叉。

#4


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

Output:

输出:


$ ./testppid
[Child2] Pid=6220 Ppid=6219 Pgid=6219
[Child1] Pid=6219 Ppid=6218 Pgid=6219
[Parent] Pid=6218 Ppid=27410 Pgid=6218
$

This indicates that the shell (pid=27410) basically does the same to the Parent process as Child1 does before it invokes Child2: {fork,setpgid,exec}. Child1 is the proces group leader for itself and Child2 (the grandchild)

这表明shell (pid=27410)在调用Child2: {fork,setpgid,exec}之前对父进程所做的基本上与Child1相同。Child1是proces group leader, 2是Child2(孙子)

#1


1  

On Linux, one somewhat imprecise check would be to see if the process's executable (/proc/$pid/exe) is the same as that of its parent. However, that won't work if a process execs its own executable, which might be common in some environments (eg. shells).

在Linux上,一个有点不精确的检查是看看进程的可执行文件(/proc/$pid/exe)是否与其父进程相同。但是,如果进程执行自己的可执行文件(这在某些环境中可能是常见的),那么这将不起作用。壳)。

#2


0  

Maybe you can use tms_utime, tms_stime, tms_cutime, or tms_cstime (see http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html). These variables are set to 0 in the child process.

也许您可以使用tms_utime、tms_stime、tms_cutime或tms_cstime(参见http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)。这些变量在子进程中被设置为0。

untested

未测试的

#3


0  

If you can control the environment of the top-level executable, you can use LD_PRELOAD to preload a shared library that installs a pthread_atfork handler that marks the child as forked by setting a globally visible. Your test code can then check the value of the variable to find out if the process has been forked without an intervening exec.

如果可以控制*可执行文件的环境,那么可以使用LD_PRELOAD预加载一个共享库,该库安装一个pthread_atfork处理器,通过设置全局可见性将子程序标记为fork。然后,您的测试代码可以检查变量的值,以查明进程是否在没有插入执行程序的情况下被分叉。

#4


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

Output:

输出:


$ ./testppid
[Child2] Pid=6220 Ppid=6219 Pgid=6219
[Child1] Pid=6219 Ppid=6218 Pgid=6219
[Parent] Pid=6218 Ppid=27410 Pgid=6218
$

This indicates that the shell (pid=27410) basically does the same to the Parent process as Child1 does before it invokes Child2: {fork,setpgid,exec}. Child1 is the proces group leader for itself and Child2 (the grandchild)

这表明shell (pid=27410)在调用Child2: {fork,setpgid,exec}之前对父进程所做的基本上与Child1相同。Child1是proces group leader, 2是Child2(孙子)