Linux进程管理(一)

  声明 : 本文仅代表个人理解,如若有错误的地方,欢迎留言指正,感谢观看。

  进程简述 : 进程是处于执行期的程序以及相关资源的总称,是管理资源的最小单位。

  线程简述 : 线程是进程中活动的对象,是调度的最小单位。每个线程都拥有一个独立的程序计数器,栈,和寄存器状态组

  对于 Linux 内核实现而言, 并不特别区别线程,线程只不过是一种特殊的进程而已(特殊点主要在于除栈以外的进程空间),但为了分辨,后续 进程 不包含线程,如若是 进程线程的共性则以 进程/线程 来称呼。

  进程/线程运行的三种条件 :

    虚拟处理器 : 调度以线程为单位,虚拟处理器可以给线程自己独享一个寄存器的错觉(主要依赖每个线程都拥有一个独立的程序计数器,栈,和寄存器状态组,在调度时,会保存上一个线程的程序计数器,栈与寄存器状态组,致使不同的线程可以执行不同的代码)。 

    虚拟内存 : 虚拟内存对于进程之间而言是独享的(每个进程都拥有自己的虚拟内存),对于同一进程下的多个线程而言是共享的

    IO设备 : 多种类型的IO设备 通过 VFS(虚拟文件系统)层 给进程/线程提供了统一的通用IO接口,这种统一的IO接口使上层调用更加便捷,隐藏了底层的实现。

  进程的核心操作

    进程的创建 : 进程通常是调用 fork()系统调用 的结果, fork 通过复制一个现有进程来创建一个全新的进程。调用 fork 的称为 父进程, 新产生的称为 子进程。如若复制成功 fork 从内核态返回两次(因为是复制创建新进程,因此复制结束后,需要修改执行返回值来分辨哪个是父进程哪个是子进程),一次返回 0 到子进程,一次返回 子进程PID 到父进程。如若失败则返回一次,返回 -1 给父进程。

    进程执行其他程序 : exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。 

    进程的退出 : 程序通过 exit() 系统调用退出执行(也可能是CRT在main函数返回后隐式调用)。 这个函数会终结进程并将其占用的资源释放。

  如何用数据结构描述进程 ?

    Linux通过 task_struct(进程描述符) 来表示一个进程/线程。task_struct包含进程打开的文件,地址空间,挂起的信号,进程状态,以及其他更多信息。如若 两个task_struct 分别表示一个进程下的两个线程,则他们 打开的文件,地址空间(具体为 mm_struct )一定是相同的。

  进程描述符放在哪里 ?

    进程描述符放在虚拟内存的内核空间,由 slab 分配器(slab是位于内核空间的一个内存池)管理,并且在进程的内核空间栈顶或栈底(对于linux而言,每个进程/线程有两个栈,一个是用户空间的栈,一个是内核空间的栈)创建一个 struct thread_info 来指向这个 struct task_struct(这样做是为了方便找到 task_struct)。

    在Linux内核2.6版本之前,没有 struct thread_info, task_struct 也不由 slab 分配器管理,而是在创建了 进程的内核空间栈后, 直接在栈顶或栈底创建一个 task_struct。

原文地址:https://www.cnblogs.com/vizdl/p/14333017.html