zoukankan      html  css  js  c++  java
  • 程序员的自我修养——第十二章——系统调用与API

          系统调用接口往往是通过中断来实现,比如Linux使用0x80号中断作为系统调用的入口,Windows采用0x2E号中断作为系统调用的入口。

    EAX

    名字

    C语言定义

    含义

    参数

    1

    exit

    void _exit(int status)

    退出进程

    EBX表示退出码

    2

    fork

    pid_t fork(void)

    复制进程

    EBX表示复制参数

    3

    read

    ssize_t read( int fd,

    void    *buf,

    size_t  count)

    读文件

    EBX表示文件句柄,ECX表示读取缓冲地址,EDX表示读取的大小

    4

    write

    ssize_t write( int fd,

    const void *buf,

    size_t   count);

    写文件

    同sys_read

    5

    open

    Int open(

        Const char *path

        int flags,

        mode_t mode);

    打开文件

    EBX表示文件路径,ECX表示打开文件的模式,EDX也表示打开的模式

    ...

     

     

     

    我们可以通过系统调用open()、read()和close()来绕过glibc的fopen()、fread()、fclose()。

    /*sys_call_01.c*/

    #include <unistd.h>

    int main()

    {

    char buffer[64];

    char buffer_r[64];

    char *error_message = "open file error \n";

    char *success_message = "open file success \n";

    char *message = "please input something\n";

    write(0,message,strlen(message));

    int r_len = read(1,buffer_r,64);

    buffer_r[r_len] = '\0';

    printf("read_len = %d \t buffer_read = %s \n",r_len,buffer_r);

    int fd = open("readme.txt",0,0);

    if(fd == -1)

    {

    write(0, error_message, strlen(error_message));

    return -1;

    }

    write(0,success_message, strlen(success_message));

    read(fd, buffer,64);

    printf("buffer: %s\n",buffer);

    close(fd);

    return 0;

    }

    注:stdin,stdout, stderr 的文件描述符分别为'0','1','2'

    $ ./sys_call_01

    please input something

    read from stdin

    read_len = 16    buffer_read = read from stdin

    open file success

    buffer: this is a test!

    this is a test!

    this is a test!

    this is a tes/

    在不同的系统中,系统调用是不相同的,为了统一,各种编程语言提供了运行库的接口来统一相同的功能。

    比如,C语言里面的fread,用于读取文件,在Windows下这个函数的实现可能是调用ReadFile这个API,而如果在Linux下则很可能调用read这个系统调用。但不在管哪个平台,我们都可以使用C语言运行库的fread来读取文件。

    运行时库将不同的操作系统的系统调用包装为统一固定的接口,使得同样的代码,在不同的操作系统下都可以直接编译,并产生一致的效果。这就是源代码级上的可移植性。

    中断一般有两个属性,一个称为中断号(从0开始),一个称为中断处理程序(Interrupt Service Routine,ISR)。不同的中断具有不同的中断号,而同时一个中断处理程序一一对应一个中断号。在内核中,有一个数组称为中断向量表(Interrupt Vector Table),这个数组的第n项包含了指向第n个中断的中断处理程序的指针。

    一个函数指针的数组:

    (* ivt[])(int n) = { isr_01, isr-02, isr_03,...}

     

                                                           CPU中断过程

    基于int的Linux的经典系统调用实现:

    1. 触发中断     2.    切换堆栈     3.    中断处理程序

    在2.6的内核里面没有找到_syscall0

     

     

    Windows API

    一个普通的fwrite()的调用路径:

    Windows API现在的数量很庞大,按照功能被划分为几大类:

    所以不管内核如何改变接口,只要维持API层面的接口不变,理论上所有的应用程序都不用重新编译就可以正常运行,这也是Windows API存在的主要原因。

     对于第下一章的内容暂时不转上来了,我只看了C的运行库的设计,基本上看懂了,什么时候来好好学习一下!

  • 相关阅读:
    IDA .edata .rdata .idata .text segments
    How to detect the types of executable files
    Dynamic-Link Library Redirection
    J-Link Version
    PE文件结构部分解析以及输入的定位
    Delphi : Analyze PE file headers?
    How to tell if a file is an EXE or a DLL?
    PE Header and Export Table for Delphi
    NXP ARM Vector Table CheckSum
    反接保护电路 Reverse Voltage Protection
  • 原文地址:https://www.cnblogs.com/zhuyp1015/p/2496730.html
Copyright © 2011-2022 走看看