[笔记分享] [OS] Linux的进程管理

Platform: msm8x60
Kernel: 2.6

进程是不局限于一段可执行代码,还要包括其他资源,如打开的文件、信号、处理器状态、地址空间、数据及一个或者多个线程。多个进程可执行同一个程序。多个进程可共享打开的文件、地址空间之类资源。
线程是进程中的活动对象,每个线程都有独立的进程栈、程序计数器和寄存器组。兄弟线程间共享地址空间、文件系统等资源。


进程描述符

内核将进程放在任务队列双向循环链表中,每项叫task_struct,如下图。结构描述了一个正在执行程序的所有信息。

[笔记分享] [OS] Linux的进程管理

Linux通过slab分配task_struct,在后面内存管理部分会讲slab。通过slab能达到避免动态分配和释放锁带来的资源消耗。task_struct由于结构太大,所以用图表示了,如下:

[笔记分享] [OS] Linux的进程管理

为了快速获取task_struct的位置,Linux在内核栈尾部创建了个新结构struct thread_info。其结构和存放位置如下:

[笔记分享] [OS] Linux的进程管理

每个进程用pid表示,可修改进程最大数目。访问task_struct的方法是通过thread_info计算偏移地址来查找。(thread_info中有task元素)
宏如下:
current_thread_info()->task或者 current 这两个宏都可以得到当前task_struct地址。


进程状态

进程通过state域描述当前状态:

TASK_RUNNING: 进程正在执行,或者在运行队列中等待执行。
TASK_INTERRUPTIBLE: 进程在睡眠,等待某事件满足,可在接收到信号后**。
TASK_UNINTERRUPTIBLE: 进程在睡眠,等待某事件满足,忽略信号的接收。
TASK_ZOMBIE: 进程已经结束,但父进程没调用wait4()系统调用。
TASK_STOPED: 进程没投入运行也不能投入运行。在收到SIGSTOP SIGTSTP等信号时发生,在调试时会处于这种状态。

进程间状态转换如下:
[笔记分享] [OS] Linux的进程管理

设置进程状态可用set_task_state()函数, 带内存屏障功能。也可用set_current_state()设置当前进程状态。
当一个程序执行系统调用时,处于内核运行状态,我们称为进程上下文。
另外,我们可通过list_entry, list_for_each, for_each_process来遍历进程链表,用next_task, pre_task来获取相邻进程描述符。


进程创建

和其他系统不一样,Linux创建进程通过fork()和exec()两个步骤实现。Fork()拷贝父进程的内容创建,父子进程的区别在于pid, ppid、挂起的信号及某些资源。之后exec()读取可执行文件载入地址空间运行。

Fork()采用写时拷贝的方法,就是说当真在写入的时候,才进行将地址空间拷贝到子进程。提高了快速执行的能力。
fork()、vfork()、__clone()都是调用clone()来实现进程创建的。Clone()调用do_fork()。主要流程如下:

[笔记分享] [OS] Linux的进程管理

vfork()和fork()的区别在于不拷贝父进程页表。子进程运行时,父进程阻塞直到子进程给其发送信号。


线程实现

内核把所有线程当进程来看待,只是传给clone()的参数有点区别而已。每个线程都有自己的task_struct,只是它和其他一些线程共享一些资源,如地址空间、文件系统资源、文件描述符和信号处理程序。
线程创建:
clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND, 0)
进程创建:
Clone(SIGCHILD, 0)
Vfork()创建:
Clone(CLONE_VFORK|CLONE_VM|SIGCHILD, 0)

内核线程和普通线程的区别在于其没有独立的地址空间,它们用的是前一个进程地址空间。不过他们和普通进程一样,可被调度和抢占。函数如下:

[笔记分享] [OS] Linux的进程管理


进程终结

不管进程如何终结,该任务大部分都要靠do_exit()来完成。代码如下:

[笔记分享] [OS] Linux的进程管理

至此,和进程相关资源被释放掉了,进程不可运行处于TASK_ZOMBIE状态,它所占用资源就是内核栈、thread_info和 task_struct结构。存在的目的是给父进程提供信息,等父进程检测到后,剩余资源都被释放。

在调用了wait4()系统调用之后,最终会调用release_task()来完成释放进程描述符剩余的资源。代码如下:

[笔记分享] [OS] Linux的进程管理
[笔记分享] [OS] Linux的进程管理