Linux进程理解( 四 )

int main(){while(1){printf("I am a process pid : %d\n",getpid());sleep(1);}return 0;}
ppid
ppid是父进程的pid,全称id.可以这么理解,一般情况下进程存在一个父进程我们多试几次,你就会发现一个问题,我们每一次运行同一个程序得到的进程的pid都是不一样的,这是OS需要重新为我们开辟空间
但是如果我们多次看一下自己的ppid,你就会发现一个很有趣的事情.
#include#include int main(){while(1){printf("I am a process pid : %d ppid : %d\n",getpid(),getppid());sleep(1);}return 0;}
那么这里的我们就开始疑惑了,为何这个ppid是不变的,这个父进程对应的是啥?我刚才退出一下 , 这个父进程会发生变化 , 不过原理还是一样的 。
我们看到了这个父进程是bash , 我这里说一个结论,我们在命令行上所有的指令几乎都是bash的子进程.至于bash怎么创建,它的父进程是谁,这里先不谈.
fork
我们这里就有点问,有没有不是使用可执行程序,也就是**./**,是不是右一些接口可以帮助我们创建.有的,这里有一个fork函数可以供我们创建子进程.
这里我们就有些疑惑了,我们从来没有遇见过可以返回两个数的函数,这个fork函数好特殊啊,这里为什么会这样,先不说,我们现在只需要知道fork可以帮助我们创建一个进程,我们先来看看.
既然我们已经知道了,fork可以创建一个子进程,我们有理由相信会执行两次.
#include#include int main(){pid_t id = fork();printf("hello bit id = %d\n",id);sleep(1);return 0;}
很好,这里就是可以确定fork确实可以创建一个进程,但是这里面还存在一个问题,你是如何确定这个新创建的进程是子进程呢?这里我们还需要查看一下进程的信息.
int main(){pid_t id = fork();while(1){if( id == 0 ){// childprintf("我是子进程 pid :%d ppid : %d\n",getpid(),getppid());sleep(1);}else{// parentprintf("我是父进程 pid :%d ppid : %d\n",getpid(),getppid());sleep(1);}}return 0;}
从这里我们就可以看出,fork创建了一个子进程,父子进程共享后面的代码,这也就解释了我们为何可以打印两次.根据返回值的不同 , 我们是可以控制这两个进程的 。
但是这里还是存在两个关键问题,我们一个id打印的时候没有修改,为何出现了两次不一样的值?fork是如何实现这个机制的?最关键的是 , 为何是给父进程返回pid , 给子进程返回0 , 这三个问题我们现在只回答两个 , 第三个等着后面的地址空间在说吧 。
为何是给父进程返回pid , 给子进程返回0?我们先来回答这个问题
在现实生活中,一个孩子肯定对应一个父亲,但是一个父亲可不止一个儿子,父亲给儿子取了名字,最主要的作用就是区分他的几个儿子,也就是说父进程必须存在可以标识子进程的方案,这个就h是fork后给父进程返回子进程的pid,帮助父亲能够快速的识别孩子.那么又为什么给子进程返回0呢?子进程最重要的是看看自己是不是被创建成功了,这个只是一个标记,对于子进程,找到父进程很容易,成本很低.
fork为何会有两个返回值
既让有两个返回值,那么他肯定返回两次.我们先来谈一下子进程是如何被创建的.
首先fork之后肯定要创建一个子进程,也就是说多了一个,这后面就是OS的作用了,OS要描述和组织,这里不谈.这里面存在一个问题,对于子进程它的属性从哪里来?大部分是通过继承父进程的,那么代码呢?它和父进程共享同一片代码,执行的逻辑是一样的,当然数据肯定存在些差异.这里面我们还要补充知识,对于一个函数,在执行语句的时候,它的核心功能已经完成了,只是一个收尾的.