LINUX系统调用及exit实例分析

上传人:woxinch****an2018 文档编号:38969464 上传时间:2018-05-10 格式:DOC 页数:9 大小:53.50KB
返回 下载 相关 举报
LINUX系统调用及exit实例分析_第1页
第1页 / 共9页
LINUX系统调用及exit实例分析_第2页
第2页 / 共9页
LINUX系统调用及exit实例分析_第3页
第3页 / 共9页
LINUX系统调用及exit实例分析_第4页
第4页 / 共9页
LINUX系统调用及exit实例分析_第5页
第5页 / 共9页
点击查看更多>>
资源描述

《LINUX系统调用及exit实例分析》由会员分享,可在线阅读,更多相关《LINUX系统调用及exit实例分析(9页珍藏版)》请在金锄头文库上搜索。

1、LINUX 系统调用及 exit 实例分析计算机系 962 班 黄山松 9615158序言: 课程即将结束, 经过这一学期的学习,我对操作系统 , 尤其是 Linux 系统有了初步认识 ,虽然限于英语水平, 对外籍参考书较少涉及, 但 也深有收获. 特别是分析系统调用的源码 , 揭开了系统核心的神密的面纱. Linux 系统的结构系统的结构 在清华大学出版的 (屠立德屠祁 编著) 曾经见过这样一 幅 Unix 结构图,我觉得对 Linux 同样适用, 经少量改动, 示意如下: 裸机汇编子程序全局变量进程管理(包括 对换进程)存贮管理文件管理IO 中断设备管理与163 个系统调用命令应用程序包子

2、程序Shell 命令解释程序 用 户 一用户二用 户 三:例图 Linux 系统的结构 Linux 系统 由内核和用户层组成. 内核是 Linux 系统的心脏. 由汇编文件和 C 语言文件构成. 汇编文件主要用于系统初启 . 中断处理等与硬件细节密切相关的部 分, 此处本文不作详解 . 内核按以下功能分块: 1. 存贮管理2. 进程管理 3. 进程通信 4. 中断 .陷阱 与系统调用 ( 此处陷阱仅狭义为异常 ) 5. 输入输出管理 6. 文件系统 由例图及上面的分类 , 我们至少知道了为什么要有系统调用 . 用最简单的话 来说 , 系统调用就是硬件与软件的接口. 或者说 内核与外壳的接口.

3、实际上, Linux 的系统核心的所有程序都是作为进程的一部分而运行的,被包括 在每一个进程的虚拟地址空间里, so 每一个进程都包含着两个部分: 系统程序部 分和用户程序部分. 一进程在用户态运行时, 执行的是用户程序;若中断而转入核心 态, 执行系统核心程序. 下面就让我们进入一一. .系统调用的流程系统调用的流程 大致流程如下: start_kernel ( ) 函数 ( i386/main.c )trap_init ( ) 函数 ( kernel/trap.c ) 宏 set_grap_gate ( ) 函数 ( asm/system.h ) start_kernel ( ) 提供了各

