初探Linux kernel之进程相关二

初探Linux kernel之进程管理二

上次说了进程的相关组成信息,这次接着说吧。之所以长期没有更新,是因为春天到了,是个容易让人心跑毛的季节,老想着跑着玩了……哈哈

继续。。。。。。。。。

知道了进程不仅仅是由一段执行代码组成的,咱们就说说linux下的进程的大概过程。其实一个进程就相当于一个软件的动态执行(严格的说是某个软件子系统的动态执行,当然我们可以把该子系统想象成一个子软件,这样会便于理解)Linux中创建一个进程要用到fork()系统调用,一个子进程的生成是通过拷贝父进程来实现的。fork以后,会返回两次:一次回到父进程,一次回到子进程。为何要返回两次,两次又是如何区别的呢??刚开始我也在像这个问题,因为子进程拷贝了父进程的代码,返回时处于fork()返回点的上下文是一样的,但是返回的值不一样,借此来区分是父进程还是子进程……

这不,新的子进程创建好了,然后干什么?肯定是做不是当前进程的工作,要不创建他干什么?所以,这时候就接着调用exec*()这一族函数,该族函数可以创建新的地址空间,并加载到当前进程执行。

最后,程序通过exit()syscall(系统调用,以后都用这个代指了)退出执行。这个函数会终结进程并将其占用的资源释放掉。父进程通过wait4()syscall来查询子进程是否终结,这使得进程拥有了等待特定进程执行完的能力(这不就是传说中的同步么?有木有?有木有?哈哈)。进程退出后被设置为僵死状态,知道父进程调用wait()waitpid()为止(其实他们貌似都是基于wait4()实现的)

上面就是进程创建到回收的简单过程。子进程由父进程创建,父进程回收,有点恢复现场的感觉,不过在比较安全的系统里面,哪里都可以看的“恢复现场”等类似概念的身影,就像借钱一样,“好借好还再借不难”,做程序也是这个道理,哈哈,慢慢体会,编程里面蕴含很多的哲学道理的。

1、进程描述符及任务结构

在软件设计中,第一就是抽象名词,一切名词都会在计算机中找到它的数据抽象,就是伟大的数据结构童鞋。他可能被抽象成一个变量,一个数组,一个struct,一个对象……可能是任何一种类型,只要满足你的需求,他就是最perfect的抽象。

进程在kernel中是被放在任务队列(tasklist)中的,tasklist是个双向循环链表。链表中的每一项都是task_struct类型,即进程描述符。定义在<include/linux/sched.h>中,包含着一个具体进程的所有信息。

1.1分配进程描述符

进程有的表达了,但是不能胡乱表达啊,就像追女朋友一样,不能见人就表白,那不成耍流氓了,名额有限,见好就收啊。OS能多道并跑的进程也就那几个,若肆意创建进程,不跑瘫了机子,那就变成病毒程序了,狂吃cpuLinux使用slab分配器分配task_struct结构。由slab动态生成task_struct,只需在栈底创建一个新的thread_info,再用这个结构的数据可以容易的计算出偏移量。

其中包含了task_struct的指针和进程的相关信息。

1.2进程描述符的存放

Kernel通过PID唯一标识一个进程,PIDpid_t类型,其实也是int型的,pid最大值是32768(shortintMax)。可以改其值,在/proc/sys/kernel/pid_max中,因为大公司的web服务器集群工作时32768个进程多开貌似不够啊。

内核在处理进程时一般是直接通过task_struct进程的,都是通过current宏直接找到或计算当前task_struct的。有的平台寄存器丰富,不用专门计算其值,一直把当前运行进程的值保存在专用的寄存器中就OK。如powerPCr2寄存器,而x86寄存器少要专门计算。

1.3进程状态

进程一直处于下面五种状态之一:

lTASK_RUNNING//运行状态

lTASK_INTERRUPTIBLE//可中断状态

lTASK_UNINTRRUPTIBLE//不可中断状态

lTASK_ZOMBIE//僵死

lTASK_STOPPED//停止

下图是大概的转换过程。不很详细,自己search一下……

s额,有空继续,今天就到这里吧……本周海贼更新了!!!哈哈!!!

详细请咨询blog专题:http://blog.csdn.net/dreambegin