一、Linux下多任务机制的介绍
Linux有一特性是多任务,多任务处理是指用户可以在同一时间内运行多个应用程序,每个正在执行的应用程序被称为一个任务。
多任务操作系统使用某种调度(shedule)策略(由内核来执行)支持多个任务并发执行。事实上,(单核)处理器在某一时刻只能执行一个任务。每个任务创建时被分配时间片(几十到上百毫秒),任务执行(占用CPU)时,时间片递减。操作系统会在当前任务的时间片用完时调度执行其他任务。由于任务会频繁地切换执行,因此给用户多个任务运行的感觉。所以可以说,多任务由“时间片 + 轮换”来实现。多任务操作系统通常有三个基本概念:任务、进程和线程,现在,我们先学习进程:
进程的基本概念
进程是指一个具有独立功能的程序在某个数据集合上的动态执行过程,它是操作系统进行资源分配和调度的基本单元。简单的说,进程是一个程序的一次执行的过程。
进程具有并发性、动态性、交互性和独立性等主要特性。
进程和程序是有本质区别的:
1)程序( program )是一段静态的代码,是保存在非易失性存储器(磁盘)上的指令和数据的有序集合,没有任何执行的概念;
2)进程( process )是一个动态的概念,它是程序的一次执行过程(在RAM上执行),包括了动态创建、调度、执行和消亡的整个过程,它是程序执行和资源管理的最小单位。
这里,我们可以看到,进程由两部分组成:内存地址空间 + task_struct ,task_struct 下面我们会讲到,内存地址空间就是我们程序在内存中运行(进程)时所开辟的4GB虚拟地址空间,用于存放代码段、数据段、堆、栈等;
从操作系统的角度看,进程是程序执行时相关资源的总称。当进程结束时,所有资源被操作系统回收。
Linux系统中主要包括下面几种类型的过程:
1)交互式进程;
2)批处理进程;
3)守护进程;
Linux下的进程结构
进程不但包括程序的指令和数据,而且包括程序计数器和处理器的所有寄存器以及存储临时数据的进程堆栈。
因为Linux是一个多任务的操作系统,所以其他的进程必须等到操作系统将处理器的使用权分配给自己之后才能运行。当正在运行的进程需要等待其他的系统资源时,Linux内核将取得处理器的控制权,按照某种调度算法将处理器分配给某个等待执行的进程。
在上面介绍程序和进程的区别时,我们看到进程除了内存地址空间以外,还有个结构体task_struct,内核将所有进程存放在双向循环链表(进程链表)中,链表的每一项就是这个结构体task_struct,称为进程控制块的结构。该结构包含了与一个进程相关的所有信息,在linux内核目录下<include / Linux / sched.h>文件中定义。task_struct内核结构比较大,它能完整地描述一个进程,如进程的状态、进程的基本信息、进程标示符、内存的相关信息、父进程相关信息、与进程相关的终端信息、当前工作目录、打开的文件信息,所接收的信号信息等。
下面详细讲解task_struct结构中最为重要的两个域:stat (进程状态) 和 pid (进程标示符)。
1、进程状态
Linux中的进程有以下几种主要状态:运行状态、可中断的阻塞状态、不可中断的阻塞状态、暂停状态、僵死状态、消亡状态,它们之间的转换关系如下:
1)运行态(TASK_RUNNING):进程当前正在运行,或者正在运行队列中等待调度(排队中);
2)等待态_可中断(TASK_INTERRUPTIBLE):进程处于阻塞(睡眠sleep,主动放弃CPU)状态,正在等待某些事件发生或能够占用某些资源。处于这种状态下的进程可以被信号中断。接收到信号或被显式地唤醒呼叫(如调用wake_up系列宏:wake_up、wake_up_interruptible等)唤醒之后,进程将转变为运行态,继续排队等待调度;
3)登台态_不可中断(TASK_UNINTERRUPTIBLE):此进程状态类似于可中断的阻塞状态(TASK_INTERRUPTIBLE),只是他不会处理信号,把信号传递到这种状态下的进程不能改变它的状态,即不可被信号所中断,不能被随便调度。在一些特定的情况下(进程必须等待,知道某些不能被中断的事件发生),这种状态是很有用的。只有在它等待的事件发生时,进程才被显示地唤醒呼叫唤醒,进程将转变为运行态,继续排队等待调度;
4)停止态(TASK_STOPPED),即暂停状态,进程的执行被暂停,当进程受到SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU等信号,就会进入暂停状态,知道收到继续执行信号,转变为运行态,继续排队等待调度;
5)僵尸态(EXIT_ZOMBIE)&#x