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信息是如此的 ...
随机推荐
- Spark SQL怎么创建编程创建DataFrame
创建DataFrame在Spark SQL中,开发者可以非常便捷地将各种内.外部的单机.分布式数据转换为DataFrame.以下Python示例代码充分体现了Spark SQL 1.3.0中DataF ...
- 《FPGA全程进阶---实战演练》第三章之接地设计
信号回路的电位基准点,(直流电源的负极或者零伏点)在单板上可以分为数字地和模拟地.理想的工作地是电路参考点的等电位平面,然而在实际中,工作地被认为信号电流的低阻抗回路和电源的供电回路,这样就会有三个方 ...
- android 内存管理机制、异常、垃圾回收
当 Android 应用程序退出时,并不清理其所占用的内存,Linux 内核进程也相应的继续存在,所谓“退出但不关闭”.从而使得用户调用程序时能够在第一时间得到响应. 当系统内存不足时,系统将激活内存 ...
- Struts2学习笔记(OGNL表达式)
Struts 2支持以下几种表达式语言: OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言: JSTL(JSP Standard T ...
- Extracting and composing robust features with denosing autoencoders 论文
这是一篇发表于2008年初的论文. 文章主要讲了利用 denosing autoencoder来学习 robust的中间特征..进上步,说明,利用这个方法,可以初始化神经网络的权值..这就相当于一种非 ...
- e646. 处理鼠标点击事件
component.addMouseListener(new MyMouseListener()); public class MyMouseListener extends MouseAdapter ...
- e640. 使一个组件可拖动
This example demonstrates the code needed to make a component draggable. The object being transferre ...
- 一键部署MongoDB集群Windows版
由于周末在家手头没有虚拟机,所以在windows下单机完毕部署要求,并编写bat执行脚本. 1.创建配置文件及相关文件夹 总的启动脚本例如以下(startmc.bat): rem m1 start m ...
- 转载:15个最受欢迎的Python开源框架
出自:http://python.jobbole.com/72306/?replytocom=57112 15个最受欢迎的Python开源框架 Django: Python Web应用开发框架 Dja ...
- 通过json传递图片(base64编码)
程序一: 后台代码: public ActionResult Index() { FileStream fs = new FileStream("e:\\file\\psb.jpg" ...