如何知道进程是父进程还是子进程

Ale*_*x.P 1 c unix linux pid systems-programming

如何识别进程是否是使用其进程的另一进程的子/孙pid

Fil*_*erg 7

进程ID:子进程和父进程

所有正在运行的程序都有唯一的进程ID.的 进程ID,一个非负整数,是一个过程,是唯一的标识符 总是唯一的.但是,可以重用进程ID.

当进程终止时,其ID可以重用.某些系统会延迟重用,以便新创建的进程不会与旧进程混淆.

某些ID是"保留"的,因为系统进程正在使用它们,例如调度程序进程.另一个示例是始终占用PID 1 的init进程.根据系统,可能会主动保留ID.

运行命令

> ps -eaf | head -n 5
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 11:49 ?        00:00:02 /sbin/init splash
root         2     0  0 11:49 ?        00:00:00 [kthreadd]
root         3     2  0 11:49 ?        00:00:00 [ksoftirqd/0]
root         5     2  0 11:49 ?        00:00:00 [kworker/0:0H]
Run Code Online (Sandbox Code Playgroud)

> pidof init
1
Run Code Online (Sandbox Code Playgroud)

将允许您独立验证这一点.1

在C中,我们可以使用以下函数来获取调用进程的进程ID和调用进程的父进程ID,

#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);
Run Code Online (Sandbox Code Playgroud)

流程可以创建其他流程.创建的进程称为" 子进程 ",我们将创建它们的进程称为" 父进程 ".

使用fork()创建一个新进程

要创建子进程,我们使用系统调用 fork()

#include <unistd.h>

pid_t fork(void);
Run Code Online (Sandbox Code Playgroud)

该函数由父进程调用一次,但它返回两次.子进程中的返回值为0,父进程中的返回值是新子进程的进程ID.1

进程可以有多个子进程,但是没有系统调用进程来获取其所有子进程的进程ID,因此父进程会观察子进程的返回值,并可以使用这些标识符来管理它们.

一个进程只能有一个父进程,它总是可以通过调用获得getppid.

孩子是复制父的,它得到一个复制母公司的数据空间,堆和栈的.他们不共享这些内存部分!2

我们将编译并执行以下代码片段以查看其工作原理,

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>

int main(void) {
    int var = 42; // This variable is created on the stack
    pid_t pid;

    // Two processes are created here
    //                 v~~~~~~~~~~|
    if ((pid = fork()) < 0) {
        perror("Fork failed");
    } else if (pid == 0) { // <- Both processes continue executing here
        // This variable gets copied
        var++; 

        printf("This is the child process:\n"
               "\t my pid=%d\n"
               "\t parent pid=%d\n"
               "\t var=%d\n", getpid(), getppid(), var);

    } else {
        printf("This is the parent process:\n"
               "\t my pid=%d\n"
               "\t child pid=%d\n"
               "\t var=%d\n", getpid(), pid, var);

    }


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我们将在执行程序时看到,无法保证首先执行哪个进程.它们甚至可以同时操作,有效地交错输出.3

$ # Standard compilation
$ gcc -std=c99 -Wall fork_example1.c -o fork_example1
$ # Sometimes the child executes in its entirety first
$ ./fork_example1
This is the child process:
     my pid=26485
     parent pid=26484
     var=43
This is the parent process:
     my pid=26484
     child pid=26485
     var=42
$ # and sometimes the parent executes in its entirety first
$ ./fork_example1
This is the parent process:
     my pid=26461
     child pid=26462
     var=42
This is the child process:
     my pid=26462
     parent pid=26461
     var=43
$ # At times the two might interleave
$ ./fork_example1
This is the parent process:
     my pid=26455
This is the child process:
     my pid=26456
     parent pid=26455
     var=43
     child pid=26456
     var=42
Run Code Online (Sandbox Code Playgroud)

1 PID代表进程ID,PPID代表 父进程ID.

2进程ID 0保留供内核使用,因此0不可能是子进程ID.

3许多系统不执行这些内存段的完整副本,而只是在任一进程执行写操作时才创建副本.最初,共享区域被内核标记为"只读",并且每当进程尝试修改这些区域时,内核都会授予每个进程自己的内存副本.

4标准输出被缓冲,因此它不是一个完美的例子.

  • 而且我相信你的第二个例子实际上告诉你你是否在一个进程的主线程中,而不是你是否在主进程中(无论这意味着什么). (2认同)