Linux进程数据结构详解
1、Linux的进程简介:
支持多线程的操作系统中,进程是资源分配的最小单位,线程是调度的基本单位。Linux是现代的32位或64位的支持多线程的操作系统,不过Linux是一种以轻量级进程作为线程,多线程任务中的数个线程以线程的组的方式存在,每个线程以轻量级进程实现。
Linux的轻量级进程没有独立的内存空间,进程有独立的内存空间,其中内核级轻量级进程没有内存空间,用户级轻量级进程共享内存空间,进程有自己的mm_struct。
事实上你可以如下理解:linux下,轻量级进程就是指线程,符合POSIX标准规范。至于创建一个线程的细节,你可以参考关于clone这个函数的介绍,除了用clone实现轻量级进程,实际上fork也是调用clone来实现的。
2、Linux进程的描述的数据结构
Linux中的进程以及轻量级进程(以下简称为线程)使用同样的描述符数据结构task_struct(可以在一定程度上理解为PCB)。
task_struct的数据成员主要有:进程状态、内核栈信息、进程使用状态、PID、优先级、锁、时间片、队列、信号量、内存管理信息、文件列表等等与进程管理、调度密切相关的信息。
详细源码参照:内核3.0.6_task_struct源码.txt文件
3、Linux的进程的组织结构、状态以及转换
Linux中,进程的组织结构是双向链表的形式,task中有prev和next的指针,其中链表表头head的位置是0号进程或者说是swapper进程的task_struct。SET_LINKS 和 REMOVE_LINKS 宏分别用于从进程链表中插入和删除一个进程描述符。这些宏考虑了进程间的父子关系。,
进程状态转换图:
◆运行状态(TASK_RUNNING)
当进程正在被CPU执行,或已经准备就绪随时可由调度程序执行,则称该进程为处于运行状态(running)。进程可以在内核态运行,也可以在用户态运行。当系统资源已经可用时,进程就被唤醒而进入准备运行状态,该状态称为就绪态。这些状态(图中中间一列)在内核中表示方法相同,都被成为处于TASK_RUNNING状态。
◆可中断睡眠状态(TASK_INTERRUPTIBLE)
当进程处于可中断等待状态时,系统不会调度该进程执行。当系统产生一个中断或者释放了进程正在等待的资源,或者进程收到一个信号,都可以唤醒进程转换到就绪状态(运行状态)。
◆不可中断睡眠状态(TASK_UNINTERRUPTIBLE)
与可中断睡眠状态类似。但处于该状态的进程只有被使用wake_up()函数明确唤醒时才能转换到可运行的就绪状态。
◆暂停状态(TASK_STOPPED)
当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可运行状态。在Linux 0.11中,还未实现对该状态的转换处理。处于该状态的进程将被作为进程终止来处理。
◆僵死状态(TASK_ZOMBIE)
当进程已停止运行,但其父进程还没有询问其状态时,则称该进程处于僵死状态。
当一个进程的运行时间片用完,系统就会使用调度程序强制切换到其它的进程去执行。另外,如果进程在内核态执行时需要等待系统的某个资源,此时该进程就会调用sleep_on()或sleep_on_interruptible()自愿地放弃CPU的使用权,而让调度程序去执行其它进程。进程则进入睡眠状态(TASK_UNINTERRUPTIBLE或TASK_INTERRUPTIBLE)。
只有当进程从“内核运行态”转移到“睡眠状态”时,内核才会进行进程切换操作。在内核态下运行的进程不能被其它进程抢占,而且一个进程不能改变另一个进程的状态。为了避免进程切换时造成内核数据错误,内核在执行临界区代码时会禁止一切中断。
4、0号进程的秘密
传说中的swapper进程,其描述符是提前设计好的,进程0创建时,系统设置了时钟,便于进程的调度轮询,process0,以下简称p0。p0具备处理系统调用,这需要通过set_system_gate和system_call(系统调用的总入口)与IDT挂接。
此外,p0还需要与task[64]、GDT、LDT、TSS挂接,并把优先级由0调整为3。Linux规定所有进程(p0除外)必须有其他进程在3特权级别下创建。因而p0需要调用move_to_user_mode()进行优先级翻转。
优先级翻转在响应中断时完成,在响应中断时,系统的各个寄存器的数据按顺序压栈(SS、ESP、EFLAGS、CS、EIP),恢复时按照反序出栈,在相应中断过程中,set_system_gate就是设置int 0x80中断,由3级(iret)反转到0级(iret),同理也可以由0级(iret)翻转到3级(iret)。注:
0级:执行系统代码
3级:执行进程代码
0号进程不是由3级翻转到0级的,没有预先的压栈数据,所以要手工模拟压栈,表示该属性的ss字段的后两位必须是11(3),总值:0x17。
5、1号与2号进程
1号进程由0号进程创建,2号进程由1好进程创建。
2号进程的执行,将意味着shell开始执行,boot过程结束,设备实现怠速。
创建进程过程:
(1)调用fork()函数:
将相应的信息压栈:以便于调用copy_process后初始化p1的TSS。压栈:fork函数偏移值(2)赋给eax,SS、ESP、EFLAGS、CS、EIP入栈,然后DS、ES、FS、EDX、ECX、EBX入栈。
(2)开始执行fork()
在task[64]除[0]以外的数组项初始化清空,调用下面的函数:find_empty_process()获得一个PID和数组中的一个位置。接下来在父进程的内核中继续压栈,5个寄存器的值入栈,为调用copy_process()做准备。
(3)调用copy_process()
创建子进程的task_struct;
复制父进程的task_struct信息到子进程的task_struct之中;
为子进程做struct和tss的个性化设置;
创建子进程的页表,复制父进程页表项到子进程;
共享文件;
设置GDT,将子进程的状态设置为就绪;
注:task_struct和内核栈共同构成task_union:正好占据一页。
Linux进程数据结构详解的更多相关文章
- linux进程地址空间详解(转载)
linux进程地址空间详解(转载) 在前面的<对一个程序在内存中的分析 >中很好的描述了程序在内存中的布局,这里对这个结果做些总结和实验验证.下面以Linux为例(实验结果显示window ...
- Linux进程退出详解(do_exit)--Linux进程的管理与调度(十四)
Linux进程的退出 linux下进程退出的方式 正常退出 从main函数返回return 调用exit 调用_exit 异常退出 调用abort 由信号终止 _exit, exit和_Exit的区别 ...
- linux进程控制函数详解
进程控制 fork函数 创建一个子进程. pid_t fork(void); 失败返回-1:成功返回:① 父进程返回子进程的ID(非负) ②子进程返回 0 pid_t类型表示进程ID,但为了表示-1, ...
- Linux进程管理详解
何谓进程?进程,就是正在执行的一个程序或命令,每一个进程都是一个运行实体,有自己的地址空间,并占用一定的系统资源.简而言之,进程就是运行中的程序.在Linux中,诸如ls等命令都是进程,只不过某些命令 ...
- Linux /dev目录详解和Linux系统各个目录的作用
Linux /dev目录详解(转http://blog.csdn.net/maopig/article/details/7195048) 在linux下,/dev目录是很重要的,各种设备都在下面.下面 ...
- linux select函数详解
linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...
- 红帽Linux故障定位技术详解与实例(2)
红帽Linux故障定位技术详解与实例(2) 2011-09-28 14:26 圈儿 BEAREYES.COM 我要评论(0) 字号:T | T 在线故障定位就是在故障发生时, 故障所处的操作系统环境仍 ...
- Linux启动过程详解(inittab、rc.sysinit、rcX.d、rc.local)
启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬 ...
- Linux启动过程详解
Linux启动过程详解 附上两张图,加深记忆 图1: 图2: 第一张图比较简洁明了,下面对第一张图的步骤进行详解: 加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的 ...
随机推荐
- Web下的整体测试 --性能测试及优化思路
随着Internet的日益普及,现在基于B/S结构的大型应用越来越多,可如何对这些应用进行测试成为日益迫切的问题.有许多测试人员来信问我B/S的测试如何做,由于工作较繁忙,对大家提出的问题也是头痛医头 ...
- ubuntu 16.04 安装pycharm
Ubuntu16.04下安装Cuda8.0+Caffe+TensorFlow-gpu+Pycharm过程(Simple) ubuntu 16.04 安装pycharm 1.安装java jdk 直接 ...
- (转)Hdmi edid 数据解析
Hdmi edid 数据解析 (转自:http://blog.chinaunix.net/uid-20672559-id-3384035.html) 一.EDID数据格式: EDID 1.3 d ...
- par函数的ann 参数-控制图片的注释信息
ann 参数控制图片的x轴和y轴标签以及标题是否显示 默认值为TRUE, 所以图片有对应的信息时,会显示出来,代码示例 plot(1:5, 1:5, main = "title", ...
- python 脚本检测python 版本
通过sys 模块的sys_info可以返回当前python 的版本信息, 其返回值是一个元组, 比如(2, 6, 6, 'final', 0); 表示当前版本为2.6.6 , 我们可以利用这个变量的值 ...
- 【Java集合的详细研究2】浅谈Arrays.asList的使用
首先,该方法是将数组转化为list.有以下几点需要注意: (1)该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean) (2)该方法将数组与列表 ...
- error C2065: “m_Pic”: 未声明的标识符
public: CPicture m_Pic; 要写在头文件里! 而不能是cpp文件的public里!
- Centos6.5 安装配置docker
宿主机:win7 64位 vagrant封装环境运行在VirtualBox 虚拟机上CentOS6.5,这是做测试时的一个环境,顺便错用安装docker玩玩. centos6.5可以直接安装d ...
- c++虚函数表 Brew VTBL
参考:http://blog.csdn.net/haoel/article/details/1948051/ BREW VTBL:http://blog.chinaunix.net/uid-51740 ...
- Android 6.0启动过程具体解析
在之前的一篇文章中.从概念上学习了Andoird系统的启动过程.Android系统启动过程学习 而在这篇文章中,我们将从代码角度细致学习Android系统的启动过程,同一时候,学习Android启动过 ...