在用fork创建子进程时,getppid()返回的却不是父进程的pid,或getppid()返回1。

在学习fork时,了解了子进程与父进程的概念,打算敲代码来实践认识一下。发现了一个很奇怪的问题,使用fork()之后,父进程中pid返回值是子进程,但是子进程中调用getppid(),得到的返回值却不是父进程。

我们先来复习下 fork(),getpid()和getppid()三个函数:
查看manual page:

fork:

 pid_t fork(void);  
 //creates  a new process by duplicating the calling process. 
 // On  success,  the PID of the child process is returned in the parent, and 0 is returned in the child. 

可知道fork用于复制一个和当前进程几乎一样的子进程,父进程返回的PID就是子进程的PID(Process ID),子进程则返回0.

getpid()和getppid:

pid_t getpid(void); 
 //returns  the process ID of the calling process.
pid_t getppid(void);  
 //returns  the  process  ID of the parent of the calling process.

即可知道,getpid()返回值为调用getpid()进程的PID,而getppid()返回调用这个函数进程的父进程的PID。

那么,为了实际的认识到子进程与父进程的关系,开始写代码了!实际操作下

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


int main()
{
   pid_t pid = fork();
   if(pid == 0)
   {
    printf("I am a child process!\n");
    printf("pid:%d,parent_pid:%d\n",getpid(),getppid());
   }
   else
   {
        printf("I am a parent process!\n");
        printf("pid:%d,child_pid:%d\n",getpid(),pid);
   }
    return 0;
}

按照道理来说,父进程中,getpid()打印的是父进程自己的PID,pid打印的是子进程的PID。而子进程中,getpid()打印的是子进程自己的PID,getppid()应该打印的是父进程的PID.

但是运行后,发现结果如下:

在这里插入图片描述父进程中getpid()确实是显示了子进程的PID:4370,但是子进程中调用getppid()返回的竟然不是父进程的PID,而是1852。

这是什么原因呢?我们先来看一下1852是什么:
(用ps命令可以查看进程的PID,或者根据PID查看进程。)

在终端输入:

ps 1852

在这里插入图片描述
会发现1852对应的进程是 init --user。

这到底是什么情况呢?init --user到底是什么?

查找资料后发现,有博主提到了“孤儿进程”这一概念Ubuntu中fork创建孤儿进程与收养,我觉得这很有意思。

大致意思就是:当使用fork()创建子进程后,主函数调用时,父函数先于子函数被调用,当父函数完成调用被摧毁后,才调用子函数。也就是说,当子函数被调用时,父函数已经被“杀死”了,这时的子进程便成了“孤儿进程”,init --user即会收养这个子进程。所以,子进程的父进程发生了改变,变为了 init --user。

而getppid返回值为1也是同样的情况,是由于父进程先退出了,造成子进程被init(PID=1)接管,所以用getppid出来的是1。

解决方法:
说了这么多,那么到底解决方法是什么呢?到底如何使getppid的返回值显示正常?或者说如何能不“杀死”父进程便能调用子进程呢?

方法很简单:在父进程调用后加上 sleep()函数即可。也就是让父进程陷入睡眠,而不导致它被摧毁。

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


int main()
{
   pid_t pid = fork();
   if(pid == 0)
   {
    printf("I am a child process!\n");
    printf("pid:%d,parent_pid:%d\n",getpid(),getppid());
   }
   else
   {
        printf("I am a parent process!\n");
        printf("pid:%d,child_pid:%d\n",getpid(),pid);
        sleep(1);
   }
    return 0;
}

在这里插入图片描述
这时子进程中的getppid()终于显示正常了!完美!

  • 18
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值