天天看点

Linux内核-系统调用 Linux内核-系统调用

Linux内核-系统调用

1.与内核通信

#系统调用在用户空间进程和硬件设备之间增加了一个中间层

    作用:1.为用户空间提供了一种硬件的抽象接口

              2.系统调用保证了系统的稳定和安全

              3.出于每个进程都运行在虚拟系统中的考虑

#系统调用是用户空间访问内核的唯一手段

2.API、POSIX和C库

#应用程序通过API而不是直接系统调用来编程

#一个API定义了一组应用程序使用的编程接口

3.系统调用

#内核必需提供系统调用所希望完成的功能,但它完全可以按照自己的方式去实现,只要最后结果正确

#所有的系统调用都要asmlinkage限定词

#为保证32/64位兼容,系统调用在用户空间返回值时int,内核空间为long

    1.系统调用号:

        #在Linux中每个系统调用被赋予一个系统调用号

        #系统调用号一旦分配不可改变,否则编译好的应用会崩溃

        #Linux上有一个“未实现”的系统调用sys_ni_syscall(),它除了返回-ENOSYS外不做其他任何工作

          如果一个系统调用被删除,或变的不可用,这个函数去填补空缺

    2.系统调用的性能

        #Linux系统调用比其他操作系统要快,原因:

            1.Linux很短的上下文切换时间

            2.系统调用处理程序和每个系统调用非常简洁

4.系统调用处理程序

#通知内核的机制靠软中断实现,通过引发异常来促使系统切换到内核态去执行异常处理程序(系统调用处理程序)

#指定恰当的系统调用:

        在x86上通过eax寄存器将系统调用号传递给内核

        system_call()函数通过将给定的系统调用号与NR_syscalls()作比较来检查其有效性

#参数传递:在x86-32系统上,ebx,ecx,edx,esi,edi按照顺序存放前五个参数

                  给用户空间的返回值通过eax寄存器传递(x86)

5.系统调用的实现

#实现系统调用:

    每个系统调用都有一个明确的用途

    系统调用的接口力求简洁,参数尽可能少

    设计接口的时候要尽量为将来多做考虑

#参数验证:

    #系统调用必须验证他们所有的参数是否合法有效,最重要的检查时检查用户提供的指针是否有效

    #在接受一个用户空间的指针之前,内核必须保证:

        1.指针指向的内存区域属于用户空间,进程决不能让内核去读取内核空间的数据

        2.指针指向的内存区域在进程的地址空间,进程决不能让内核去读取其他进程的数据

        3.如果是读,内存标记为可读;如果是写,标记为可写;如果标记为可执行,进程决不能绕过内存访问限制

6.系统调用上下文

#绑定一个系统调用的最后步骤:

    1.首先,在系统调用表的最后加入一个表项

    2.系统调用号定义于<asm/unistd.h>中

    3.系统调用必须被编译进内核映像(不能编译为模块)

#建立新的系统调用的利与弊:

    利:#系统调用创建容易且使用方便

          #Linux系统调用高性能

    弊:#需要一个系统调用号,由官方分配

          #系统调用加入稳定内核后被固化,它的接口不允许改动

          #需要将系统调用分别注册到每个需要支持的结构体系去

          #在脚本中不容易调用,也不能从文件系统直接访问系统调用

          #在主内核树之外很难维护和调用系统调用

继续阅读