zoukankan      html  css  js  c++  java
  • 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) != '' && 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
    ");
            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
    ");
                    return -1;
            }
            printf("%s
    ",str);
        return 0;
    }

      结果

      

  • 相关阅读:
    算法笔记_091:蓝桥杯练习 递推求值(Java)
    算法笔记_090:蓝桥杯练习 7-1用宏求球的体积(Java)
    算法笔记_089:蓝桥杯练习 7-2求arccos值(Java)
    算法笔记_088:蓝桥杯练习 8-1因式分解(Java)
    算法笔记_087:蓝桥杯练习 9-1九宫格(Java)
    算法笔记_086:蓝桥杯练习 9-2 文本加密(Java)
    算法笔记_085:蓝桥杯练习 9-3摩尔斯电码(Java)
    面试(3)-java-se-java中的匿名内部类总结
    面试(2)-java-se-HashSet和TreeSet
    面试(1)-java-se-字符串
  • 原文地址:https://www.cnblogs.com/Ccluck-tian/p/11861975.html
Copyright © 2011-2022 走看看