第三章 进程

可以看到很多熟悉的结构体

进程状态:

可运行状态(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)的更多相关文章

  1. 深入理解Linux内核 学习笔记(1)

    1.用户和用户组 每个用户是一个或多个用户组的一名成员,组由唯一的用户组标识符(user group ID)标识.每个文件的相关权限也恰好与一个组相对应. root为超级用户, 2.模块 为了达到微内 ...

  2. 深入理解Linux内核 学习笔记(5)

    第五章  定时测量 内核必须显式地与三种时钟打交道:实时时钟(Real Time Clock, RTC).时间标记计数器(Time Stamp Counter, TSC)及可编程间隔定时器( Prog ...

  3. 深入理解Linux内核 学习笔记(4)

    第四章 中断和异常 中断通常被分为同步中断和异步中断,同步中断是当指令执行时由CPU控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后CPU才会发出中断异步中断是由其他硬件设备依照CPU时 ...

  4. 深入理解Linux内核 学习笔记(2)

    第二章 :内存寻址 略.基本同计算机组成原理中的讲述 内核代码和数据结构会存储在一个保留的页框中. 常规Linux安装在RAM物理地址0x00100000开始的地方.因为:页框0是由BIOS使用,存放 ...

  5. 深入理解Linux内核 学习笔记(8)

    第八章 系统调用 API定义了一个给定的服务:系统调用是通过软中断向内核发出一个明确的请求. API可能不调用系统调用,也可能调用多个系统调用. Linux系统调用必须通过执行int 0x80,系统调 ...

  6. 20135316王剑桥Linux内核学习笔记

    王剑桥Linux内核学习笔记 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 计算机是如何工作的 个人理 ...

  7. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  8. Linux内核学习笔记-1.简介和入门

    原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  9. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

随机推荐

  1. i春秋——Misc之百度杯

    今天心里很是不开森,想想往日何必那么努力呢?不如你的比比皆是,可是人家就是因为有关系,你又能怎样呢? 你所有应该有的都被打翻了,别灰心,至少你曾经努力过! 愿我未来的学弟学妹们都能一直开开心心的过好每 ...

  2. js继承之组合继承(结合原型链继承 和 借用构造函数继承)

    在我的前两篇文章中,我们已经介绍了 js 中实现继承的两种模式:原型链继承和借用构造函数继承.这两种模式都存在各自的缺点,所以,我们考虑是否能将这二者结合到一起,从而发挥二者之长.即在继承过程中,既可 ...

  3. BootStrap:轮播插件

    前述 利用 BootStrap 实现图片轮播,包括 基本轮播.带标题的轮播.设置轮播速度的轮播.控制前后的轮播 实例 基本轮播 代码 1.引入bootstrap和jQuery文件 <!-- jQ ...

  4. [PHP] debug_backtrace()可以获取到代码的调用路径追踪

    查看代码的时候,看到有使用这个函数,测试一下 1.debug_backtrace()可以获取到代码的调用追踪,以数组形式返回 2.debug_print_backtrace() — 打印一条回溯,直接 ...

  5. 深入浅出—Redis集群的相关详解

    前言: 这篇文章主要介绍了Redis集群的相关,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值. 注意!要求使用的都是redis3.0以上的版本,因为3.0以上增加了red ...

  6. openlayers4 入门开发系列之地图属性查询篇(附源码下载)

    前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...

  7. .NET Framework和 .Net Core实现不一致的API之 `EmailAddressAttribute`

    .NET Framework和 .Net Core实现不一致的API之 EmailAddressAttribute Intro 现在我们的类库项目大多是 NETStandard2.0 项目,但是 ne ...

  8. PostgreSQL 10.7 linux 主从配置

    PostgreSQL 10.7 主从安装 硬件环境 云服务商:华为云 Linux: CentOS7.1 工具:Xshell Xftp IP:114.115.251.168 Port: 5432 543 ...

  9. Django-CSRF跨站请求伪造防护

    前言 CSRF全称Cross-site request forgery(跨站请求伪造),是一种网络的攻击方式,也被称为“One Click Attack”或者Session Riding,通常缩写为C ...

  10. 数据库优化案例——————某知名零售企业ERP系统

    写在前面 记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也分享自己做的优化案例. 之前分享过OA系统.H ...