【问题标题】:How to know if a process is a parent or a child如何知道一个进程是父进程还是子进程
【发布时间】:2016-11-06 15:53:15
【问题描述】:

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

【问题讨论】:

  • ps -eal | less 检查列 PIDPPID(以及 man ps ;-)

标签: c linux unix pid systems-programming


【解决方案1】:

进程 ID:子进程和父进程

所有正在运行的程序都有一个唯一的进程 ID。这 process ID,一个 非负整数,是进程的唯一标识符 始终独一无二。但是,进程 ID 会被重复使用。

当一个进程终止时,它的 ID 就可以重用了。肯定 系统延迟重用,以便新创建的进程不会混淆 和旧的。

某些 ID 是“保留的”,因为它们正被以下用户使用 系统进程,例如 scheduler 进程。另一个例子是 init 进程总是占用 PID 1。取决于系统 该 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]

> pidof init
1

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

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

#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);

一个进程可以创建其他进程。创建的进程被称为 “子进程”,我们将创建它们的进程称为 “父进程”。

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

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

#include <unistd.h>

pid_t fork(void);

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

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

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

孩子是父母的副本,它得到父母的副本 数据空间、堆和栈。他们不分享这些部分 记忆! 2

我们将编译并执行以下代码sn -p 看看如何 这行得通,

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

当我们执行程序时,我们会看到没有任何保证 至于哪个进程首先执行。他们甚至可以操作 同时,有效地交错输出。 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

1PID代表进程IDPPID代表 父进程 ID.

2 进程 ID 0 是保留给内核使用的,所以 0 不可能是子进程 ID。

3 许多系统不执行这些的完整副本 内存段,而是仅在任一进程时创建副本 执行写入。最初,共享区域由 内核作为“只读”并且每当一个进程试图修改这些 内核授予每个进程自己的内存副本。

4标准输出是缓冲的,所以它不是一个完美的例子。

【讨论】:

  • 当这些进程是您的进程时,很容易知道哪个进程是子进程,但我认为问题在于确定其他进程的 pid。
  • 我相信你的第二个例子实际上告诉你你是否在一个进程的主线程中,而不是你是否在主进程中(不管这意味着什么)。
【解决方案2】:

使用getpid()和getppid()函数获取进程id和父进程id。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 2014-08-18
    相关资源
    最近更新 更多