写在前面
这是一篇十分简短的文章,主要讲述了进程的基本概念,如何创建进程以及一些细节问题,为接下来学习进程调度打好基础。
什么是进程
简单来说,进程就是运行中的程序。比如,我们双击了存放在硬盘中的某个exe程序,程序被加载到内存中运行起来后,就是所谓的进程。所以我们很自然的想到,进程中一定有可执行的代码,这些代码需要对一些数据进行操作,所以进程中还保存有需要使用的数据。由于代码和数据等东西最终都会保存到内存中,我们就把这些东西称为进程的地址空间。
有一些硬件基础的读者可能会想,进程可能还有各种硬件状态,比如各种寄存器中保存的值。最后,进程可能会进行一些I/O操作,所以进程中可能还有一些打开的文件。综上所述,一个进程由以下内容构成:
- 地址空间
- 寄存器
- I/O信息
进程的创建
要创建进程,就需要使用操作系统提供的API。例如,在UNIX中创建进程需要使用fork
,在Windows中需要使用CreateProcess
。fork
会创建一个与父进程一模一样的子进程,它们通过写时复制的机制共享同一个内存空间(也就是父进程的内存空间),除非子进程调用了exec
族函数或者修改了共享内存空间中的内容。而使用CreateProcess
,父进程和子进程的内存空间在一开始就是不一样的。
关于不同操作系统提供的创建进程的API的具体使用请读者自行查阅相关文档。
一般来说,在创建进程时,操作系统会执行以下步骤:
- 将代码和所有静态数据(例如初始化变量)加载(load)到内存中,加载到进程的地址空间中。现代操作系统惰性执行该过程,这涉及到分页和交换机制。
- 操作系统为运行时栈分配内存。
- 操作系统为程序的堆分配内存。
- 执行一些其它的初始化。
- 启动程序。
进程的状态
进程有三种状态:
- 运行
- 就绪
- 阻塞
运行状态很好理解,CPU正在执行该进程中的指令。就绪状态是指进程可以运行,但因为其他进程正在运行而暂时停止。阻塞状态下的进程博不可以运行,比如进程正在执行一些I/O操作,例如等待数据的输入。
从上图中我们不难发现,进程是可以在不同状态之间切换的,如果我们在一个进程阻塞的时候,转而运行另一个进程,这样就可以大大提高CPU的利用效率,我们称之为进程调度。为了调度进程,我们需要一个进程调度器,这一般由操作系统担任。操作系统根据某种调度算法来决定何时运行哪一个进程,进程可以运行多久。
在下一篇文章中,我将详细介绍进程调度机制。