深入理解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_2820_YY的GCD_莫比乌斯反演
BZOJ_2820_YY的GCD_莫比乌斯反演 题意&分析: 首先f[i]非积性,但可以通过μ处理,所以我们考虑线筛 f[i*p]=μ[i*p/p']; 1.当i为质数时f[i]=1; 2.当 ...
- BZOJ_1833_[ZJOI2010]count 数字计数_数位DP
BZOJ_1833_[ZJOI2010]count 数字计数_数位DP 题意: 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 分析: 数位DP f[i][ ...
- BZOJ_5301_[Cqoi2018]异或序列&&CF617E_莫队
Description 已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l.r ,问在 [l,r] 区间内,有多少连续子 序列满足异或和等于 k . 也就是说,对于所 ...
- 发送email
package com.rjj.d; import java.security.GeneralSecurityException; import java.util.Date; import java ...
- java 关闭钩子函数的应用
Runtime.getRuntime().addShutdownHook(shutdownHook); 说明:这个方法的意思就是在jvm中增加一个关闭的钩子,当jvm关闭的时候,会执行系统中已经设置的 ...
- 【STM32H7教程】第7章 STM32H7下载和调试方法(IAR8)
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第7章 STM32H7下载和调试方法(IAR8) 本 ...
- 如何使用AWS和Azure的配置存储服务保存读取配置
原文:Want to yank configuration values from your .NET Core apps? 作者:pauljwheeler 译文:https://www.cnblog ...
- 【转】大白话讲解Promise(一)
原文地址:https://www.cnblogs.com/lvdabao/p/es6-promise-1.html ES6 Promise 先拉出来遛遛 复杂的概念先不讲,我们先简单粗暴地把Promi ...
- Docker入门(三)使用Docker Compose
Compose介绍 Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排.Compose 是一个用户定义和运行多个容器的 Docker 应用程序.在 ...
- Java笔记(day12)
包: 对类文件进行分类管理:给类提供多层命名(名称)空间:写在程序文件的第一行:类名的全称是 包名.类名包也是一种封装形式: package protected必须是成为其子类,才能继承import导 ...