一、fork 函数
刚才为什么子进程 ppid=1? 收尸的问题
第
1
种情况就是父进程先死
,
所以交给
bash
收
,
而
bash
是一个
shell
有命令提示符所以每行都有子进程跟在后面输出。
第
2
种情况是父进程运行时休眠了
1
秒
,
子进程先运行结束
,
父进程收尸
,
当父进程结束
bash
给收尸就会打印出命令提示符。
其实第
1
种情况
,
父子进程同时运行到底谁先谁后不确定
,
第
2
种情况用软件来控制。一般情况同一个程序运行父子进程就是这种形式了。
f ork的特点:
1.调用
1
次返回
2 次,一分为二,父子进程各自分离,返回的是不同的值,后续各自独立运行自己的代码;
2.fork 时子进程会“复制”一份父进程的所有的代码;
3.fork 返回到底先执行哪一个进程是不确定;
写操作时拷贝:
由于 fork 完整地拷贝了父进程的整个地址空间,因此执行速度是比较慢的。为了提高效率,创建新进程, 但它不产生父进程的副本。它通过允许父子进程可访问相同物理内存从而伪装了对进程地址空间的真实拷贝,当子进程需要改变内存中数据时才拷贝父进程。这就是著名的“写操作时拷贝”(copy-on-write)技术。
扩展学习:
pid =0 :称为交换进程(
swapper)
作用: 进程调度
pid=1 :
init 进程
作用: 系统初始化
Linux 内核启动之后,会创建第一个用户级进程
init,由上图可知,
init 进程
(pid=1)
是除了
idle
进程
(pid=0,
也就是 init_task)
之外另一个比较特殊的进程,它是
Linux
内核开始建立起进程概念时第一个通过 kernel_thread
产生的进程,其开始在内核态执行,然后通过一个系统调用,开始执行用户空间的 / sbin/init 程序。
二、vfork 函数
由于
fork
完整地拷贝了父进程的整个地址空间,因此执行速度是比较慢的。为了提高效率,有些
Unix
系统 设计者创建了 vfork
。
vfork
也创建新进程,但它不产生父进程的副本,子进程不将父进程地址空间完全复制到子进程中,
而是共享的
,因为子进程会立即调用
exit
(或
exec
)后,也就不会存放该地址空间。
例如:很多嵌入式
Linux
系统的
fork
函数调用都采用
vfork
函数的实现方式。实际上
uClinux
所有的多进程管理都通过 vfork
来实现。
用
vfork()
有个特点必须在父进程和子进程末尾加
exit
函数结束
与
fork
区别
1) fork()
执行后两个进程同时执行
,
而
vfork
有先后顺序;
2)
子进程会先于父进程执行
,
前提子进程创建成功;
3)
子进程不将父进程地址空间完全复制到子进程中;
4)
记得加入
exit()
有先后顺序用它来结束
,
否则会有
core dump;
什么是core dump?
core dump
当一个进程要异常终止时
,
可选择把进程的用户空间内存数据全部保存在磁盘上
,
文件名通常是
core,
这叫
Core Dump.
进程异常终止通常是因为有
Bug
,比如非法内存访问导致段错误,事后可以用调试器检查
core
文件以查清错误原因,这叫做
Post-mortem Debug
。一个进程允许产生多大的
core
文件取决于进程的
Resource
Limit
(这个信息保存在
PCB
中)。默认是不允许产生
core
文件的,因为
core
文件中可能包含用户密码等敏感信
息,不安全。在开发调试阶段可以用
ulimit
命令改变这个限制,允许产生
core
文件。
三、exec 函数家族
exec
函数族提供了一种在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。在执行完之后,原调用进程的内容除了进程号外,其他全部都被替换了。
可执行文件既可以是二进制文件,也可以是任何
Linux
下可执行的脚本文件。
有
6
个函数 参数类型含义个数不同
,
有共同前缀
exec
区别:l, lp, le, v, vp, vpe
参数分为
2
个部分;
第
1
个参数
path
或
file
寻找程序的方式;
第
2
个参数 加载程序执行的命令;
l/v
表示第
2
个参数不同的;
l
表示以列举方式传参;
v
表示以数组方式传参;
在一个进程空间中加载另一个程序,一般和 fork
一起用,
共享代码段,
执行同样的程序,创建进程希望干别的事情,
不是做同样的事情。
四、exit 和_exit 函数
exit 和_exit 函数 功能都是结束进程
exit:
1)刷新缓冲;
2)释放缓冲区;
3)清理现场结束进程;
注意: return
会实现和
exit()
相同的功能;
_exit:
直接结束当前进程;
不去处理现场;
五、wait 函数
调用该函数使进程阻塞,直到任一个子进程结束或者是该进程接收到了一个信号为止。如果该进程没有子进程或者其子进程已经结束,wait
函数会立即返回。
用法1:
.
给子进程收尸使当前进程阻塞;如果调用 wait()
的函数没有子进程则立即返回。
用法2:
用宏来测试拿到子进程
exit()
函数返回值。
不能给多个进程收尸
?
https://blog.csdn.net/qq_43471489/article/details/125232557
六、waitpid 函数
waitpid
函数功能和 wait
函数类似。可以指定等待某个子进程结束以及等待的方式(阻塞或非阻塞) ;waitpid 函数比较复杂用的不多给指定进程收尸。
pid
参数:pid 有
4
个值
pid>0 给指定进程 pid
的子进程收尸
pid=-1 类似 wait
函数
pid=0 等待 当前进程组(
用户组一样
)
进程组
1
有
2
个进程
p1,p2
进程组
2
有
2
个进程
p3,p4
同一个进程组里面任意进程例如
进程组
2
里面
p3
或
p4
pid=-1
只能给进程
p1
即使同一个组
p2
也不能
pid<=1:
给指定进程组里面的进程收尸
option
参数
0:
阻塞
(
一般传
0
即可
wait
目的就是收尸
)
WNOHANG
不阻塞
WUNTRACED