是fork 不是 f**k。好吧,这个fork 翻译过来是”分叉”,在GitHub 那里可以fork 一份别人的仓库到自己的名下。就是开了个分叉,然后可以再自己fork 的这份仓库里进行操作,操作完了以后可以发起pull request 到原有的地方。
很形象啊有木有。在Linux 系统下可以通过fork (系统调用)来创建子进程,子进程会从fork 起继续向下执行代码。
一调用fork,就有了两个进程,当前进程创建出一个子进程,两个进程都继续从fork 这行继续往下走。
子进程的fork 返回值是0
父进程fork 返回子进程的pid。
如果fork 返回值小于0,说明创建进程失败。
创建失败的原因:
内存不够
内核参数限制(进程太多达到上限)ulimit -a查看
平台不支持
信号打断
好了,现在知道了这个写代码验证一下。
1 |
|
上面这个代码的16行,我不写sleep 和写了的输出结果是有区别的:
第一个红色框起来的是不写sleep:
爸爸:我叫23798,我的爸爸叫3766
儿子:我叫23799,我的爸爸叫1
为什么他爸生出来的儿子不认亲爸呢?这就是孤儿进程,爸爸把儿子创造出来后没多久就抛下儿子了,儿子被叫1号进程的人收养,所以这个儿子说我爸是1不是23798。
第二个红色框的是写了sleep的。
fork 的详细解释
fork 会以父进程为模板,创建一个子进程。
会把父进程的 PCB 稍加修改,成为子进程的 PCB。
会把父进程的虚拟地址空间拷贝一份,作为子进程的地址空间。
堆和栈都会拷贝一份,注意这里是写时拷贝(偷懒?效率?)
父子进程会共用一份代码,各自有一份数据(代码有的时候也会被拷贝,比如做外挂的时候应该会😼)
fork 分别在父子进程中返回
父进程返回子进程的pid,子进程返0,在fork后继续执行。
父子进程的执行顺序并不是 if 判断返回值来的,这个是由调度器来弄。
通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。