深入理解Linux内核 学习笔记(3)
第三章 进程
可以看到很多熟悉的结构体
进程状态:
可运行状态(TASK_ RUNNING)
进程要么在CPU上执行,要么准备执行。
可巾断的等待状态(TASK_ INTERRUPTIBLE)
进程被挂起(睡眠),直到一些条件变为真,这些条件包括:产生-个硬件巾断,释放进程正等待的系统资源,或传递一个信号,它们都能唤醒进程,即让进程的状态回到TASK RUNNING。
不可中断的等待状态(TASK_ _UNINTERRUPTIBLE)
与前一一个状态类似,但有一个例外,把信号传递到睡眼的进程不能改变它的状态。这种状态很少用到,但在一些特定的情况下这种状态是很有用的:进程必须等待,不能被中断,直到给定的事件发生。例如,当进程打开一个设备文件,其相应的设备驱动程序开始探测相应的硬件设备时会用到这种状态,探测完成以前,设备驱动程序不能被中断,否则,硬件设备会处于不可预知的状态。
暂停状态(TASK_ STOPPED)
进程的执行被暂停。当进程接收到SIGSTOP. SIGTSTP、SIGTTIN或SIGTTOU信号后,进入暂停状态。当-一个进程被另-一个进程监控时[例如debugger执行ptrace()系统调用监控-.个测试程序],任何信号都可以把这个进程置于TASK_ STOPPED 状态。
僵死状态(TASK_ ZOMBIE)
进程的执行被终止,但是,父进程还没有发布wait()类系统调用[wait(),wait3(),wait4()或waitpid()]以返回有关死进程的信息。发布wait()类系统调用前,内核不能丟弃包含在死进程描述符中的数据,因为父进程可能还需要它。(参见本章结尾的“删除进程”一节)。
Linux有两种策略选择其中之一:
TASK_ STOPPED或TASK_ ZOMB IE状态的进程不链接在专门的链表中,也没必要把它们分组,因为父进程叮以通过进程的PID,或进程间的亲属关系检索到子进程。
把TASK_ INTERRUPTIBLE或TASK_ _UNINTERRUPTIBLE状态的进程再分成很多类,每一类对应一个特定的事件。在这种情况下,进程状态提供的信息满足不了快速检索进程,因此,有必要引入另外的进程链表。这些附加的链表叫等待队列( wait queue )。
关于轻量级进程和线程:每一个轻量级进程都与一个特定的内核线程关联。内核线程只能由内核管理并像普通进程一样被调度。轻量级进程可以共享内核大部分数据结构。
进程链表:双向循环链表,链表的头是init_tash描述符,由task数组的第一个元素指向,为所有进程的祖先,称为进程0。中间为进程描述符
关于linux下的进程使用限制:
Linux下对进程执行了以下的限制:
RLIMIT_CPU
进程使用CPU的最长时间。如果进程超过了这个限制,内核就向它发-一个SIGXCPU信号,然后如果进程还不终止,再发一个SIGKILL信号(参见第九章)。
RLIMIT_FSIZE
允许文件大小的最大值。如果进程试图把一个文件的大小扩充到大于这个值,内核就给这个进程发SIGXFSZ信号。
RLIMIT_DATA
堆大小的最大值。在扩充进程的堆之前,内核检查这个值(参见第七章中“堆的管理”一节)。
RLIMIT_STACK
栈大小的最大值。在扩充进程的用户态堆栈之前,内核检查这个值(参见第七,章中" 缺页异常处理程序”一节)。
RLIMIT_CORE
内存信息转储文件的大小。当一个进程异常终止时,内核要在进程的当前目录下创建一个内存信息转储文件,在这个文件创建之前,内核检查这个值(参见第九章的“接收信号之前所执行的操作”一节)。如果这个限制为0,那么,内核就不创建这个文件。
RLIMIT_RSS
进程所拥有的页框的最大数。实际上,内核从来不检查这个值,因此,没有实现这个使用限制。
RLIMIT_NPROC ,
用户能拥有的进程最大数[参见本章“clone(), fork()及vfork()系统调用”- 节]。
RLIMIT_NOFILE
打开文件的最大数。当打开一个新文件或复制-一个文件描述符时,内核检查这个值(参见第十二章)。
RLIMIT_MEMLOCK
非交换内存的最大尺寸。当进程试图通过mlock()或mlockal1()系统调用锁住一个页框时,内核检查这个值(参见第七章巾“分配线性地址区间”--节)。
RLIMIT_AS
进程地址空间的最大尺寸。当进程使用malloc()或相关函数扩大它的地址空间时,内核检查这个值(参见第七章中“进程的地址空间”)。
对于以上的限制,每一个会有一个rlimit的结构体,如果想要修改可以看这个
|
#include <sys/resource.h> if (getrlimit(RLIMIT_NOFILE,&rlim)==0){ printf("%x\n",rlim.rlim_cur); rlim.rlim_cur=(rlim_t)4; setrlimit(RLIMIT_NOFILE,&rlim); } |
任务状态段TSS: 每个进程都有,最小长度104,每个TSS有自己的8字节任务段描述符,TSSD,如果TSSD指向当前正在CPU上运行的进程的TSS,那么Type域被置为11;否则被置为9 (注4)。Type域最低第2位叫做忙位(Busy
bit),就是这- -位区分值9和11。因为在对这一位进行修改前,处理器执行“忙锁定”,因此,多任务操作系统可以测试这一位以检查CPU是否试图切换到正在执行的进程。但是Linux没有利用这个硬件特点(参见第十一章)。
由Linux创建的TSsD存放在全局描述符表(GDT)中,GDT的基地址存放在gdtr寄存器中。tr 寄存器包含了当前正在CPU上运行的进程的TSSD选择符,也包含了两个隐藏的非编程域: TSSD的Base域和Limit域。通过这种方式,处理器就能直接对TSS寻址,而不用从GDT中检索TSS的地址。
Switch_to宏进行进程切换,这个函数作用于prev和next参数,这两个参数分别指向前一个进程的进程描述符和新进程的。这个函数的调用不同于一般函数的调用,因为__ switch _to() 从eax和edx取参数prev和next (我们在前面已看到这些参数就是保存在那里),而不像大多数函数 。这里将esi,edi,ebp保存在prev内核态堆栈中,在prev->tss.esp中保存esp的内容,以便指向内核态堆栈的顶部,会在prev->tss.eip保存标号为1的地址,恢复执行时将执行这条指令
创建进程:
clone,fork和vfork,Linux用clone{}实现了传统的fork(}系统调用,clone() 的第一个参数指定为SIGCHLD信号,并把所有的克隆标志清0,第二个参数为0。
前面描述的vfork()系统调用在Linux中是由clone()实现,c1one()的第一个参数指定为SIGCHLD信号和CLONE VM及CLONE VFORK标志,第二个参数为0.
进程0 和进程1 :
所有进程的祖先,又称swapper进程,为Linux初始化阶段由start_kernel创建,start_kernel(}函数初始化内核需要的所有数据结构,开中断,创建另一个内核线程,这个线程命名为进程1.更--般的叫法为init进程。进程1四次轮流调用kernel_thread创建常规内核任务初始化四个必要的内核线程,用于kflushd(刷新脏缓冲区内容到磁盘归还内存)十四章,kupdate(刷新旧缓冲区内容到磁盘减少文件系统不一致的风险)十四章,kpiod(把属于共享内存映射的页面交换出去)十六章,kswapd(执行内存回收功能)十六章。
深入理解Linux内核 学习笔记(3)的更多相关文章
- 深入理解Linux内核 学习笔记(1)
1.用户和用户组 每个用户是一个或多个用户组的一名成员,组由唯一的用户组标识符(user group ID)标识.每个文件的相关权限也恰好与一个组相对应. root为超级用户, 2.模块 为了达到微内 ...
- 深入理解Linux内核 学习笔记(5)
第五章 定时测量 内核必须显式地与三种时钟打交道:实时时钟(Real Time Clock, RTC).时间标记计数器(Time Stamp Counter, TSC)及可编程间隔定时器( Prog ...
- 深入理解Linux内核 学习笔记(4)
第四章 中断和异常 中断通常被分为同步中断和异步中断,同步中断是当指令执行时由CPU控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后CPU才会发出中断异步中断是由其他硬件设备依照CPU时 ...
- 深入理解Linux内核 学习笔记(2)
第二章 :内存寻址 略.基本同计算机组成原理中的讲述 内核代码和数据结构会存储在一个保留的页框中. 常规Linux安装在RAM物理地址0x00100000开始的地方.因为:页框0是由BIOS使用,存放 ...
- 深入理解Linux内核 学习笔记(8)
第八章 系统调用 API定义了一个给定的服务:系统调用是通过软中断向内核发出一个明确的请求. API可能不调用系统调用,也可能调用多个系统调用. Linux系统调用必须通过执行int 0x80,系统调 ...
- 20135316王剑桥Linux内核学习笔记
王剑桥Linux内核学习笔记 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 计算机是如何工作的 个人理 ...
- Linux内核学习笔记-2.进程管理
原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记-1.简介和入门
原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记二——进程
Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...
随机推荐
- BZOJ_3940_[Usaco2015 Feb]Censoring_AC自动机
BZOJ_3940_[Usaco2015 Feb]Censoring_AC自动机 Description FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S.他有一个包含n个 ...
- JQuery 将div中的内容替换掉
$("#div2").children().replaceWith($("#userText").val());谷歌没有效果. $("#div2&qu ...
- Shell脚本的三种执行方式
Shell脚本的执行方式可以有以下几种: 方式一: ./script.sh # 利用小数点来执行 方式二: sh script.sh 或 bash script.sh # 利用bash(sh)来执 ...
- java泛型中使用的排序算法——归并排序及分析
一.引言 我们知道,java中泛型排序使用归并排序或TimSort.归并排序以O(NlogN)最坏时间运行,下面我们分析归并排序过程及分析证明时间复杂度:也会简述为什么java选择归并排序作为泛型的排 ...
- Eclipse 出现项目没有错但是项目名称却有红色感叹号或者红叉的解决办法
错误的起因是本人因为一不小心点了下面圈出来的某一个按钮,具体记不清楚了(好像是"remove from build path"),然后整个项目变得很奇怪了,所有的包都变成了一个普通 ...
- redis一致性hash算法理解
一般算法: 对对象先hash然后对redis数量取模,如果结果是0就存在0的节点上. 1.2同上,假设有0-3四个redis节点.20个数据: 进行取模后分布如下: 现在因为压力过大需要扩容,增加一台 ...
- 简述private,protected,public,internal修饰符的访问权限
private:私有成员,在类的内部才可以访问 protected:保护成员,在类的内部和继承类中可以访问 public:公共成员,完全公开,没有访问限制 internal:当前程序集内可以访问
- openlayers4 入门开发系列之风场图篇
前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...
- 《SQL CookBook 》笔记-准备工作
目录 准备 1.建立员工表--EMP 2.建立部门表--DEPT 3.EMP表和DEPT表插入数据 4.建立透视表T1,并插入数据 5.建立透视表T10,并插入数据 第二章 shanzm 准备 1.建 ...
- python 自学之路-Day Two
Day1补充部分 模块初识 模块就是由其他人写好的功能,在程序需要的时候进行导入,直接使用,也叫库. 库有标准库和第三方库,所谓标准库,就是不需要安装就可以直接使用的,自带的:第三方库,就是需要进行下 ...