linux0.11添加系統調用


概述

printf()是c語言中一個很常用的函數,printf()底層如何實現,如何在中斷設備上顯示出字符?

linux系統下,printf()的底層是對系統調用write()的封裝。

應用程序在使用硬件資源時,一般都是通過系統調用來告知操作系統使用哪些資源,系統調用會通過int0x80中斷進入到內核態工作,將應用程序的需求滿足后,返回用戶態,應用程序再繼續執行。

  

系統調用write

開機后,操作系統在進行初始化時會調用sched_init(); --->set_system_gate() 設置一個系統調用處理函數的入口地址(當應用程序再運行中進行任何一個系統調用時觸發0x80中斷,首先會找到處理函數的入口地址)

  

0x80中斷處理程序system_call 首先進行系統調用號的檢查(系統調用號放在eax中,參數分別放在ebx,ecx,edx中),匹配上之后進行sys_call_table[]中找到該系統調用號所對應的系統調用函數在內核中的地址,即sye_write()的地址,在調用sys_write()進行輸出工作,此時一直處於內核態, 所有的資源都可以訪問。sys_write()執行完畢返回,system_call返回,系統調用結束。

  

 

在linux0.11內核上添加系統調用

1、添加foo() 系統調用的步驟為:

  ①在linux-0.11/include/unistd.h下定義系統調用號,並聲明系統調用函數的形式。

  ②在linux-0.11/kernel/system_call.s中修改系統調用的個數,以使此系統調用被調用時,可以識別到。

  ③在linux0.11/include/sys.h中添加extern頭,再在sys_call_table[]中加入系統調用的‘地址’。

  ④在linux-0.11/kernel中實現該系統調用,並修改Makefile文件。

  ⑤將usr/include/unistd.h文件中添加(第①步)系統調用號和系統調用的聲明。

  ⑥寫測試程序進行測試。

2、實現

  ①    define __NR_iam 72 

    define __NR_whoami 73

  

  ②在linux-0.11/kernel/system_call.s中修改 nr_system_calls = 74 //system_call會判斷是否有該系統調用號

    ③linux0.11/include/sys.h

  

   ④linux-0.11/kernel中定義who.h,並修改Makefile文件

  

    

 

#define __LIBRARY__
#include<asm/segment.h>  //定義了get_fs_byte()和set_fs_byte()
#include<errno.h> //定義EINVAL
char ch[24] ;
int len = 0;
int sys_iam(const char* name)
{
        int i = 0; 
        while(get_fs_byte(name + i) != '\0' && i<=23) i++;
        if( i == 24) return -EINVAL;
        len = i ;
        for(;i>=0;i--)
        {//將用戶數據段的數據復制到內核數據段
            ch[i] = get_fs_byte(name + i);
        }
        return  len;
}
int sys_whoami(char* name,unsigned int size)
{
        int i = len ;
        if(len > size - 1) return -EINVAL;
        while(i>=0) 
        {//將內核數據段的數據復制到用戶數據段
            put_fs_byte(ch[i],name + i);
            i--;
        }
        return len ;
}

  ⑤同第一步(usr/include/unistd.h)

  ⑥測試代碼(usr/root-->whoami.c、iam.c)

#define __LIBRARY__
#include<errno.h>
#include<unistd.h>
_syscall1(int, iam, const char*, name);
int main(int argc, char * argv[]){
    if(iam(argv[1])<0)
    {
        printf("error\n");
        return -1;
    }
    return 0;
}
#define __LIBRARY__
#include<errno.h>
#include<unistd.h>
#include<stdio.h>
_syscall2(int,whoami,char*,name,unsigned int,size);
int main(int argc, char * argv[]){
        char str [24];
        if(whoami(str,24)<0)
        {
                printf("error\n");
                return -1;
        }
        printf("%s\n",str);
    return 0;
}

  結果

  

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM