• 深入理解Linux内核 学习笔记(8)


    第八章 系统调用

    API定义了一个给定的服务;系统调用是通过软中断向内核发出一个明确的请求。

    API可能不调用系统调用,也可能调用多个系统调用。

    Linux系统调用必须通过执行int 0x80,系统调用时用户态切换到内核态。

    使用eax传递系统调用号。返回值0为成功,负数为程序错误码。

    System_call()函数会检查current的flags域是否包含PF_TRACESYS为1,即是否在被跟踪执行。如果是,system_call()在系统调用服务例程执行之前,和之后调用syscall_trace(),允许收集current的信息。

    传参:参数长度不能超过寄存器长度(32位),不能超过6个。Eax,ebx,ecx,edx,esi,edi。

    动态地址检查:修正代码

    内核态缺页异常的三种情况:

    内核试图访问属于进程地址空间的页,但是,或者是相应的页框不存在,或者是内核试图去写一个只读页。

    某一内核函数包含程序设计错误,当这个函数运行时就引起异常;或者,可能由于瞬时的硬件错误引起异常。

    本章所讨论的一种情况:个系统调用服务例程试图读写-.个内存区,而该内存区的地址是通过系统调用参数传递来的,但却不属于进程的地址空间。

    异常表:把访问进程值空间的任一条内核指令放异常表里。发生页异常时,do_page_fault()处理程序检查异常表,有就是由非法系统调用参数引起的,不然就是更严重的bug。

    Linux定义了几个异常表。主要的异常表在建立内核程序映像时由C编译器自动生成。它存放在内核代码段的__ex_table部分,其起始与终止地址由C编译器产生的两个符号: __ start_ __ ex_ table和_ . stop__ ex_ table 标识。

    此外,每个动态装载的内核模块(参看附录二)都包含有自己的局部异常表。这个表是在建立模块映像时由C编译器白动产生的,当把模块插人到运行中的内核叶把这个表装入到内存。

    修正代码为几条汇编指令,解决缺页异常引发的问题

    封装例程:内核也需要调用系统调用,但不能用库函数。

    尽管系统调用主要由用户态进程使用,但也可以被内核线程调用,内核线程不能使用库的数。为了简化桕应的封装例程的声明,Linux定义了六个从_ syscal10到一syscall5的宏。

    例程的声明。然而,不能用这些宏来为超过5个参数(系统调用号除外)的系统调用或产生非标谁返回值的系统调用定义封装例程。

    每个宏严格地需要2+2xn个参数.n是系统调用的参数个数。前两个参数指明系统调用的返回值类型和名字;每-对附加参数指明相应的系统调用参数的类型和名字。因此,以fork(}系统调用为例,其封装例程可以通过如下语句产生:.

          .syscall0lint, fork)

    而write()系统调用的封装例程可以通过如下语句生产:

          _ syscall3(int, write, int, fd, const char *, buf, unsigned int, count )

  • 相关阅读:
    Nginx练习练习玩玩
    MySQL Lock--MySQL加锁规则
    MySQL Transaction--RR事务隔离级别下加锁测试
    MySQL Transaction--RC事务隔离级别下加锁测试
    MySQL Transaction--事务隔离级别基础
    MySQL Transaction--快照读和当前读
    MySQL Transaction--RC和RR区别
    MySQL Disk--NAND Flash原理
    MySQL Disk--SSD与RAID
    MySQL Disk--SSD磁盘性能抖动问题
  • 原文地址:https://www.cnblogs.com/61355ing/p/10906883.html
Copyright © 2020-2023  润新知