zoukankan      html  css  js  c++  java
  • 《程序员的自我修养》读书笔记——系统调用、API

     
     

    系统调用

    程序运行的时候,本身是没有权限访问多少系统资源的。系统资源有限,如果操作系统不进行控制,那么各个程序难免会产生冲突。线程操作系统都将可能产生冲突的系统资源保护起来,阻止程序直接访问。比如文件、网络、IO、各种设备等。

    系统调用涵盖的功能很广,有程序运行锁必须的支持,如创建和退出进程、线程,进程内存管理,对系统资源的访问等。

    Linux系统调用与中断

    在x86下,系统调用是通过0x80中断完成,各个通用寄存器用于传递参数。EAX寄存器用于表示系统调用的接口号。

    比如:EAX=1表示退出进程,EAX=2表示创建进程,EAX=3表示读文件或IO,EAX=4表示写文件或IO。每个系统调用对应到内核源码中的一个函数,他们都是以sys_开头的,比如exit调用对应内核中的sys_exit函数

    如果直接使系统调用会有非常多的问题:

    • 使用不方便,操作系统提供的系统调用接口往往过于原始。程序员需要了解很多跟操作系统相关的细节
    • 各个操作系统之间系统调用不兼容

    于是增加一个层来解决,系统调用与程序之间增加一个抽象层。这个层就是前面所说的glibc,或者API.

    系统调用原理

    这里单单以Linux为例,至于Windows调用原理暂时省略。

    用户态、内核态、中断与系统安全

    现代操作系统中有两种特权级别,分为用户模式和内核模式。

    多个模式存在,那么操作系统就可以让不同代码运行在不同模式下,进而限制代码的权限,提高稳定性、安全性。一般普通程序在用户态,操作会受到限制。系统调用运行在内核态,应用程序基本都是运行在用户态被限制。

    用户态的程序通过中断来运行内核态的代码,进而从用户态切换到内核态。

     

    比如Linux中int 0x80为例,系统调用号使用eax来传入,用户将系统调用号保存在eax,然后使用int 0x80调用中断,中断服务传给信号就可以从eax取得系统调用号,进行调用相应的函数。

     

    切换堆栈

    在实际执行中断向量表中的第0x80好中断之前,CPU还要进行堆栈的奇幻,在Linx中,用户态和内核态使用的是不同的栈,两者各自负责各自的函数调用,互不干扰。

    在执行0x80中断的时候,程序从用户态切换到内核态。这时相应的栈也必须切换到内核栈,从中断处理函数中返回时,程序当前栈需要从内核栈切换到用户栈。

    当前栈是指ESP值所在的栈空间,如果ESP的值位于用户栈范围能,那么程序的当前栈就是用户栈。内核栈同理。并且SS的值需要指向当前栈所在的页。所以用户栈切换到内核栈就是:

    • 保存当前ESP、SS的值
    • 将ESP、SS的值设置为内核栈的值

    (反过来同理)

    • 恢复原理ESP、SS的值
    • 用户态的ESP和SS的值保存在内核栈上,

    当发生中断的时候,CPU除了进入内核态之外还会做如下事情:

    • 找到当前进程的内核栈(每一个进程都有一个内核栈)
    • 在内核栈中一猜压入用户态的寄存器SS、ESP、EFLAGS、CS、EIP

    当内核从系统调用中返回,则调动iret指令回到用户态,iret指令会从内核栈里面弹出SS、ESP、EFLAGS、CS、EIP的值。使得栈恢复到用户态的状态。

     


    作者:纸简书生
    链接:https://www.jianshu.com/p/4b9c40e6b8ae
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 相关阅读:
    Android 一个app启动另一个app
    Android 电池电量进度条,上下滚动图片的进度条(battery)
    Android 返回键双击退出程序
    Failed to load or instantiate
    GNUstep 快捷键编译
    Android 文件夹命名规范 国际化资源
    mac 安装protobuf,并编译为java,c++,python
    Android 贝塞尔曲线 折线图
    android 制作自定义标题栏
    Gson
  • 原文地址:https://www.cnblogs.com/feng9exe/p/10738380.html
Copyright © 2011-2022 走看看