学习Linux C编程之进程控制编程

来源:互联网 发布:起点数据库 编辑:程序博客网 时间:2024/05/29 16:56

创建进程 fork

fork 的定义

在 Linux 中,我们使用 fork 来创建一个子进程

fork 的返回值

fork 函数有些特殊,成功它返回 2 次,失败返回 -1,利用这个特性可以判断当前的进程是子进程还是父进程: 
1. 在子进程中返回 0 
2. 在父进程中返回子进程的进程 ID

fork 的写时复制技术

通过执行 fork,子进程得到父进程的一个副本,例如子进程获得父进程的数据空间,堆和栈的副本,但是它们并不共享存储空间,它们只共享代码段。但是在现在的系统实现中,并不执行拷贝父进程的副本,作为替代方案,而是使用写时复制(Copy - On - Write)技术。

写时复制:在 fork 之后,这些区域由父子进程共享,而且内核将它们的访问权限改变为只读,如果父子进程中的任何一个试图修改这些区域,内核只为修改区域的那片内存制作一个副本给子进程。

不管是哪种技术实现,最后父子进程的数据都是独立的,不会相互影响

子进程的执行位置

fork 还有一个特点:子进程不是从 main 函数开始执行的,而是从 fork 返回的地方开始

创建进程 vfork

还有一个创建进程的系统调用 vfork,它跟 fork 很相似,但是也有几点不同: 
1. vfork 的目的是创建一个子进程来运行一个程序 
2. vfork 并不复制父进程地址空间,子进程在父进程地址空间中运行,并阻塞父进程直到子进程返回 
3. vfork 保证子进程先运行 
4. 子进程需要调用 exec 或 exit 函数退出,否则会带来未知结果。

exec

fork 函数里面最后也是调用 exec 等函数来执行程序的

exec 有很多变种函数,例如 execlpexecle,等等,但基本的用法都是差不多的

运行结果就相当与 shell 命令:ps - ef,其他的变种函数可以通过 man exec 来查看。

进程等待 wait

父进程可以使用 wait 系统调用主动等待子进程或者指定进程结束,并获得子进程的结束信息

这个系统调用的过程如下: 
1. wait 暂停调用它的进程直到子进程结束 
2. wait 调用成功返回子进程的 PID 
3. wstatus 存储子进程的返回信息(正常退出,异常退出,被信号杀死),以此来知道子进程是如何结束的

大致的流程如下:

F ---fork------> F -------- wait ----> F ------------->        |                              |        |                              |        |                              |        -------> C -------------exit() -
  • 1
  • 2
  • 3
  • 4
  • 5


如果子进程调用 exit 退出,那么内核将 exit 的退出状态码放在 status 中 
如果进程被杀死,内核将信号序列放在 status 中

实际使用时,wait 提供了相关的宏来判断 status 的状态

进程结束

既然能够创建进程,那肯定能够结束进程,在 Linux 中进程退出又分为正常和异常退出,分别来了解了解。

正常退出

有 5 种正常退出进程的方法: 
1. 在 main 内执行 return,等价于调用 exit 
2. 调用 exit 
3. 调用 _exit 或 _Exit 
4. 进程的最后一个线程在其启动例程中执行 return 语句 
5. 进程的最后一个线程调用 pthread_exit 函数

异常终止

有 3 种异常终止的方法: 
1. 调用 abort,产生 SIGABRT 信号 
2. 当进程接受到某些信号时 
3. 最后一个线程对「取消」请求作出响应

不管是哪种终止情况,我们都可以使用 wait 或者 waitpid 来得到子进程的退出状态。

原创粉丝点击