第三章 进程

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

进程状态:

可运行状态(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. Angularjs interceptor

    angularJs 请求过滤 新建一个服务, $HttpProvider 中有一个 interceptore 数组,所谓的拦截器就是一个注册到该数组的工厂,该工厂在app.config() 中注入, ...

  2. 在Eclipse上Maven环境配置使用

    1. 安装配置Maven: 1.1 从Apache网站 http://maven.apache.org/ 下载并且解压缩安装Apache Maven. Maven下载地址: http://maven. ...

  3. 对图片进行索引,存入数据库sqlite3中,实现快速搜索打开

    对图片进行索引,存入数据库中,实现快速搜索打开    这个任务分为两步: 第一步:建立索引 import os import shutil import sqlite3 # 扫描函数,需扫描路径目录处 ...

  4. SpringCloud分布式微服务搭建(一)

    本例子主要使用了eureka集群作为注册中心来保证高可用,客户端来做ribbon服务提供者的负载均衡. 负载均衡有两种,第一种是nginx,F5这种集中式的LB,对所有的访问按照某种策略分发. 第二种 ...

  5. sau交流学习社区--songEagle开发系列:Vue.js + Koa.js项目中使用JWT认证

    一.前言 JWT(JSON Web Token),是为了在网络环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519). JWT不是一个新鲜的东西,网上相关的介绍已经非常多了.不是很了解的 ...

  6. asp.net core系列 48 Identity 身份模型自定义

    一.概述 ASP.NET Core Identity提供了一个框架,用于管理和存储在 ASP.NET Core 应用中的用户帐户. Identity添加到项目时单个用户帐户选择作为身份验证机制. 默认 ...

  7. 聊聊 JUC 并发包

    今天开始我们聊聊 Java 并发工具包中提供的一些工具类,本文主要从并发同步容器和并发集合工具角度入手,简单介绍下相关 API 的用法与部分实现原理,旨在帮助大家更好的使用和理解 JUC 工具类. 在 ...

  8. Asp.NetCore轻松学-部署到 Linux 进行托管

    前言 上一篇文章介绍了如何将开发好的 Asp.Net Core 应用程序部署到 IIS,且学习了进程内托管和进程外托管的区别:接下来就要说说应用 Asp.Net Core 的特性(跨平台),将 .Ne ...

  9. 简易版本vue的实现

    用了Vue也有两年时间了,一直以来都是只知其然,不知其所以然,为了能更好的使用Vue不被Vue所奴役,学习一下Vue底层的基本原理. Vue官网有一段这样的介绍:当你把一个普通的JavaScript对 ...

  10. 解决 Vue 动态生成 el-checkbox 点击无法赋值问题

    博客地址:https://ainyi.com/68 最近遇到一个问题,在一个页面需要动态渲染页面内的表单,其中包括 checkbox 表单类型,并且使用 Element 组件 UI 时,此时 v-mo ...