首页
|
Linux 基础
|
资讯动态
|
Linux 应用
|
Linux 服务器
|
Linux 开发
|
Linux 安全
|
专题
|
联盟论坛
当前位置:
主页
>
Linux 开发
>
linux 内核
>文章内容
深入学习LINUX内核之七(图文讲解)
来源:http://www.unix5.com 作者:riechelr_hl 发布时间:2008-04-15
暂停状态 (TASK_STOPPED)
当行程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让行程转换到可执行状态。行程在除错期间接收到任何信号均会进入该状态。在Linux 0.12中,还未实现对该状态的转換处理。处於该状态的行程将被作为行程终止来处理。
僵死状态(TASK ZOMBIE)
当行程已停止执行,但其父行程还沒有呼叫wait ( )询问其状态时,则称该行程处於僵死状态。为了了让父行程能夠获取其停止其执行的资讯,此时子行程的任务资料结构资讯还需要保留着。一旦父行程呼叫wait ( )取得了子行程的资讯,则处於该状态行程的任务资料结构就会被释放掉。
当一个行程的执行时间片用完,系统就会使用调度程式強制切換到其他的行程去执行。另外,如果行程在內核态执行时需要等待系统的某个资源,此时该行程就会呼叫sleep_on( )或interruptible_sleep_on 自愿地放棄CPU的使用权,而让调度程式去执行其他行程。行程则进入睡眠状态(TASK_UNINTERRUPTIBLE或TASK_INTERRUPTIBLE)。
只有当行程从“內核执行态”转移到“睡眠状态”时,內核才会进行行程切換操作。在內核态下执行的行程不能被其他行程抢占,而且一个行程不能改变另一个行程门状态。为了避免行程切換时造成內核数据错误,內核在执行临界区代码时会禁止一切中断。
5.7.3行程初始化
在boot/目錄中,开机程式把內核从磁碟上载入到记忆体中,並让系统进入保护模式下执行后,就开始执行系统初始化程式init/main.c。该程式首先确定如何分配使用系统实体记忆体,然后呼叫內核各部分的初始化函数分別对记忆体管理、中断处理、区块装置和字元装置、行程管理以及硬盘和软碟硬体进行初始化处理。在完成了这些操作之后,系统各部分已经处于可执行状态。此后程式把自己“手工”移动到任务0(行程0)中执行,並使用fork( )呼叫首次建立出行程l。在行程1中程式将继续进行应用环境的初始化並执行shell登錄程式。而原行程0则会在系统空閒时被调度执行,此时任务0仅执行pause( )系统呼叫,並又会呼叫调度函数。
“移动到任务0中执行”这个过程由巨集move_to_user_mode (include/asm/system.h)完成。它把main.c程式执行流从內核态(特权级0)移动到了用戶态(特权级3)的任务0中继续执行。在移动之前,系统在对调度程式的初始化过程(sched_init ( ))中,首先对任务0的执行环境进行了设置。这包括人工预先设置好任务0资料结构各栏位的值(include/linux/sched.h) 、在全域描述符表中添入任务0的任务状态段(TSS) 描述符和区域描述符表(LDT)的段描述符,並把它们分別载入到任务寄存器tr和区域描述符表寄存器ldtr中。
这裡需要強调的是,內核初始化是一个特殊过程,內核初始化代码也即是任务0的代码。从任务0资料结构中设置的初始数据可知,任务0的代码段和资料段的基址是0、段限长是640KB。而內核代码段和资料段的基址是0、段限长是16MB,因此任务0的代码段和资料段分別包含在内核代码段和资料段中。內核初始化程式main.c也即是任务0中的代码,只是在移动到任务0之前系统正以內核态特权级。执行著main.c程式。巨集move_ to_user_mode的功能就是把执行特权级从內核态的0级变換到用戶态的3级,但是仍然继续执行原来的代码指今流。
在移动到任务0的过程中,巨集move_to_user_mode使用了中断返回指令造成特权级改变的方法。使用这种方法进行控制权转移是由CPU保护机制造成的。CPU允许低级別(如特权级3)代码透过呼叫门或中断、陷阱门来呼叫或转移到高级別代码中执行,但反之则不行。因此内核採用了这种模拟IRET返回低级別代码的方法。该方法的主要思想是在堆栈中构筑中断返回指令需要的內容,把返回位址的段选择符设置成任务0代码段选择符,其特权级为3。此后执行中断返回指令iret时将导致系统CPU从特权级0跳转到外层的特权级3上执行。
参见图5-22所示的特权级发生变化时中断返回堆栈结构示意图。
巨集move_to_user_mode首先往內核堆栈中压入任务。资料段选择符和內核堆栈指标。然后压入标志寄存器內容。最后压入任务0代码段选择符和执行中断返回后需要执行的下一条指令的偏移位置。该偏移多位置是iret后的一条指令处。
当执行iret指令时,CPU把返回位址送入CS: EIP中,同时弹出堆栈中标志寄存器内容。由於CPU判断出目的代码段的特权级是3,与当前內核态的0级不同。于是CPU会把堆栈中的堆栈段选择符和指标弹出到SS : ESP中。由於特权级发生了变化,段寄存器DS、ES、FS和GS的值变得无效,此时CPU会把这些段寄存器清零。因此在执行了iret指令后需要重新载入这些段寄存器。此后,系统就开始以特权级3执行在任务0的代码上。所使用的用戶态堆栈还是原来在移动之前使用的堆栈。而其內核态堆栈则被指定为其任务资料结构所在页面
的顶端开始(PAGE_SIZE + (1ong) &init_task)由於以后在建立新行程时,需要复制任务0的任务资料结构,包括其用戶幻 ”指标,因此要求任务。的用戶
态堆栈在建立任务l (行程1)之前保持“干淨”状态。
5.7.4 建立新行程
Linux系统中建立新行程使用fork( )系统呼叫。所有行程都是透过复制行程0而得至的,都是行程0的子行程。
在建立新行程的过程中,系统首先在任务阵列中找出一个还沒有被任何行程使用的空项(空槽) 。如果系统已经有64个行程在执行,则fork ( )系统呼叫会因为任务阵列表中沒有可用空项而出错返回。然后系统为新建行程在主记忆体区中申请一页记忆体来存放其任务资料结构资讯,并复制当前行程任务资料结构中的所有内容作为新行程任务资料结构的范本。为了防止这个还未处理完成的新建行程被调度函数执行,此时应该立刻将新行程状态置为不可断的等待状态 (TASK_UNINTERRUPTIBLE)。
随后对复制的任务资料结构进行修改。把当前行程设置为新行程的父行程,清除信号点阵图並重定新行程各统计值,並设置初始执行时间片值为15个系统滴答数(150毫秒) 。接著根据当前行程设置任务状态段(TSS)中各寄存器的值。由于建立行程时新行程返回值应为0,所.以需要设置tss.eax = 0。新建行程內核态堆栈指标tss.esp0被设置成新行程任务资料结构所在记忆体页面的顶端,而堆栈段 tss.ss0被设置成內核资料段选择符。tss.1dt被设置为区域表描述符在GDT中的索引值。如果当前行程使用了辅助运算器,则还需要把辅助运算器的完整状态保存到新行程的tss.i387结构中。
共12页:
上一页
[1]
[2]
[3]
[4]
5
[6]
[7]
[8]
[9]
[10]
[11]
[12]
下一页
如果您对本文有任何疑问或者建议,请到论坛讨论区发表您的意见:
>>
论坛入口
[
收藏
] [
推荐
] [
评论(0条)
]
[返回顶部]
[打印本页]
[关闭窗口]
热点文章
·
使用 Linux 系统调用的内核命令
·
Linux 2.6.11内核文件IO系统调用
·
Linux操作系统的源代码目录树结
·
Linux用户态与内核态的交互讲解
·
Linux内核对I/O端口的管理实现(
·
深入分析 Linux操作系统的内核链
·
Linux内核可装载模块对设备驱动
·
概述Linux系统的驱动框架及驱动
·
详解Linux 2.6内核新文件系统变
·
Linux系统可卸载内核模块完全指
·
FreeBSD手册讲解(一)--配置FreeB
·
编译Linux操作系统的内核讲解
相关文章
·
深入学习LINUX内核之六(图文讲解
·
深入学习LINUX内核之五(图文讲解
·
深入学习LINUX内核之四(图文讲解
·
Linux系统内核漏洞分析
·
深入学习LINUX内核之三(图文讲解
·
如何在Linux内核中的实现SYN Coo
·
深入学习LINUX内核之二(图文讲解
·
简析Linux与FreeBSD的syscall
·
深入学习Linux内核文档一(图文讲
·
Linux操作系统“警惕”内核汉化
·
Linux操作系统核心的汉字显示机
·
如何利用异常表处理Linux内核态
本站信息源至:互联网络,均为学习,交流所用,如有版权问题,请联系我们.
站长QQ:397422079 E_mail:riechelr_hl@unix5.com
转载本站内容请注明原作者名.谢谢!