精华内容
下载资源
问答
  • 系统调用的处理过程

    千次阅读 2013-09-13 11:12:02
    用户程序执行到系统调用指令通过访管指令产生中断系统进入访管中断处理保护现场,并通过系统调用入口表,按功能号跳转找到相应功能入口地址执行相应例行程序,结束后正常情况返回系统调用的下一条指令执行。
    1. 用户程序执行到系统调用指令
    2. 通过访管指令产生中断
    3. 系统进入访管中断处理
    4. 保护现场,并通过系统调用入口表,按功能号跳转找到相应功能入口地址
    5. 执行相应例行程序,结束后正常情况返回系统调用的下一条指令执行。
    展开全文
  • Read 系统调用在用户空间中的处理过程 当调用发生时,库函数在保存 read 系统调用号以及参数后,陷入 0x80 中断。这时库函数工作结束。Read 系统调用在用户空间中的处理也就完成了。 Read 系统调用在核心空间中...

    转载:https://www.cnblogs.com/tcicy/p/8454740.html

    Read 系统调用在用户空间中的处理过程

    当调用发生时,库函数在保存 read 系统调用号以及参数后,陷入 0x80 中断。这时库函数工作结束。Read 系统调用在用户空间中的处理也就完成了。

    Read 系统调用在核心空间中的处理过程

    0x80 中断处理程序接管执行后,先检察其系统调用号,然后根据系统调用号查找系统调用表,并从系统调用表中得到处理 read 系统调用的内核函数 sys_read ,最后传递参数并运行 sys_read 函数。至此,内核真正开始处理 read 系统调用(sys_read 是 read 系统调用的内核入口)。

    Read 系统调用在核心空间中处理的层次模型

    • 虚拟文件系统层的作用:屏蔽下层具体文件系统操作的差异,为上层的操作提供一个统一的接口。正是因为有了这个层次,所以可以把设备抽象成文件,使得操作设备就像操作文件一样简单。
    • 在具体的文件系统层中,不同的文件系统(例如 ext2 和 NTFS)具体的操作过程也是不同的。每种文件系统定义了自己的操作集合。关于文件系统的更多内容,请参见参考资料。
    • 引入 cache 层的目的是为了提高 linux 操作系统对磁盘访问的性能。 Cache 层在内存中缓存了磁盘上的部分数据。当数据的请求到达时,如果在 cache 中存在该数据且是最新的,则直接将数据传递给用户程序,免除了对底层磁盘的操作,提高了性能。
    • 通用块层的主要工作是:接收上层发出的磁盘请求,并最终发出 IO 请求。该层隐藏了底层硬件块设备的特性,为块设备提供了一个通用的抽象视图。
    • IO 调度层的功能:接收通用块层发出的 IO 请求,缓存请求并试图合并相邻的请求(如果这两个请求的数据在磁盘上是相邻的)。并根据设置好的调度算法,回调驱动层提供的请求处理函数,以处理具体的 IO 请求。
    • 驱动层中的驱动程序对应具体的物理块设备。它从上层中取出 IO 请求,并根据该 IO 请求中指定的信息,通过向具体块设备的设备控制器发送命令的方式,来操纵设备传输数据。
    • 设备层中都是具体的物理设备。定义了操作具体设备的规范。

    内核相关数据结构:

    • Dentry : 联系了文件名和文件的 i 节点
    • inode : 文件 i 节点,保存文件标识、权限和内容等信息
    • file : 保存文件的相关信息和各种操作文件的函数指针集合
    • file_operations :操作文件的函数接口集合
    • address_space :描述文件的 page cache 结构以及相关信息,并包含有操作 page cache 的函数指针集合
    • address_space_operations :操作 page cache 的函数接口集合
    • bio : IO 请求的描述

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 本片内容接上一篇,是系统调用的续篇,也就是简要分析一下系统调用的处理过程。同样,以一个实验开始。 本实验同样在实验楼环境下完成。下面先介绍一下实验: 1.实验: 将上一个系统调用函数和asm版本的实现整合进入...

    罗晓波 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 

    本片内容接上一篇,是系统调用的续篇,也就是简要分析一下系统调用的处理过程。同样,以一个实验开始。

    本实验同样在实验楼环境下完成。下面先介绍一下实验:

    1.实验:

    将上一个系统调用函数和asm版本的实现整合进入menu的内核中:

    int GetPid()
    {
        int pid = getpid();
        printf("The Current Progress pid is : %d\n",pid);
        return 0;
    }
    
    int GetPidAsm()
    {
        int pid;
        asm volatile(
            "mov $0,%%ebx\n\t"
            "mov $0x14,%%eax\n\t" 
            "int $0x80\n\t" 
            "mov %%eax,%0\n\t"  
            : "=m" (pid) 
        );
        printf("The Current Progress pid asm is : %d\n",pid);
        return 0;
    }
    int main()
    {
        PrintMenuOS();
        SetPrompt("MenuOS>>");
        MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
        MenuConfig("quit","Quit from MenuOS",Quit);
        MenuConfig("time","Show System Time",Time);
        MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
        MenuConfig("getpid","Show Current Progress id",GetPid);
        MenuConfig("getpid-asm","Show Current Progress asm id",GetPidAsm);
        ExecuteMenu();
    }
    
    简单介绍一下上面的一段代码,MenuConfig这个函数是菜单(也就是制作出来的内核)的初始化配置函数,第一个参数是命令,第二个参数是该命令的描述,第三个参数是这个命令相对应的handler,也就是回调函数,是通过一个函数指针进行实现的。ExecuteMenu这个函数是为了启动这个menu引擎,其实是一个循环等待用户输入命令的过程。

    在添加了getpid和getpid-asm这两个命令之后,make一下,再重新编译一下内核,make rootfs。再启动一下qemu:


    接下来,我们开始调试这个系统调用函数,对应着getpid这个系统调用,在sys_getpid这个内核函数这里打一个断点。continue之后,输入getpid-asm或者getpid这个命令会停在sys_getpid();



    可以看到,在kernel/sys.c中有这么一个sys_getpid()内核函数,这个也就是系统调用的服务例程。跟进这个task_tgid_vnr(current)函数,之后finish之后的返回值是1,也就是init进程的进程号。


    当然打印出来的current pid 也是1 。

    有点遗憾的是我没有找到让gdb在systemcall这个汇编代码处停止的办法,希望小伙伴可以友情提示。下面来进一步分析从systemcall到系统调用结束之后,iret之间的过程。

    2.从systemcall到iret过程:

    Systemcall内核源码(汇编代码)进行简要分析:

    490ENTRY(system_call)
    491	RING0_INT_FRAME			# can't unwind into user space anyway
    492	ASM_CLAC
    493	pushl_cfi %eax			# save orig_eax
    494	SAVE_ALL
    495	GET_THREAD_INFO(%ebp)
    496					# system call tracing in operation / emulation
    497	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
    498	jnz syscall_trace_entry
    499	cmpl $(NR_syscalls), %eax
    500	jae syscall_badsys
    首先在内核栈中,压栈eax,也就是用户态传递给内核态的系统调用号,之后SaveAll这个指令就开始保存现场了,这里GET_THREAD_INFO(%ebp)是将这个进程的threadinfo结构体的地址指针放在了ebp寄存器里,下面对于这个结构体的访问也就可以顺理成章的用ebp的地址偏移进行访问就行了。比如下一句的TI_flags这个宏代表的其实就是一个offset,这个testl 指令主要是为了检查是否存在调试程序对这个系统调用正在调试,如果是,则跳转到syscall_trace_entry标签处,这个标签我一会来分析。接着往下看,cmpl $(NR_syscalls),%eax 这个指令主要是为了防止eax传递参数越界了,也就是超过了系统调用符号表中的值,如果出错了就跳到syscall_badsys标签处。


    501syscall_call:
    502	call *sys_call_table(,%eax,4)
    503syscall_after_call:
    504	movl %eax,PT_EAX(%esp)		# store the return value
    505syscall_exit:
    506	LOCKDEP_SYS_EXIT
    507	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
    508					# setting need_resched or sigpending
    509					# between sampling and the iret

    如果上面的都没问题的话,我们来到系统调用函数执行的地方了,调用服务例程,系统调用号乘以4加上sys_call_table的基址,内核系统调用的服务例程,也就是getpid的函数地址就是它了,调用call指令,开始执行,又是顺理成章的将eax的值,也就是系统调用的返回值放到esp的某一个偏移量(PT_EAX)处。

    在系统调用退出之前,在restoreall之前,会将threadinfo中的许多标志位进行比较,看是否需要在返回用户态之前做点什么事,比如我们看着一段:

    在恢复用户态之前的一段代码:

    350	TRACE_IRQS_OFF
    351	movl TI_flags(%ebp), %ecx
    352	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done on
    353					# int/exception return?
    354	jne work_pending
    355	jmp restore_all
    这里检查了TIF_WORK_MASK,有其他的int值或者异常要返回?这个时候我们跳到workpending,这个workpending我们贴一下代码看看:

    593work_pending:
    594	testb $_TIF_NEED_RESCHED, %cl
    595	jz work_notifysig
    596work_resched:
    597	call schedule
    598	LOCKDEP_SYS_EXIT
    599	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
    600					# setting need_resched or sigpending
    601					# between sampling and the iret
    602	TRACE_IRQS_OFF
    603	movl TI_flags(%ebp), %ecx
    604	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done other
    605					# than syscall tracing?
    606	jz restore_all
    workpending主要是为了检测重调度标志,下面的work_resched标签是如果进程切换的请求被挂起了,辣么,在内核态开始一次进程调度,选择一个进程运行,当前面的进程要恢复的时候在跳转回到resume_userpace处,也即回到用户态的标签处。
    在restoreall之后,就将中断的程序被恢复了。
    下面是一张简要流程图:
    
    


    展开全文
  • 处理过程分为硬件处理和软件处理,每个外设都有相对应中断号,从而让操作系统和所识别; 中断 一:硬件(外设) 设置中断标记(CPU初始化) 1:将内部外部事件设置中断标记 2:找出中断事件ID,让操作系统识别...

     

    中断和异常

    在中断和异常之前,操作系统会生成一个表(为每一个异常,中断编号);

    处理过程分为硬件处理和软件处理,每个外设都有相对应的中断号,从而让操作系统和所识别;

    中断

    一:硬件(外设) 设置中断标记(CPU初始化)

    1:将内部外部事件设置中断标记

    2:找出中断事件ID,让操作系统识别

    二:软件(操作系统)

    1:保存当前处理状态

    2:中断服务程序处理

    3:清除中断标记

    4:恢复之前保存的处理状态

    异常:

    一:硬件 设置中断标记(CPU初始化)

    1:将内部外部事件设置异常标记

    2:找出异常事件ID,让操作系统识别

    二:软件(操作系统)

    1:保存现场

    2:异常处理(杀死异常程序或重新执执行异常命令)

    3:恢复现场

    系统调用:

    由操作系统为应用程序提供服务

    eg:c程序在调用printf()时,会触发系统调用write(设备,内容)->访问设备;

    系统调用接口:(可以实现跨平台)

    win32 API 用于windows

    POSIX API 用于Linux,UNIX,MAC OS

    实现方式:

    系统调用使得计算机从应用程序的用户态(应用程序运行时的cup状态,权限低)转向操作系统内核态(权限大);

    该过程还需要切换堆栈;使得计算机变得更安全可靠。

    总结:中断异常。系统调用均跨越了操作系统的边界;也就有了内存和时间的开销;开销如下;

    1:建立中断异常表

    2:建立内核堆栈

    3:验证参数

    附:中断异常和系统调用的基本

     

    展开全文
  • 一次系统调用的完整执行过程如下: 通过特定指令发出系统调用(int $80、sysenter、syscall) CPU从用户态切换到内核态,进行一些寄存器和环境设置 调用system_call内核函数,通过系统调用号获取对应的服务...
  • 转载于:https://www.cnblogs.com/mwxjmmyjfm/archive/2010/11/19/1881870.html
  • 学号后三位:069 ... 一、实验内容 ...分析系统调用的处理过程 二、升级内核 升级前版本为:4.19.4 下载内核源码:https://github.com/mengning/linux/tree/v5.0 将文件解压,进入Linux-5.0目录下...
  • 跟踪分析Linux内核5.0系统调用select处理过程 学号:282 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ 操作系统主要功能是为管理硬件资源和为应用程序开发人员提供良好环境来使应用...
  • 3. execve系统调用处理过程分析   一、如何用execve系统调用加载一个可执行程序 下面代码可以展示如何用execlp函数启动一个新进程,execlp是对系统调用execve一层封装。  其中第19行输出是故意加上...
  • 中断处理程序执行,也即切换到了内核态,此处也就是执行系统调用的程序,从 eax 寄存器中读出系统调用号,查系统调用表,找到对应的内核函数执行,将结果继续写入 eax 寄存器中。 中断处理程序执行完成,恢复原程序...
  • ③执行system-call()函数,继续保护中断现场信息并检查本次系统调用的正确性。若通过检查,则利用EAX寄存器传递过来的系统调用号查找系统调用入口表,找到这个系统调用的服务例程的入口地址。 ④执行write()服务例程...
  • 上一篇博文我们用汇编的方式实现了对系统调用open的引用,这一次我们来深入到系统调用处理的内部,来看看Linux到底是如何处理系统调用的。    系统调用函数system_call的代码可以在arch/x86/kernel/entry_32.S中...
  • 跟踪分析Linux内核系统调用处理过程 学号245。原创作品,转载请注明出处:https://github.com/mengning/linuxkernel/ 实验要求 举例跟踪分析Linux内核5.0系统调用处理过程 编译内核5.0 qemu -kernel linux-5.0.1/...
  • “casualet + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程...本文将分析可执行程序加载的过程,包括可执行程序的个是ELF,动态链接以及静态链接相关内容,并通过gdb调试的方式展示该系统调用的执行过程。 ...
  • 系统调用system_call的处理过程

    千次阅读 2016-03-27 19:51:29
    关于system_call,虽然它有函数申明,但它其实是关于系统调用的一段汇编代码的起点,所以使用gdb无法跟踪到它。 下面我们通过实验来了解system_call的处理过程,首先我们需要用一个新的内核,然后把我们的系统调用...
  • 学号300原创作品转载请...举例跟踪分析Linux内核5.0系统调用处理过程 编译内核5.0 qemu -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img 选择系统调用号后两位与您学号后两位相同的系统调用进行跟...
  • 选择系统调用号后两位与您学号后两位相同的系统调用进行跟踪分析 实验环境 Ubuntu18 内核:Linux Kernel 5.0.1 qemu:运行内核代码模拟器 gdb:断点调试工具 编译内核5.0 1.下载内核5.0压缩包,...
  • Read 系统调用在用户空间中的处理过程 Linux 系统调用(SCI,system call interface)的实现机制实际上是一个多路汇聚以及分解的过程,该汇聚点就是 0x80 中断这个入口点(X86 系统结构)。也就是说,所有系统调用...
  • 系统调用的过程

    2020-09-15 14:24:35
    1.用户层可调用的系统调用接口函数中内嵌了一段汇编代码,调用了0x80号中断,并将一些参数保存在eax等寄存器中 2.CPU去IDT表格中查找0x80号中断对应的中断处理程序system_call(硬件行为),system_all所在的内存段的...
  • 跟踪分析Linux5.0内核处理系统调用的过程 416原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ 实验要求 下载并编译Linux5.0内核 选择一个系统调用进行跟踪 实验步骤 一. 编译Linux5.0内核 1....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,086
精华内容 2,434
关键字:

系统调用的处理过程