4、种 trap 入口 . 通过调用 trap_init ( ) 函数 设置, 而 trap_init ( ) 又通过调用 set_ system_gate( 0x80, errno=-_res; return -1; 该宏的第一个参数是一类类型参数,它指明系统调用返回值的类型,第二个 参数指明系统调用的名称。若还有别的参数, 则第 2i 个参数是系统调用函数的 第 i 个参数的类型,第 2i+1 个参数是系统调用函数的第 i 个参数, 该宏的主体部 分是一内联汇编,它通过汇编代码段_asm_volotile 调用中断“int $0x80“将参 数传递给 ENTRY(system_call),其中

5、,定义 res 取得返回值 ,并将_NR_用 #将其与 name 连接起来作为参数,这个参数定义在 unistd.h 的宏中,其它参 数 arg1,arg2,arg3 则被存放在相应的寄存器 ebx, ecx, edx 中. 在“_syscallX” 宏中,约定五个参数分别与五个寄存器对应: arg1 值存入寄存器 ebx; arg2 值存入寄存器 ecx; arg3 值存入寄存器 edx; arg4 值存入寄存器 esi; arg5 值存入寄存器 edi;另外, 若系统调用中出错,则将_res 的相反数作为出错号赋给全局变量“errno” ,并返回 -1,否则返回_res 。 注意: 上面提

6、到了汇编指令 int 0x80 中断调用能跳转到 ENTRY(system_call),这 就不得不提到系统的中断矢量表, 在中断矢量表中,事先将 int 0x80 中断的 指 针指向了系统调用 system_call, 正如下面提到的 1. 3 系统调用矢量表系统调用矢量表在“/arch/i386/entry.S” 中定义了系统调用表 ( sys_call_table ),保存了所有 Linux 基于 Intel x86 系列体系结构的计算机的系统调用入口地址, 核心入口指针 ENTRY(system_call)对所有的系统调用都是相同的。它的作用是保存所有的寄存器 值: ENTRY(sys

7、tem_call)pushl %eax # save orig_eaxSAVE_ALLGET_CURRENT(%ebx)cmpl $(NR_syscalls),%eaxjae badsystestb $0x20,flags(%ebx) # PF_TRACESYSjne tracesyscall *SYMBOL_NAME(sys_call_table)(,%eax,4)movl %eax,EAX(%esp) # save the return valueALIGN.globl ret_from_sys_call.globl ret_from_intr 首先用 SAVE_ALL 这个宏将所有的寄存

8、器值都保存,并且检查确认该系统调用 合法性, 然后用 cmpl $( NR_syscalls ), %eax 来判断, 如果$(NR_syscalls ) =%eax(eax 中存放的是当前的系统调用号),则超过了系统调用的最大限制, 违法. 跳至badsys:movl $-ENOSYS,EAX(%esp)jmp ret_from_sys_call 这段代码先将 eat 中的出错码的相反数赋给 ENOSYS , 再调用 ret_from_sys_call 返回. 如果调用合法, ENTRY 将控制权交至 *SYMBOL_NAME (sys_call_table) (,%eax,4 ) ,eax

9、 中的内容 * 4 就是 系统调用的实际地址偏移量. 通过它可找到相 应的系统调用代码的: .data ENTRY(sys_call_table) .long SYMBOL_NAME(sys_setup)/* 0 */ .long SYMBOL_NAME(sys_exit) .long SYMBOL_NAME(sys_fork)* * * * * * .space (NR_syscalls-166)*4 在 include/linux/sys.h 文件中定义了宏 NR_systemcall,其值为 256,表示 x86 微机 上最多可容纳的系统调用个数。 我们已经介绍过了中断 0x80 和 系

10、统调用表, 可以说已经了解了系统调用的 一般流程, 下面就结合一个实例具体分析一下吧二二. .系统调用实例系统调用实例 exit 的分析的分析exit 系统调用简介:正与 fork 系统调用创建一个子进程相反, exit 的目的是为了撤销一个进程, 像上面系统调用表中提到的那样, 通过调用 sys_exit( ) 函数终止一个进程的运行. 处理期间, 要保存当前帐号的各种信息,逐步退出占用的资源, 还要处理好与之有 关的其他进程.2.1 exit 的简单流程的简单流程首先, 为了以下讨论方便, 我先将主要源码 exit.c 中的一些代码附在下面, 并分别加上字母序号划分开来 ( NORET_T

11、YPE 表示 此为非停机类型): NORET_TYPE void do_exit(long code) (a) if (intr_count) printk(“Aiee, killing interrupt handlern“); intr_count = 0; (b) fake_volatile: acct_process(code); current-flags |= PF_EXITING; del_timer( sem_exit(); kerneld_exit();(c) _exit_mm(current); _exit_files(current); _exit_fs(current)

12、; _exit_sighand(current); exit_thread();(d) current-state = TASK_ZOMBIE; current-exit_code = code; exit_notify(); #ifdef DEBUG_PROC_TREE audit_ptree(); #endif(e) if (current-exec_domain if (current-binfmt (f) schedule(); goto fake_volatile; (g ) asmlinkage int sys_exit(int error_code) do_exit(error_

13、code 语句 del_timer( 语句 current-exit_code=code 设置退出码为传进来的参数 code; 函数 exit_notify()发送信号给进程所在的进程组( ”SIGHUP”和” SIGCONT”信号) , 并且通知父进程,本进程已经被撤销了;然后进入一循环 做以下两件事: a 使初始进程(init)继承所有子进程。 b 检查是否还有进程组不是孤立的。如果是, 按照上面方法处 理;最后,调用函数 disassciate_ctty ( int) ( 定义在 linuxdriverschartty_io.c文件中 )。只有当参数是 1 时,才是被 exit_noti

14、fy()调用的。在该函数中,将当前 tty 进程组杀掉,所有进程对应的 tty 成员赋 NULL;(e ) 标注处:语句 current-exec_domain 指向进程所属的全局执行域结构,将所属 用户数目减一;( f) 继续调度:schedule(); 正常情况下, 此函数将不再返回, 如果异常情况发生, 导致跳出, 使用 goto fake_volatile 语句继续处理.至此. Exit 的流程结束 . 下面是 2.2 关于关于 exit 的若干说明的若干说明 首先 sys_exit 系统调用的宏定义可在文件/asm-i386/unistd.h 下面找到很( 其他系统调用也包括在此文件

15、中), sys_exit 的具体定义如下:static inline _syscall1(int,_exit,int,exitcode) 很明显 exit 只使用一个参数, 将其展开后,形成代码如下: int _exit(int exitcode) long _res; _asm_ volatile (“int $0x80“ : “=a“ (_res) : “0“ (_NR_exit), “b“ (long)(exitcode); if (_res = 0 ) return (int) _res; errno = -_res; return -1; 可以看出来,sys_exit 带了参数 exitcode,该参数便是系统退出(sys_exit)的退出 码。正如前面第一章曾提到的那样, _exit 通过调用 int 0x80 并传入系统调用号 (_NR_exit,即在 sys_call_table 中的偏移量)和退出码(exitcode)的方法,来达到 调用 sys_exit 的目的。 然后,当调用完

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 其它相关文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号