进程调度与系统调用

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

Linux操作系统内核分析湘潭大学信息工程学院讲课内容中断管理进程管理信号处理中断的概念改变处理器正常执行顺序的事件中断来源:硬件:时钟、键盘、硬盘等,异步发生异常:CPU检测到的错误软件系统调用:进程向OS发出的请求中断向量保护模式支持256个中断,每个中断用一个0到255的整数来标识,把这个整数称为中断向量0到31对应异常(P76表5-2)32到47对应硬件中断(P9图2-5)48到255预留,linux使用了0x80作为系统调用中断类别原因异步/同步返回中断I/O设备有信号同步下一条要执行的指令陷阱有意的异常异步下一条要执行的指令故障潜在可恢复的异常异步引起异常的指令终止不可恢复的异常异步终止保护模式下中断处理idtr0号中断描述符1号中断描述符2号中断描述符3号中断描述符中断描述符表中断描述符段选择子段内偏移(0-15)段内偏移(16-31)Type0DPL1000000002位4位Head中对中断描述符表的处理在程序232行(P58),定义了有256个中断描述符的中断描述符表,并在程序开始处把该描述符表的基地址输出(可以被C程序使用)在程序78行(P54),把这256个中断描述符中的处理程序设置为ignore_int在程序105行(P55)把中断描述符表的基地址装入到idtr寄存器中gcc嵌入汇编_asm__volatile_(汇编语句:输出寄存器:输入寄存器:会被修改的寄存器);输出寄存器:“=代表寄存器的字母”(变量名)寄存器的值会被写入变量中输入寄存器:“代表寄存器的字母”(变量名)用变量的值初始化寄存器P81常用寄存器加载代码P83表5-3嵌入汇编示例#define__save_flags(x)\_asm__volatile_(\“pushfl;”\“popl%0”\:“=a”(x)\);汇编语句输出寄存器a代表寄存器eax。把eax和变量x绑定,往eax中写入值等于给变量x赋值数字代表寄存器的序号。把输出寄存器和输入寄存器按照顺序进行编号,从0开始。%n代表第n个寄存器。序号0嵌入汇编示例#defineget_seg_byte(seg,addr)({registerchar_res;__asm__(“push%%fs;mov%%ax,%%fs;movb%%fs:%2,%%al;pop%%fs”:“=a”(_res):“0”(seg),“m”(*(addr)));_res;})序号0序号1序号2宏的返回值eax用seg的值进行了初始化_set_gate宏_set_gate宏(定义在system.h,P390的22行),用来设置中断描述符gate_addr:描述符的地址type:描述符的类型dpl:使用描述符的最低权限addr:中断处理函数的地址_set_gate宏#define_set_gate(gate_addr,type,dpl,addr)\__asm__(movw%%dx,%%ax\n\t\movw%0,%%dx\n\t\movl%%eax,%1\n\t\movl%%edx,%2\:\:i((short)(0x8000+(dpl13)+(type8))),\o(*((char*)(gate_addr))),\o(*(4+(char*)(gate_addr))),\d((char*)(addr)),a(0x00080000))01234_set_gate宏0号立即数1号内存地址指向描述符的基地址(前4个字节)2号内存地址指向描述符的基地址+4(后4个字节)处理程序高16位处理程序低16位edx0x00080x0000eax处理程序低16位0x8000+(dpl13)+(type8)0x8000+(dpl13)+(type8)中断描述符段选择子段内偏移(0-15)段内偏移(16-31)Type0DPL100000000设置中断描述符#defineset_trap_gate(n,addr)\_set_gate(&idt[n],15,0,addr)#defineset_system_gate(n,addr)\_set_gate(&idt[n],15,3,addr)idt是head中定义的描述符表基地址dpl=0,只有操作系统能够使用该中断dpl=3,任何进程都可以使用该中断异常初始化trap.c中的trap_init()(P80的181行)函数负责再次初始化中断描述符表,该函数在main函数(P65的127行)中被调用异常的中断向量参见P76表5-2中断初始化在traps.c中的trap_init函数的最后(P81第207行)设置了并口(0x27)的中断描述符在sche.c中的sched_init函数的最后(P103第409行)设置了时钟中断(0x20)的中断描述符参见P9图2-5系统调用初始化在sche.c中的sched_init函数的最后(P103第411行)设置了系统调用(0x80)的中断描述符中断处理中断处理完后,进程会按照被打断前的状态继续运行,所以需要保存该状态。保存执行现场调用中断处理函数恢复执行现场指令1指令2指令n进程中断处理保存执行现场调用中断处理函数恢复执行现场用户指令1用户指令2内核指令1内核指令2进程内核硬中断异常系统调用硬中断异常中断处理CSEIPSSESPEFLAGS通用寄存器用户态指令用户态堆栈CPU内核态指令内核态堆栈用户态内核态中断处理当发生中断时,如果当前进程运行在内核态,CPU会将EFLAGS、CS、和EIP寄存器中的内容压入堆栈当发生中断时,如果当前进程运行在用户态,CPU除了会将EFLAGS、CS、和EIP寄存器中的内容压入堆栈外,还会把进程在用户态时使用的SS和ESP寄存器的内容压入堆栈中断发生时的堆栈CSEFLAGSEIPCSEFLAGSEIP用户态ESP用户态SS中断发生时进程在内核态中断发生时进程在用户态中断处理异常处理系统调用中断处理异常处理异常发生时,可能带有出错码。如果有,则该出错码也会被CPU压入堆栈CSEFLAGSEIP用户态ESP用户态SSCSEFLAGSEIP用户态ESP用户态SS出错码不带出错码的异常处理pushl$do_divide_errorno_error_code:xchgl%eax,(%esp)pushl%ebxpushl%ecxpushl%edxpushl%edipushl%esipushl%ebppush%dspush%espush%fspushl$0lea44(%esp),%edxpushl%edxmovl$0x10,%edxmov%dx,%dsmov%dx,%esmov%dx,%fscall*%eaxdo_divide_errorespeax的值ebx的值eax保存do_divide_error的地址CSEFLAGSEIP用户态ESP用户态SSespespecx的值espedx的值espedi的值espesi的值espebp的值espDSespESespFSesp错误码0espedx初始esp位置esp指向内核数据段保存现场参数不带出错码的异常处理addl$8,%esppop%fspop%espop%dspopl%ebppopl%esipopl%edipopl%edxpopl%ecxpopl%ebxpopl%eaxireteax的值ebx的值CSEFLAGSEIP用户态ESP用户态SSespecx的值edx的值edi的值esi的值ebp的值DSESFS错误码0初始esp位置espesp异常处理流程保存现场准备参数调用C语言函数弹出参数恢复现场中断返回发生中断带出错码的异常处理P75页第99行CSEFLAGSEIP用户态ESP用户态SS出错码中断处理异常处理系统调用中断处理使用系统调用P383第133行#define_syscall0(type,name)typename(void){long_res;__asm__volatile(“int$0x80:“=a”(_res):“0”(_NR_##name));if(_res=0)return(type)_res;errno=-_res;return-1;}系统调用的返回放在eax中系统调用的功能号放在eax中(P381)使用系统调用P63第23行staticinline_syscall0(int,fork)intfork(void){long_res;__asm__volatile(“int$0x80:“=a”(_res):“0”(_NR_fork));if(_res=0)return(type)_res;errno=-_res;return-1;}使用系统调用系统调用的输入把子功能号放入eax中如果还有其它参数(最多3个),则第1、第2和第3个参数分别放入寄存器ebx,ecx和edx中系统调用的返回值保存在eax中数据结构及算法函数指针数组sys_call_talbe[](P409)system_call(P86第80行)处理流程保存现场以子功能号作为索引查找sys_call_table,找到处理该功能的C语言函数,然后调用该函数。恢复现场系统调用的处理cmpl$nr_system_calls-1,%eaxjabad_sys_callpush%dspush%espush%fspushl%edxpushl%ecxpushl%ebxmovl%0x10,%edxmov%dx,%dsmov%dx,%esmovl%0x17,%edxmov%dx,%fscall_sys_call_table(,%eax,4)pushl%eaxCSEFLAGSEIP用户态ESP用户态SSespDSESFSEDXECXEBXespespespespespesp系统调用参数_sys_call_table+4*eax_sys_call_table在P409定义EAXesp保存系统调用返回值系统调用的处理3:popl%eaxpopl%ebxpopl%ecxpopl%edxpop%fspop%espop%dsiretCSEFLAGSEIP用户态ESP用户态SSDSESFSEDXECXEBXEAX讲课内容中断管理进程管理信号处理进程的概念进程是程序的一次执行,是由代码段、数据段和堆栈段组成动态的实体,在Linux中,把进程又称为任务(task)进程是系统资源分配的基本单位,也是使用CPU运行的基本调度单位进程描述符为了管理进程,操作系统需要清楚地知道每个进程的属性,Linux用一个称为进程描述符(task_struct)的数据结构来描述task_struct定义在sched.h中,参见P404第78行进程描述符——状态P12图2-6没有实现进程描述符——线性地址分布代码数据bss用户态堆栈环境参数nr*64M(nr+1)*64Mstart_codeend_codeend_databrkstart_stack进程描述符——任务状态段任务状态段(TSS)是保存任务的所有信息的内存段,共104B寄存器保存区域内层堆栈指针区域地址映射寄存器区域其它字段P116图5-8进程描述符——任务状态段在任务切换过程中首先,CPU中各寄存器的当前值被自动保存到TR所指定的TSS中(当前任务的TSS中)然后,下一任务的TSS的选择子被装入TR最后,从TR所指定的TSS中取出各寄存器的值送到处理器的各寄存器中由此可见,通过在TSS中保存任务现场各寄存器状态的完整映象,实现任务的切换进程描述符——任务状态段TSS的段描述符在GDT中,当前进程的TSS的段选择子被保存在TR寄存器中TSS段描述符GDTTSS段当前进程的TSS段选择子TRTSS段描述符TSS段进程描述符——局部描述符表局部描述符表(LDT)包含任务私有内存段的描述符(也是一个内存段)LDT的段描述符在GDT中,当前进程的LDT段选择子在ldtr中进程描述符——局部描述符表Linux中LDT包含3个描述符,其中:

1 / 127
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功