标签:
在现代操作系统中,进程提供两种虚拟机制:
虚拟处理器
虚拟内存
几个函数:
fork():创建新进程
exec():创建新的地址空间并把新的程序载入其中
clone():fork实际由clone实现
exit():退出执行
wait4():父进程查询子进程是否终结
wait()、waitpid():程序退出执行后变为僵死状态,调用这两个消灭掉。
X86系统中,current把栈指针的后13个有效位屏蔽掉,用来计算出threadinfo的偏移(currentthread_info函数)
movl $-8192, %eax
andl %esp,%eax
进程描述符中的state域是用来描述进程当前状态的。共有五种状态,标志如下:
状态转换图如下:
使用settaskstate(task,state)函数.
settaskstate(task,state); //将任务task的状态设置为state
setcurrentstate(state) 和下面等价
对于给定的进程,获取链表中下一个进程:
- list_entry(task->tasks.prev,struct
- task_struct,tasks)
一般操作系统产生进程的机制:
1. 在新的地址空间创建进程
2. 读入可执行文件
3. 执行
Unix的机制:
fork()和exec()。
fork():
通过拷贝当前进程创建一个子进程。
子进程与父进程的区别仅在于PID,PPID和某些资源和统计量
exec():
读取可执行文件并将其载入地址空间开始运行。
-** Linux通过clone系统调用实现fork** - 创建进程的大概步骤如下:
fork()、vfork()、__clone()都根据各自需要的参数标志调用clone()。
由clone()去调用do_fork()。
do_fork()调用copy_process()函数,然后让进程开始运行。
返回do_fork()函数,如果copy_process()函数成功返回,新创建的子进程被唤醒并让其投入运行。
一般内核会选择子进程首先执行。
除了不拷贝父进程的页表项之外,vfork()系统调用和fork()的功能相同。理想情况下不要调用vfork()。
子进程作为父进程的一个单独的线程在它的地址空间里运行 ,父进程被阻塞,直到子进程退出或执行exec()。子进程不能向地址空间写入。
vfork()系统调用的实现是通过向clone()传递一个特殊标志来进行的。
调用copyprocess()是,taskstruct的vfor_done成员被设置为NULL。
与普通进程类似,只不过在调用clone()的时候需要传递一些参数标志来指明共享的资源
与普通进程的区别只在于内核线程没有独立的地址空间。
- 它只能通过其他内核线程创建;内核通过kthread内核进程衍生所有的内核线程
- 新创建的线程处于不可运行状态,直到wake_up_process()明确地唤醒它
## 3.5 进程终结 ## - 进程终结时,内核必须释放它所占有的资源并告知父进程。
进程终结的原因:一般是来自自身,发生在调用exit()系统调用时。
显式的调用
隐式的从某个程序的主函数返回
大部分依赖于do_exit()来完成。其中有几个重点:
……
给子进程重新找养父(线程组中的其他线程或者init进程)
调用schedule()切换到新的进程
……
释放task_struct结构发生在父进程获得已终结的子进程信息并且通知内核不关注后,需要的系统调用是wait4():
挂起调用它的进程,直到其中的一个子进程退出,此时函数返回该子进程的PID。
- do_exit()--
- >forget_original_parent()-
- >find_new_parent()-
- >ptrace_exit_finish()
- (这一函数是为被跟踪的进程寻找父进程,因为被跟踪的进程会以调试程序作为临时父亲)
在本章中,我知道了操作系统的核心概念--进程,也跟着书本学习了进程的一般特性的重要性等等,很有趣。
《linux内核设计与实现》原书第三版
标签:
原文地址:http://www.cnblogs.com/20135239-yxlm/p/5340143.html