关闭

Linux进程管理:核心调度CPU

标签: linux内核
263人阅读 评论(0) 收藏 举报
分类:

在我的理解中,操作系统是上帝写好的代码,人之一生爱恨情仇都是操作系统控制下死循环。如果说进程是CPU的抽象,那么人一生的开始就是多进程循环往复的开始。没有开始,没有终结。

那么,什么是进程呢?

程序不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。进程和程序的区别在于:程序是指令的集合,是程序的静态描述。而进程是动态的一次活动的执行。

Linux 系统中同时运行着大量的进程,ubuntu 在shell 终端中输入ps -ef 命令时,如图。


PID是指进程的标识号,是系统赋予每一个进程的唯一标识号。最后一列CMD是正在执行的进程的名称。

这么多进程,他们之间关系如何呢?

系统允许一个进程创建新的进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树的结构模型。整个linux 系统的所有进程也就是一个树型结构。如上图,每个进程对应一个PID 和一个PPID ,在我们的程序里可以通过getpid 和get ppid 函数来获取。在我们的程序里可以通过getpid和getppid函数获取,PID标识了进程本身,而PPID标识了父进程,所有进程的PPID一层层往上推最终都会汇集到0。在我看来,这就是上帝赋予人类的宇宙第一推动力。

树根是系统自动构造的,即在内核态下执行的0号进程,它是所有进程的祖先。由0号进程创建1号进程(内核态),1号负责执行内核的部分初始化工作及进行系统配置,并创建若干个用于高速缓存和虚拟主存管理的内核线程。随后,1号进程调用execve()运行可执行程序init,并演变成用户态1号进程,即init进程。上述过程可描述为:0号进程->1号内核进程->1号用户进程(init进程)->getty进程->shell进程。

注意,上述过程描述中提到:1号内核进程调用执行init并演变成1号用户态进程(init进程),这里前者是init是函数,后者是进程。


大概了解完什么是进程,进程间的关系,祖先进程,进程树以后,那么我们会问,进程是如何运行的,进程是如何进行内存操作以及文件操作的呢?

那么,程序运行在操作系统之上,当他们要访问硬件(内存、磁盘)的时候,就要借助于操作系统,因为应用程序不能直接访问。CPU里面有一个MMU(内存管理单元),虚拟出内存的映射表,给每一个进程分配了4G空间的虚拟地址,从而实现了把虚拟地址逐一映射到物理地址上的机制。其中,每一个虚拟的4G包括了3G的用户空间(代码区、全局变量、局部变量、堆、栈)和1G的内核空间。MMU的具体实现相当于VA(x,y)=PA。

在实际上,进程=资源提+调度能力,也就是说,一个task_struct和一个memory map(地址空间映射表)表示一个进程。每一个进程都占据独立的资源空间和地址映射。

但是,每一个时刻只有一个进程占据着CPU。在多道编程中,我们允许各个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是可以提高CPU 的利用率,让每个用户可以感觉到自己可以独享CPU。如同,一个人开起来可以同时处理多件事情一样。所以一般来说,进程分为了以下的几种状态:

这里写图片描述

(1)、就绪态: 进程已经获得了除cpu以外的所有其它资源,在就绪队列中等待cpu调度; 
(2)、执行状态: 已经获得cpu以及所有需要的资源正在运行; 
(3)、阻塞状态(等待状态): 进程因等待所需要的资源而放弃处理器,或者进程本来就不拥有处理器,且其它资源也没有满足;

Linux将一个个进程抽象为一个个任务,并定义了一个结构体task_struct用于表示一个任务(也称为进程PCB),保存了内核用于管理进程所需要的重要信息,包括了进程管理中最重要的进程描述符,也是task_struct结构体存储相关的信息,在linux/sched.h文件里定义。那么我们先看看linux内核3.0.8版本的task_struct结构体的定义。一个task_struct主要包含以下这些域:

(1)、调度参数:进程优先级,已使用的CPU时间,已休眠的时间,用于系统决定调度哪个进程执行; 
(2)、内存镜像:指向进程text,data,stack或page table的指针; 
(3)、信号:指定哪些信号将被处理,哪些信号将被忽略等; 
(4)、寄存器:进程切换至内核模式时,用于保存当前正在运行的寄存器信息; 
(5)、系统调用状态:保存当前系统调用的信息,包括参数,结果等; 
(6)、文件描述符表:保存进程打开的文件的i-node数据; 
(7)、统计信息:记录了进程使用cpu时间,栈空间大小,分页帧数等; 
(8)、内核栈空间:本进程专属的内核栈空间地址; 
(9)、其他:当前进程状态,正在等待的事件,进程ID,父进程ID,用户ID等信息。

Linux内核提供了一种/proc文件系统,在运行时访问内核内部的数据结构。他是一个伪文件系统,只存在内存中,而不占用硬盘空间。同事他以文件系统的方式去访问系统内核数据结构的操作提供接口。以数字命名的目录,这些事进程目录,当前运行的每一个进程都有对应的一个目录在/proc下,以进程的PID号作为目录号,他们是读取进程信息的接口。

说完了进程,就到线程了。这里不再赘述线程本身,运维之道多与架构,以及问题有关。不过,进程与线程的关系如下:

(1)、进程是资源分配的基本单位,不同进程内存映射表不同,相互独立,互不影响; 
(2)、线程是任务执行的基本单位,多个线程共享进程的内存映射表,同步或者互斥。


这里写图片描述
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7323次
    • 积分:148
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类