使用内核模块添加系统调用

使用内核模块添加系统调用

 

1,为什么要使用内核模块的方式添加系统调用?

    1.1,编译内核的方式费时间,一般的PC机都要两三个小时。

    1.2,不方便调试,一旦出现问题前面的工作都前功尽弃。

-------------------------------------------------------

2,首先要获取系统调用表sys_call_table的地址(虚拟地址)

   因为sys_call_table在内核中没有导出,可以使用如下命令查看。

 cat /boot/System.map-`uname -r`|grep sys_call_table


注意点:当我把模块在一个机子上运行成功后,如果移植到另外一个机子上马上就会出现

        错误,为什么呢?因为每个机子上sys_call_table的地址可能不一样。

-------------------------------------------------------

3,需要查看预留的系统调用号。

  可以到arch/x86/include/asm/unistd.h文件中查看预留的系统调用号。

可以看出223就是一个预留的系统调用号。

-------------------------------------------------------

4.创建c文件。实例:syscall.c

 

    #include <linux/init.h>

    #include <linux/module.h>

    #include <linux/kernel.h>

    #include <linux/unistd.h>

    #include <asm/uaccess.h>

    #include <linux/sched.h>

 

    #define my_syscall_num 223

    //如下的这个值要到你机子上查。cat /boot/System.map-`uname -r`|grep sys_call_table

    #define sys_call_table_adress 0xc0582130//(此处是上面命令查出的地址)

    unsigned int clear_and_return_cr0(void);

    void setback_cr0(unsigned int val);

    asmlinkage long sys_mycall(long num);

    int orig_cr0;

    unsigned long *sys_call_table = 0;

    static int (*anything_saved)(void);

    unsigned int clear_and_return_cr0(void)

    {

     unsigned int cr0 = 0;

     unsigned int ret;

     asm("movl %%cr0, %%eax":"=a"(cr0));

     ret = cr0;

     printk("cr0 = %d\n",ret);

     cr0 &= 0xfffeffff;

     asm("movl %%eax, %%cr0"::"a"(cr0));

     return ret;

    }

 

    void setback_cr0(unsigned int val) //读取val的值到eax寄存器,再将eax寄存器的值放入cr0中

    {

     asm volatile("movl %%eax, %%cr0"::"a"(val));

    }

 

    static int __init init_addsyscall(void)

    {

     printk("hello, kernel\n");

     sys_call_table = (unsigned long *)sys_call_table_adress;//获取系统调用服务首地址

     anything_saved = (int(*)(void)) (sys_call_table[my_syscall_num]);//保存原始系统调用的地址

     orig_cr0 = clear_and_return_cr0();//设置cr0可更改

     sys_call_table[my_syscall_num] = (unsigned long)&sys_mycall;//更改原始的系统调用服务地址

     setback_cr0(orig_cr0);//设置为原始的只读cr0

     return 0;

    }

 

    asmlinkage long sys_mycall(long num)

    {

            printk("This is my_syscall!\n");

         if(num%2==0)

                   printk("my id is 0%ld\n",num%10000);

         else

                   printk("my id is %ld\n",num%100000);

            return current->pid;

    }

 

    static void __exit exit_addsyscall(void)

    {

     //设置cr0中对sys_call_table的更改权限。

     orig_cr0 = clear_and_return_cr0();//设置cr0可更改

 

     //恢复原有的中断向量表中的函数指针的值。

     sys_call_table[my_syscall_num] = (unsigned long)anything_saved;

    

     //恢复原有的cr0的值

     setback_cr0(orig_cr0);

 

     printk("call exit \n");

    }

 

    module_init(init_addsyscall);

    module_exit(exit_addsyscall);

    MODULE_LICENSE("GPL");

 

 

5.创建Makefile文件(与syscall.c文件创建在同一文件夹下)

obj-m := syscall.o //(与自己创建的c文件名对应)

KERNELDIR := /lib/modules/$(shell uname -r)/build

PWD := $(shell pwd)

modules:

         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:

         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

 

clean:

         rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

 -------------------------------------------------------------------------------

6.执行make命令

 -------------------------------------------------------------------------------

7.执行sudo insmod syscall.ko 命令

-------------------------------------------------------------------------------

8.将模块插入成功后,剩下的就是在用户态下测试是否成功

-------------------------------------------------------------------------------

9.编写c程序(test.c)

#include<stdio.h>

int main()

{

         syscall(223,13130000);//第二个参数填你的学号

         return 0;

}

 ------------------------------------------------------------------------------

10.编译c程序  gcc –o test test.c

------------------------------------------------------------------------------

11.dmesg


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值