getppid获取父进程的ID,父进程的ID是永远不变的
时间: 2024-03-07 22:53:33 浏览: 128
在一个进程的生命周期中,它的父进程 ID 是固定的,不会发生改变。因此,使用 `getppid()` 函数获取父进程 ID 的返回值也是不变的。父进程 ID 通常在进程创建时被赋值,并且在整个进程的生命周期中保持不变,直到进程终止。子进程的父进程 ID 则通常为创建它的进程的进程 ID。但是有一种特殊情况,即孤儿进程,如果一个进程的父进程在它结束前终止了,那么它的父进程 ID 将变为 1(init 进程的进程 ID)。
相关问题
利用fork()函数创建一个进程,形成的父进程和子进程分别输出自己的pid和ppid(ppid为当前进程的父进程id)
在Unix/Linux系统中,`fork()` 函数是一个用于创建新进程的基本工具。当父进程调用 `fork()` 时,它会复制自身并返回两个进程ID:一个是原进程自身的ID(不变),另一个是新生成子进程的ID(对于子进程是它的初始PID)。如果调用成功,子进程将拥有一个新的副本,共享相同的地址空间和文件描述符,而父进程则获得子进程的副本。
以下是简化的步骤说明:
1. 父进程(parent process)调用 `fork()` 函数。
- 如果返回值是0,那么这个新的进程就是子进程,此时应立即调用 `exec*()` 家族函数替换自身(例如 `execvp()`),以避免成为孤儿进程(即没有直接父进程管理的进程)。
- 如果返回值不是0,而是正数,那就是父进程本身,这时它可以记录子进程的PID。
2. 子进程(child process)执行流程:
- 子进程不需要再次调用 `fork()`,因为它已经通过父进程获得了新的身份。
- 子进程可以简单地打印出自己的PID和父进程的PID(通过 `getppid()` 函数获取)。
下面是一个简单的C语言示例:
```c
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t child_pid = fork(); // 创建子进程
if (child_pid == 0) { // 子进程
printf("我是子进程,我的PID是 %d,父进程的PID是 %d\n", getpid(), getppid());
} else if (child_pid > 0) { // 父进程
printf("我是父进程,我创建了一个子进程,其PID是 %d\n", child_pid);
} else { // fork失败
perror("Fork failed");
return 1;
}
return 0;
}
```
当你运行这个程序,你会看到父进程和子进程各自输出它们的PID和父进程的PID。
fork父进程和子进程
### Fork 创建的父进程与子进程的关系
Fork 调用用于创建新进程,该操作由现有进程发起并复制其当前状态来形成新的子进程。在 fork 执行之后,两个几乎完全相同的进程中有一个是原进程(父进程),另一个是由前者派生出来的副本(子进程)。父子两者的区别在于返回值以及它们各自的 PID 和 PPID (父进程 ID)[^1]。
对于父进程而言,在成功调用 `fork()` 后会获得一个正值作为子进程的 PID;而子进程则会在相同位置收到 0 的返回结果,并且拥有自己独立的新 PID 。这种机制允许程序区分哪个部分正在父进程中执行,哪些是在新生的子进程中运行[^3]。
#### 关键属性对比
| 属性 | 父进程 | 子进程 |
| --- | ------ | -------|
| 返回值 | 新建子进程的 PID | 总为 0 |
| 自身 PID | 不变 | 新分配 |
| 父进程 PID | 不变 | 继承自父进程 |
### 行为差异
- **资源共享**:尽管两者看起来相似,但实际上除了某些特定的数据结构外,比如文件描述符表项等会被二者共同持有之外,其他大部分内存映像都会被操作系统标记为写时拷贝(Copy-On-Write),这意味着只有当任意一方尝试修改数据时才会真正分离出单独的一份副本给改方使用[^2]。
- **终止通知**:一旦子进程结束生命周期,不会立即释放其所占用的所有系统资源直到对应的僵尸(zombie)条目被清理掉为止——这通常发生在父进程通过 wait 或 waitpid 类型的功能收集到有关已故子女的信息之时。如果子进程异常退出,则可以通过宏 WIFSIGNALED 来检测相应的信号编号[^4]。
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid;
printf("Before forking.\n");
pid = fork();
if (pid < 0){
fprintf(stderr,"Fork failed\n");
exit(1);
}else if(pid == 0){ // Child process
printf("This is child process, my PID=%d and parent's PID=%d\n",getpid(), getppid());
sleep(5); // Simulate work
_exit(EXIT_SUCCESS); // Exit without calling cleanup handlers.
}
else{ // Parent process
int status;
wait(&status); // Wait until the child has finished.
if(WIFEXITED(status)){
printf("Child exited normally with code %d\n", WEXITSTATUS(status));
}
if(WIFSIGNALED(status)){
printf("Child terminated by signal %d\n", WTERMSIG(status));
}
printf("Parent got message from child. My PID=%d\n", getpid());
}
}
```
阅读全文
相关推荐












