zoukankan      html  css  js  c++  java
  • 《Linux内核设计与实现》CHAPTER5阅读梳理

    《Linux内核设计与实现》CHAPTER5阅读梳理

    【学习时间:2.5hours】

    【学习内容:系统调用的概念、功能及实现;系统调用的创建和使用方法】

    CHAPTER5 系统调用

    1.系统调用的作用

    系统调用在用户空间和硬件设备之间提供了一个中间层:

    1. 为用户空间提供了一个硬件抽象接口;
    2. 系统调用保证了系统的稳定和安全(防止应用程序不正确地使用硬件设备);
    3. 实现多任务和虚拟内存

    2.系统调用的支持方式

    1. 系统调用依靠C库支持。用户程序通过包含标准头文件并和C库链接,就可以使用系统调用。
    2. C库也实现了Unix系统的主要API。此外,C库还提供了POSIX的大部分API。

    3.mechanism&policy

    • Unix设计中的一大亮点就是区别对待机制和策略。机制指的是“需要提供什么功能”,而策略是指“如何实现这些功能”。
    • 比如,程序员就只需要和API打交道,他们不关心机制。而内核只需要和系统调用打交道,只负责提供功能。

    4.系统调用的概述

    1. 系统调用在Linux中称为syscall,返回的值是long型变量;如果出错,C库会将错误代码写入errno全局变量(通过调用perror()函数可以把该变量翻译成用户可以理解的错误代码);
    2. 为了保证32和64位系统兼容,系统调用在用户空间和内核空间有不同的返回值类型:在用户空间为int,在内核空间为long。
    3. 如果一个系统调用被删除或者不可用,sysnisyscall()函数将会占用对应的系统调用号负责“填补空缺”,其只返回-ENOSYS。

    5.系统调用处理程序

    1. 用户程序无法直接执行内核代码,它们也不能直接调用内核空间中的代码;
    2. 通知内核的机制是靠软中断实现的:通过引发一个一场来促使系统切换到内核态去执行处理程序,此时的异常处理程序实际上就是系统调用处理程序——int $0x80所指向的128号异常处理程序就是系统调用处理程序;
    3. 在陷入内核态之前,用户空间就把相应的系统调用号传给eax;这样系统调用处理程序一旦运行,就可以从eax中得到数据。

    6.系统调用实现

    1. 第一步,明确系统调用的用途;
      1. 新系统调用的参数、返回值和错误码都应该清晰;借口也要尽量简洁。
    2. 参数验证
      1. 验证参数是否合法有效;
      2. 验证指针是否有效:
        • 指向的区域属于用户空间;
        • 指向的区域在进程的地址空间中(不允许访问其他进程空间);
        • 进程不能绕过内存访问限制。
      3. 方法:
        • 使用内核提供的copytouser()以及copyfromuser()检查从用户空间拷贝或者向其中写入数据是否成功(可能引起阻塞;比如当发生缺页中断的时候);
        • 使用capale()函数检查函数是否有权对指定的资源进行操作(如果不能的话则返回0)。
    3. 绑定系统调用
      • 在系统调用表(位于entry.s文件)中加入最后一个表项;
      • 将系统调用号定义到<asm/unistd.h>中:#define NR[系统调用] [数值]
      • 将系统调用编译进内核映像(而不是模块):将其放入kernel/下的相关文件中(比如sys.c)
    4. 系统调用定义形式:

      asmlinkage long sys_getpid(void)//以getpid()函数为例
      
      • 【asmlinkage限定词是一个编译指令,通知编译器仅从栈中提取该函数的参数】
    5. Linux本身提供了一组宏,用于直接对系统调用进行访问,即_syscalln();其中n是传递给系统调用的参数个数

      • 对每一个宏而言,都有2+2*n个参数:第一个是系统调用返回值类型;第二个是系统调用名称;以后是每个参数的类型和名称

    课堂内容补充

    1. 所有内核服务都通过系统调用的形式实现。也就是说,系统调用是除了异常和陷入以外内核唯一的合法入口。

    2.内核在执行系统调用的时候处于进程上下文,current指针指向引发系统调用的那个进程。

    • 在进程上下文中,内核可以休眠——说明系统调用可以使用内核提供的绝大部分功能(然而中断处理程序就不能休眠);
    • 并且,在进程上下文中,系统调用是可以重入的,也就是说当前进程可以被抢占

    疑问与自查

    1. NR_syscalls是什么意思?

      • 我能够大概理解到该变量应该代表了系统调用号。通过后面的阅读,确定它就是代指的系统调用号(网上也有说是当前地址减去系统调用表开始地址的)
    2. asmlinkage限定词的意义?为什么非要从堆栈中取值呢?

      • 参考http://www.cnblogs.com/china_blue/archive/2010/01/15/1648523.html
      • gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器。缺省时采用寄存器,假如你要在你的汇编过程中调用c语言函数,并且想通过堆栈传递参数,你定义的c函数时要在函数前加上宏asmlinkage。因为当 system call handler 要调用相对应的 system call routine 时,便将一般用途缓存器的值 push 到 stack 里,因此 system call routine 就要由 stack 来读取 system call handler 传递的参数。这就是 asmlinkage 标签的用意。
    3. reboot()系统调用的作用?

  • 相关阅读:
    'yiiaseInvalidRouteException' with message 'Unable to resolve the request "site/error".'
    yii2:不使用composer安装yii2-jui的方法
    Oracle cmd乱码
    oracle 11g安装过程中问题:移动binoralbac11.dll 到binoralbac11.dll.dbl出错
    yii2打印数据属性(字段名)/数据
    在xampp集成环境下使用 php 连接oracle
    phalcon: 项目地址/P(.*), 项目地址/Pbaidu 与 路由
    PHP返回32位与16位的md5加密值
    PHP调用webservice接口
    java:日期格式化
  • 原文地址:https://www.cnblogs.com/lwr-/p/5291320.html
Copyright © 2011-2022 走看看