Linux内核进程管理
介绍:
在Linux的内核的五大组成模块中,进程管理模块时很重要的一部分。它尽管不像内存管理、虚拟文件系统等模块那样复杂。也不像进程间通信模块那样条理化,但作为五大内核模块之中的一个,进程管理对我们理解内核的运作、对于我们以后的编程很重要。同一时候。作为五大组成模块中的核心模块。它与其它四个模块都有联系。
以下就对进程模块进行想写的介绍,首先要了解进程及其相关的概念。其次介绍进程的创建、切换、撤销等基本操作。除此之外,还给出了Linux内核是怎样对进程进行调度管理的。
一、进程及其相关概念
进程:进程能够理解为程序运行的一个实例,它包括可运行程序以及与其相关的系统资源,比方打开的文件、挂起的信号、内核内部数据、处理器状态、内存地址空间及包括全局变量的数据段等。
从内核的角度看,进程也能够称为任务。
进程描写叙述符:与进程相关的事情许多。比方进程的状态、进程的优先级、进程的地址空间、同意该进程訪问的文件等等,Linux内核为此专门设计了一个类型为task_struct的结构体,称之为进程描写叙述符。进程描写叙述符中包括了内核管理进程的全部信息。能够说,仅仅要得到一个进程的进程描写叙述符,就能够知道一个进程的全部信息。
进程状态:进程描写叙述符task_struct结构体中有一个state字段,表示进程当前的所处状态。从进程的创建到进程的删除。它能够经过5种不同的状态。各自是可执行状态、可中断的等待状态、不可中断的等待状态、暂停状态、跟踪状态。
除此之外,当进程被终止时,还可能会变为僵死状态、僵死撤消状态。内核能够使用宏set_current_state(state)设置当前进程的状态,用set_task_state(task,state)设置某进程的状态。
进程标示符:进程描写叙述task_struct结构体中的pid字段能够标识唯一标识一个进程,称之为进程标识符PID。当创建一个新进程时,PID是依照顺序从小到大分配给新进程的。内核通过管理一个pidmap_array位图来表示当前已分配的PID和闲置的PID号。
注意:在多线程组中。全部的线程共享同样的PID。
除了进程标识符外,内核对进程的大部分訪问时通过进程描写叙述符指针进行的。
进程关系:进程之间的关系有亲属关系和非亲属关系。亲属关系包含父子关系和兄弟关系等。当中由tast_struct结构体中的parent/children/real_parent/sibling等字段描写叙述。
除了亲属关系外,还有其它关系,比方,一个进程是一个进程组或登录会话的领头进程,可能是一个线程组的领头进程。这些关系由group_leader/tgid/signal->pgrp等字段描写叙述。
进程资源:为了防止进程过度的使用系统资源。内核为每一个进程使用资源的数量进行了一些限制。
当中包含进程地址空间的最大数、进程使用CPU的最大时间、堆的最大值、文件大小的最大值、文件锁数量的最大值、消息队列的最大字节数、打开文件描写叙述符的最大数、进程拥有的页框最大数等。
二、进程的创建、切换、撤销
进程的创建:在Linux环境编程时,一般採用fork()函数来创建新的进程,当然。那是在用户空间的函数。它会调用内核中的clone()系统调用,由clone()函数继续调用do_fork()完毕进程的创建。
传统Unix系统中,创建的子进程复制父进程所拥有的资源,这样的方法效率低,由于子进程须要拷贝父进程的整个地址空间。
可是,子进程差点儿不必读或改动父进程拥有的全部资源,由于非常多情况下,子进程创建后会马上调用exec()一族的函数。并清除父进程细致拷贝过来的地址空间。现代Unix系统用三种方式攻克了这个问题:1、写实复制技术同意父子进程读同样的物理页。
2、轻量级进程同意父子进程共享每进程在内核的非常多数据结构。3、vfork()系统调用创建的进程能共享父进程的内存地址空间,为了防止父进程重写子进程须要的数据。堵塞父进程的运行,一直到子进程退出或运行一个新的程序为止。整个进程创建过程可能涉及到例如以下函数:
fork()/vfork()/_clone----------->clone()--------->do_fork()---------->copy_process()
上面的创建过程结束之后,就有了处于可执行状态的完整的子进程,新的子进程有了PID、进程描写叙述符等各种数据结构。要想实际执行它,还须要调度程序把CPU交给新创建的子进程。
除了进程外,还有内核线程(用kernet_thread创建)的概念。
在Linux中。内核线程与普通进程存在下面两个方面的不同:
1、内核线程仅仅执行在内核态。而普通进程既能够执行在内核态,也可执行在用户态。
2、由于内核线程仅仅执行在内核态。它仅仅使用大于PAGE_OFFSET的线性地址空间。
还有一方面。无论在用户态还是在内核态,普通进程能够用4GB的线性地址空间。
撤销进程:进程终止后,须要通知内核以便内核释放进程所拥有的资源。包含内存、打开文件以及其它资源。如信号量。进程终止的一般方式是调用exit()库函数,该函数释放C函数库所分配的资源,运行编程者所注冊的每一个函数,并结束从系统回收进程的那个系统调用。
除了进程自己终止自己外。内核能够有选择地强迫整个线程组死掉。这发生在:当进程接收到一个不能处理或忽视的信号时,或者当内核正在代表进程执行时再内核态产生一个不可恢复的CPU异常时。
有两个终止用户态应用的系统调用:exit_group()系统调用,它终止整个线程组,即整个基于多线程的应用。do_group_exit()是实现这个系统调用的主要内核函数。
exit()系统调用,它终止一个线程,而无论该线程所属线程组中的全部其它进程。do_exit()是实现这个系统调用的主要内核函数。
进程切换:进程切换又称为任务切换、上下文切换。它是这样一种行为,为了控制进程的运行,内核挂起当前在CPU上运行的进程。并恢复曾经挂起的某个进程的运行。
跟函数的调用类似。进程切换时。一般要在CPU上装载要运行进程的进程上下文。
进程的硬件上下文指:可运行程序上下文的一个子集,是进程恢复运行前装入寄存器的一组数据。
当中一部分放在TSS段。即任务状态段。剩余部分存放在内核态堆栈中。
进程的切换仅仅发生在内核态,在运行进程切换之前。用户态进程使用的全部寄存器内容都已保存在内核态堆栈上。
进程的切换有两种方法,一种是硬件切换,一种是软件切换。软件切换就是利用程序逐步运行切换,它的长处是。能够对切换时装入的数据进行合法性检查,运行时间虽与硬件切换大致同样,但仍有可改进的地方。
进程切换使用schedule()函数完毕,在本质上。每一个进程切换由两部分组成:1、切换页全局文件夹以安装一个新的地址空间。2、切换内核态堆栈和硬件上下文,由于硬件上下文提供了内核运行新进程所须要的全部信息,包含CPU寄存器。主要有switch_to函数完毕。
三、进程调度
调度策略:调度策略就是这样一组规则:决定什么时候以如何的方式选择一个新进程执行的规则。Linux的调度基于分时技术:多个进程以“时间多路复用”方式执行,由于CPU的时间被分成“片”。给每一个可执行进程分配一片。
调度策略也是依据进程的优先级对它们进行分类。在Linux中,进程的优先级是动态的。
调度程序跟踪进程正在做什么,并周期性地调整它们的优先级。依据不同的分类标准,能够把进程分成不同的类型。
比方能够把一个进程看作是“I/O受限”或“CPU受限”。也可把进程区分为下面三类:交互式进程、批处理进程、实时进程。Linux的进程是抢占式的,不管是处于内核态还是用户态。时间片的长短对系统性能是非常关键的:它既不能太长也不能太短。假设平均时间片太短。由进程切换引起的系统额外开销就变得非常高。假设平均时间片太长。进程看起来就不再是并发执行的。对时间片大小的选择始终是一种折中。
Linux採用单凭经验的方法,即选择尽可能长、同一时候能保持良好响应时间的一个时间片。
调度算法:早起的Linux中,调度算法是依据进程的优先级选择“最佳”进程来执行,它的缺点是时间开销与“可执行进程数量”有关。
现代的Linux中,调度算法能够在固定时间内(与可执行进程数量无关)选中要执行的进程。首先,我们必须知道进程能够分为实时进程与普通进程。每一个LInux进程总是依照例如以下的调度类型被调度:先进先出的实时进程、时间片轮转的实时进程、普通的分时进程。
调度算法依据进程是普通进程还是实时进程而有非常大不同。
普通进程的调度:每一个普通进程都有它自己的静态优先级(值是从100到139)。调度程序使用静态优先级来估价系统中这个进程与其它普通进程之间调度的程度。
静态优先级决定进程的基本时间片。即进程用完了曾经的时间片时。系统分配给进程的时间片长度。普通进程除了静态优先级,还有动态优先级。
动态优先级是调度程序在选择新进程来执行的时候使用的数。平均睡眠时间是进程在睡眠状态所消耗的平均纳秒数。即使具有较高静态优先级的普通进程获得了较大的CPU时间片,也不应该使静态优先级较低的进程无法执行。为了避免这个问题,提出了活动进程和过期进程的概念。活动进程指进程的时间片还未用完。过期进程指进程的时间片以用完,即使过期进程的优先级更高,也不能继续执行。除非等到全部活动进程都过期以后。
实时进程的调度:每一个实时进程都与一个试试优先级相关,实时优先级是一个范围从1到99的值。
跟普通进程不同,实时进程总是被当作活动进程。
调度程序所使用的主要数据结构:数据结构runqueue和进程描写叙述符
数据结构runqueue:runqueue数据结构中最重要的字段是与可执行进程 的链表相关的字段。当中的arrays字段是活动进程和过期进程的两个集合,active字段是指向活动进程链表的指针,expired字段是指向过期进程链表的指针。
进程描写叙述符:每一个进程描写叙述符都包含几个与调度相关的字段。当中的time_slice字段是在进程的时间片中还剩余的时钟节拍数。它由copy_process函数设置:父进程的剩余节拍数被划分为两等分,一份给父进程,一份给子进程。
四、调度程序所使用的函数
调度程序依靠几个函数来完毕调度工作。当中最重要的函数例如以下:
try_to_wake_up()函数通过把进程状态设置为TASK_RUNNING,并把该进程插入本地CPU的执行队列来唤醒睡眠或停止的进程。
recalc_task_prio()函数更新进程的平均睡眠时间和动态优先级。
schedule()憾事实现调度程序。它的任务时从执行队列的链表中找到一个进程,并随后将CPU分配给这个进程。schedule()能够由几个内核控制路径调用。能够採用直接调用或延迟调用的方式
总结:
Linux内核中的进程管理模块很重要,它是连接其它4大模块的重要桥梁,它也很复杂,理解它的一些基本原理,对于理解Linux内核很重要。上面仅仅是对它进行了一些简单的描写叙述,它没有深入到具体的实施细节,我们希望能有机会到已经能够实现在深入分析的细节。
版权声明:本文博客原创文章。博客,未经同意,不得转载。
Linux内核进程管理的更多相关文章
- Linux 内核进程管理之进程ID 。图解
http://www.cnblogs.com/hazir/tag/kernel/ Linux 内核进程管理之进程ID Linux 内核使用 task_struct 数据结构来关联所有与进程有关的数 ...
- Linux 内核进程管理之进程ID
Linux 内核使用 task_struct 数据结构来关联所有与进程有关的数据和结构,Linux 内核所有涉及到进程和程序的所有算法都是围绕该数据结构建立的,是内核中最重要的数据结构之一.该数据结构 ...
- Linux 内核进程管理之进程ID【转】
转自:http://www.cnblogs.com/hazir/p/linux_kernel_pid.html Linux 内核使用 task_struct 数据结构来关联所有与进程有关的数据和结构, ...
- Linux进程管理知识整理
Linux进程管理知识整理 1.进程有哪些状态?什么是进程的可中断等待状态?进程退出后为什么要等待调度器删除其task_struct结构?进程的退出状态有哪些? TASK_RUNNING(可运行状态) ...
- Linux内存描述之高端内存–Linux内存管理(五)
服务器体系与共享存储器架构 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...
- 【ARM-Linux开发】Linux内存管理:ARM Memory Layout以及mmu配置
原文:Linux内存管理:ARM Memory Layout以及mmu配置 在内核进行page初始化以及mmu配置之前,首先需要知道整个memory map. 1. ARM Memory Layout ...
- [转帖]linux进程管理总结
linux进程管理总结 https://www.cnblogs.com/chenfangzhi/p/10660355.html 高手总结的.. 看出来我是菜逼. 目录 一.进程相关的概念 二.关闭会话 ...
- Linux—进程管理
Linux 进程管理 1.进程管理介绍 1.1 什么是进程? 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 简而言之 ...
- 浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...
随机推荐
- Linux命令之文本处理(二)
cut命令 cut命令用来操作文件的列,能够视为列编辑器:与之相应是大多数的行"编辑器".如sed.grep.sort等,它们操作文本时,以行为单位. cut的主要功能就是输出文本 ...
- hdu1520 (树形dp)
hdu1520 http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意是给定一棵树,每个结点有一个价值,要我们选择任意个结点使得总价值最大,规则是如果父亲结 ...
- Mono+CentOS+Jexus
在.NET Core之前,实现.Net跨平台之Mono+CentOS+Jexus初体验准备工作 本篇文章采用Mono+CentOS+Jexus的方式实现部署.Net的Web应用程序(实战,上线项目). ...
- JQuery打印
jquery.jqprint-0.3.js JQuery提供的局部打印功能: <input type="button" value="打印" onclic ...
- Android 调试native的crash和anr
1. 于trace找到相应的库.例如 liba.so和相应的地址信息 2. 采用addr2line 查看 addr2line 住址 -e liba.so -f 要么 arm-eabi-addr2lin ...
- [windows phone] 教你如何使地图动画缩放
原文:[windows phone] 教你如何使地图动画缩放 说明 本篇将介绍如何将地图以动画显示呈现,在以下的范例介绍中可以看到有动画跟没动画的差别,如果你的地图还是很单调的话,不仿加上这个设计,让 ...
- bat脚本命令
注:本文转载地址 http://www.cnblogs.com/yefengmeander/archive/2011/12/01/2887978.html 1.Echo 命令 打开回显或关闭请求回显 ...
- hdu 4308 Saving Princess claire_ BFS
为了准备算法考试刷的,想明确一点即可,全部的传送门相当于一个点,当遇到一个传送门的时候,把全部的传送门都压入队列进行搜索 贴代码: #include <iostream> #include ...
- 桥模式设计模式进入Bridge
Abstraction:抽象部分的父类,定义须要实现的接口. 维护对实现部分的引用,从而把实现桥接到Implementor中去 Implementor:实现部分的接口 RefinedAbstracti ...
- 关于js中window.location.href,location.href,parent.location.href,top.location.href的使用方法
关于js中"window.location.href"."location.href"."parent.location.href".&qu ...