前言
- 本文是对进程的总体概述,具体细节会在后面几篇文章分别介绍
- 进程描述符task_struct介绍,见文章:https://www.daimajiaoliu.com/series/linux_kernel/4797f752c1003f8
- 进程的创建与终结介绍,见文章:https://www.daimajiaoliu.com/series/linux_kernel/4797d2ce7900402
- 线程介绍,见文章:https://www.daimajiaoliu.com/series/linux_kernel/479938c58900402
一、进程概述
- 进程就是处于
执行期的程序(目标码存放在某种存储介质上)
- 但进程并
不仅仅局限于一段可执行程序代码(Unix称其为代码段,text section)。通常进程
还要包含其他资源,像打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程(thread of execution),当然还包括用来存放全局变量的数据段等。实际上,进程就是正在执行的程序代码的实时结果。内核需要有效而又透明地管理所有细节
- 进程的另一个名字是任务(task)。Linux内核通常把进程也叫做任务
二、线程概述
- 执行线程,简称线程(thread),是
在进程中活动的对象
- 每个线程都拥有一个独立的程序计数器、进程栈和一组进程寄存器
- 内核调度的对象是线程,而不是进程
- 在传统的Unix系统中,一个进程只包含一个线程,但现在的系统中了包含多个线程的多线程程序司空见惯
- 在后面介绍现成的文章中你会看到,Linux系统的线程实现非常特别:它对线程和进程并不特别区分。对Linux而言,线程只不过是一种特殊的进程罢了
三、虚拟机制(虚拟处理器、虚拟内存)
- 在现代操作系统中,进程提供两种虚拟机制:
虚拟处理器和虚拟内存
- 有趣的是,注意在
**线程之间可以共享虚拟内存,但每个都拥有各自的虚拟处理器(**这里是指包含在同一个进程中的线程
)
虚拟处理器
- 虽然实际上可能是
许多进程正在分享一个处理器,但虚拟处理器给进程一种假象,让这些进程觉得自己在独享处理器
- 在后面的文章我们会详细描述这种虚拟机制
虚拟内存
- 而虚拟内存让进程在分配和管理内存时觉得自己拥有整个系统的所有内存资源
- 在后面的文章我们会详细描述这种虚拟机制
四、进程创建
- 程序本身并不是进程,进程是处于执行期的程序以及相关的资源的总称。实际上,完仝可能存在两个或多个不同的进程
执行的是同一个程序。并且两个或两个以上并存的
进程还可以共享许多诸如打开的文件、地址空间之类的资源
进程的创建(fork、vfork)
- 无疑,进程在创建它的时刻开始存活。在Linux系统中,这通常是调用fork()系统的结果,
该系统调用通过复制一个现有进程来创建一个全新的进程。调用fork()进程称为父进程,新产生的进程称为子进程。在该调用结束时,在返回点这个相同位置上,父进程恢复执行,子进程开始执行
- **fork()系统调用从内核返回两次:**一次回到父进程,另一次回到新产生的子进程
- 通常,创建新的进程都是为了立即执行新的、不同的程序,而接着
调用exec()这组函数就可以创建新的地址空间,并把新的程序载入其中
- 在现代Linux内核中,
fork()实际上是由clone()系统调用实现的**(在后面文章介绍)**
五、进程的退出
- 最终,
程序通过exit()系统调用退出执行。这个函数会终结进程并将其占用的资源释放掉
- 父进程可以
通过wait4()系统调用查询子进程是否终结,这其实使得进程拥有了等待特定进程 执行完毕的能力。(
**备注:**wait4()是内核实现的系统调用,Linux通过C库提供了wait()、waitpid()、wait3()、wait4()函数。虽然语义有差别,但所有函数都返回关于终止进程的状态)
- 进程退出执行后
被设置为僵死状态,直到它的父进程
**调用wait()或 waitpid()**为止