进程控制(上):进程创建,进程等待,进程终止

本文详细介绍了进程控制的三个方面:进程创建(包括fork和vfork函数的特性)、进程终止(正常与异常终止方式)以及进程等待(wait和waitpid函数的使用与区别)。重点讨论了进程间的资源共享、状态转换以及父进程如何获取子进程的退出状态。建议阅读《UNIX环境高级编程》以深入学习。

进程创建

进程创建被定义为通过父进程创建子进程的过程。

fork函数

函数原型:pid_t fork(void);

特点
1.fork函数调用一次,返回两次两次返回值得区别分别是子进程当中的返回值为0,父进程当中的返回值为新建子进程的ID(将ID返回给父进程的原因是没有函数可以使父进程得到子进程的ID,这样会便于管理);
2.子进程被创建出来后,子进程是父进程的副本(子进程获得父进程数据空间,堆,栈的副本<一定注意是副本>);
3.父进程和子进程只共享正文段(.text);
4.由于fork之后经常跟随者exec(程序加载函数),所以现在很多操作系统的实现并不执行一个父进程的副本,而是使用了写时拷贝(这些区域由父子进程所共享,而且内核将这些区域的访问权限设定为只读权限,如果父进程和子进程中的任意一个区域试图被修改,则内核会为修改区域产生一个副本)。
5.fork之后父进程和子进程的执行顺序是随机的,取决于内核所使用的调度算法。
6.关于文件共享,这部分内容和文件描述符有关大家可以看看下面这篇博客:http://blog.youkuaiyun.com/bit_clearoff/article/details/54565044
7.父进程和子进程的区别:
- fork的返回值不同
- 进程ID,父进程ID不同
- 子进程不继承父进程设置的文件锁
- 子进程未处理的闹钟被清楚
- 子进程未处理的信号集,被设置为空集

函数vfork

vfork函数也是创建进程,但是与fork函数不相同的是:
1.vfork创建一个新进程,而新进程的目的是exec一个新程序;
2.vfork并不将父进程的地址空间完全复制到子进程中;
3.子进程在调用exec函数或者exit函数之前,子进程在父进程的空间中运行;
4.vfork函数保证子进程先运行,在它调用exec或exit函数之后父进程才会被恢复运行。

进程终止

进程有五种正常终止方式和三种异常终止方式,他们分别是:
五种正常终止方式
1.在main函数内执行return 语句。它等效于调用exit;
2.调用exit函数,exit函数由C库定义,其操作包含调用各种终止处理程序,关闭所有标准I/O流等。详细的大家可以看看下面这篇博客:
http://blog.youkuaiyun.com/bit_clearoff/article/details/54425362
3.调用_exit函数,exit函数和_exit函数的不用地方就是它为进程提供了一种无需终止运行终止处理程序或信号处理程序而终止的办法
4.进程的最后一个线程在其启动例程中执行return语句.(这个现在大家先了解即可,关于线程的知识后面会详细分析)
5.进程的最后一个线程调用pthread_exit函数。

三种异常终止方式
1.调用absort。
2.当进程接收到某些信号时。
3.最后一个线程对“取消请求作出响应”。

不管进程以上面的何种方式进行终止,都会执行内核中的同一段代码,这段代码为相应的进程关闭所有打开的描述符,释放进程所拥有的地址空间。
另外,对任意一种终止情形,父进程都希望得到所终止的子进程的相关退出信息,对于三个终止函数,都采用了输出型参数status得到子进程的退出状态和信息;在异常情况中,内核产生一个指示其异常终止原因的终止状态,另外,父进程可以用wait函数和waitpid函数取得子进程的终止状态。

上面提到的都是子进程先被终止,然后父进程回收子进程的相关状态,这时被终止的子进程被称为僵死进程(注意父进程此时还没有被终止);
这里写图片描述
但是如果父进程在子进程被终止前先被终止,此时我们称子进程

### 如何在DFA状态转换图中确定终止状态 在NFA到DFA的转换过程中,终止状态的确定是至关重要的一步。为了确保DFA能够正确地接受或拒绝字符串,需要追溯到NFA中定义的终止状态,并考虑状态迁移时可能达到的所有路径[^1]。 在子集构造算法中,每个DFA的状态实际上对应于NFA中的一个状态集合。因此,DFA中的终止状态是由NFA中的终止状态决定的。具体来说,如果某个DFA状态(即NFA状态的集合)包含至少一个NFA的终止状态,则该DFA状态被标记为终止状态。例如,在一个具体的例子中,如果某个DFA状态 \( D \) 包含了NFA的终止状态集合中的元素(如状态 9),那么 \( D \) 就会被视为DFA的终止状态[^2]。 此外,子集构造算法的核心思想是将NFA的状态集合化,从而消除不确定性,使得每个输入字符都能唯一地决定下一个状态。由于NFA的状态转移可能存在多条路径,因此通过计算 ε-closure(空闭包)来涵盖所有可能的状态迁移[^3]。最终,当某个状态集合与NFA的终止状态集合有交集时,这个状态集合就被认为是DFA的终止状态。 在实际实现中,可以通过以下代码片段模拟DFA的状态转换,并判断是否到达终止状态: ```python # 假设我们有一个DFA的状态转换表 Map 和终止状态集合 final_states def is_accepted(Map, final_states, s_begin, str, alpha2idx): curState = s_begin # 初始状态 for char in str: if char not in alpha2idx: # 如果字符不在字母表中 return False nextState = Map[curState][alpha2idx[char]] if nextState == -1: # 如果没有对应的转换关系 return False curState = nextState # 更新当前状态 return curState in final_states # 判断最后是否达到了结束状态 # 示例使用 Map = { 0: {'a': 1, 'b': -1}, 1: {'a': -1, 'b': 2}, 2: {'a': -1, 'b': -1} } final_states = {2} # 终止状态集合 s_begin = 0 # 初始状态 alpha2idx = {'a': 0, 'b': 1} print(is_accepted(Map, final_states, s_begin, "ab", alpha2idx)) # 输出 True ``` 上述代码展示了如何根据输入字符串和状态转换表判断是否到达DFA的终止状态。如果最终状态属于终止状态集合,则返回 `True`,否则返回 `False`[^4]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值