1、fork()函数简单认识
用来创建进程,
进程的概念:一个可执行程序执行起来就是一个进程。
多个进程可以共享同一个可执行文件。
在一个可执行程序中,可以用fork来创建一个子进程,他从fork指令的下一条开始执行与父进程相同的代码。内存也一样。原来一条执行通路,现在变成了两条。
1.1、fork()函数简单范例,上图。
ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E 'bash|nginx|PID'
-E表示可以多个选项,如果是-e要写多次。
kill -usr1 1090
1.2、僵尸进程的产生、解决、SIGCHLD
sudo strace -e trace=signal -p 1090 附着进程
kill孩子进程,父进程收到SIGCHLD信号。子进程编程僵尸进程Z+状态。
僵尸进程的产生:一个子进程结束了,但是他的父进程还活着,
但是该父进程没有调用wait()/waitpid()函数来进行额外的处置,
那么子进程就会编程僵尸进程。占用pid号,整个系统pid号总共三万多个。
内核认为父进程还需要子进程的一些收尾信息。
开发者不能允许僵尸进程的存在。
解决:把父进程干掉,实际工作中不会这么干。
或者父进程收到SIGCHLD信号,
所以对于源码中有fork这种调用的行为,
就应该拦截并处理SIGCHLD信号。
waitpid(获得子进程状态)回收子进程资源。
上图:
2、fork()函数进一步认识
fork产生新进程的速度非常快,fork()产生的新进程并不复制原进程的内存空间,
而是和原进程共享一个内存空间,但这个内存空间的特性是“写时复制”
也就是说,原来的进程和fork()出来的子进程可以同时、自由的读取内存,
但是如果子进程或者父进程对内存进行修改的话,
那么这个内存就会复制一份给该进程单独使用,
以免影响到共享这个内存空间的其它进程使用。
上图:
3、完善一下fork()代码
fork会返回两次,父进程返回一次,子进程返回一次。
而且fork在父进程和子进程返回的值是不同的。
父进程返回子进程的pid,子进程返回0 ;
也为全局量发生改变,此时父子进程单独一块内存。
3.1、一个和fork()执行有关的逻辑判断
上图:((fork() && fork()) || (fork() && fork())) 7个进程。
或:有1出1,全0出0
与:全1出1,有0出0
分析:第一个fork分成两条,等于0 的不用执行第二个fork,
但需要执行第三个fork,等于0的不用执行第4个fork,
大于0的分支的要执行第4个fork,
所以第一个fork=0的总共分出3条进程。
一次类推,第一个fork=1的分出4条进程。
4、fork()失败的可能性
1、系统中进程太多,可能是僵尸进程太多。
缺省情况下,最大的pid是32767,16位。
2、每个用户有个可以开启的最大的的进程数。
printf("%ld" , sysconf(_SC_CHILD_MAX)); 一般7788左右。
网友评论