进程阻塞
在上一篇文章中讲了进程的退出和进程等待的必要性,在进程等待里面提到一个概念叫做阻塞,在这里对阻塞进行一个比较详细的讲解。
进程阻塞就是进程主动停下来不跑了,在原地等待某个事件,如果没有等到,进程绝不往下执行。在学习C语言时,我们其实就见过,甚至经常见到阻塞的情况,比如 scanf 等待键盘输入就是我们最先看到的阻塞情况,还有 sleep 休眠也是。
来比较一下 "就绪" "运行" "阻塞"。
就绪:准备好了,等待CPU调用。
运行:正在CPU上干活。
阻塞:原本在CPU上干活,现在主动退出等待某个事件再继续。
那么现在我们可以知道,在父进程使用 wait 等待子进程退出时只能干等着,什么也干不了,而使用 waitpid 并设置 WNOHANG ,让父进程在非阻塞模式下等待子进程的同时,父进程也可以干自己的事情了。
但要注意的是,非阻塞模式下,如果父进程仅调用一次 waitpid ,子进程很大概率没有退出,此时无法获得子进程的退出信息,所以应该使用循环,这种方法叫做非阻塞轮询。

进程程序替换
进程的替换是在原来进程之上换入新的代码、数据,但是进程的 pid 不会改变。
使用 exec 系列函数可以实现进程的替换:

" exec " 后面的不同字符代表不同的含义,理解这些含义就可以可以轻松记住这 6 个函数各自的作用。
l : 表示 list ,可以认为是让你把参数一个一个列出来。
v:表示 vector ,可以认为是让你把参数放进数组里面。
p:表示 path ,可以认为是该函数会自动去PATH里面帮你查找命令,故你不需要写路径。
e:表示 env,可以认为是让你可以自己传环境变量而不使用系统默认的。
下面分别给出 6 个函数的例子:

对于这张图,要进行以下说明:
-
对于有 p 的函数例子,为什么会出现两个 "ls":第一个 "ls" 是给系统用来找到 ls 可执行文件的,我们只是不需要带路径,不是文件名都不需要写,第二个 "ls" 自然是我们要执行的命令了。
-
对于有 e 的函数例子,为什么没写:有两点原因,第一点是因为带 e 的函数使用的场景较少,而且自定义环境变量比较容易出问题。第二点,也是最重要的一点,由于写环境变量会导致该例子内容过多,破坏队形 (◑◡◑)。
下面是一个进程替换的例子:

在程序替换的过程中,并不会创建新的进程,只是把当前进程的代码和数据用新的程序代码和数据覆盖式的进行替换。值得注意的是,一旦进程替换成功,原始代码的后半部分就永远不会被执行到了,已经不存在了。像这样:
