LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1062|回复: 0

2.6内核下以模块方式添加系统调用的问题

[复制链接]
发表于 2007-6-6 13:27:12 | 显示全部楼层 |阅读模式
我在2.6.15内核下以模块方式添加系统调用,出现了一些问题,结果不对,谁能知道错在那?

模块如下:
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
#include<linux/unistd.h>

#include<linux/time.h>

#include<asm/uaccess.h> // for copy_to_user
#include<linux/sched.h> // for current macro

#define __NR_pedagogictime 223

static int (*oldsaved)(void);

// 中断描述符表寄存器结构
struct {
    unsigned short limit;
    unsigned int base;
} __attribute__((packed)) idtr;

// 中断描述符表结构
struct {
    unsigned short off1;
    unsigned short sel;
    unsigned char none, flags;
    unsigned short off2;
} __attribute__((packed)) idt;

// 查找sys_call_table的地址
unsigned long * get_sys_call_table(void)
{
    unsigned int sys_call_off;
    unsigned long *sys_call_table=NULL;
    char* p;
    int i;

    // 获取中断描述符表寄存器的地址
    asm("sidt %0":"=m"(idtr));
    printk("中断描述符表寄存器的地址  idtr: %x\n", &idtr);

    // 获取0x80中断处理程序的地址
    memcpy(&idt, idtr.base+8*0x80, sizeof(idt));
    sys_call_off=((idt.off2<<16)|idt.off1);
    printk("0x80中断处理程序的地址: %x\n", sys_call_off);

    // 从0x80中断服务例程中搜索sys_call_table的地址
    p=(char *)sys_call_off;
    for (i=0; i<1000; i++)
          {
        if (p=='\xff' && p[i+1]=='\x14' && p[i+2]=='\x85')
                    {
            sys_call_table=*(unsigned int*)(p+i+3);
            printk("1: Address of sys_call_table: %x\n", (unsigned int)sys_call_table);
            break;
           
                    }
        }
   if(i==100)printk("没有找到!");
   return sys_call_table;
}

asmlinkage int sys_pedagogictime(struct timeval *tv)
{
    struct timeval ktv;
    do_gettimeofday(&ktv);

    copy_to_user(tv,&ktv,sizeof(ktv));
    printk("ktv_sec: %ld      \n",ktv.tv_sec);
    return 0;
}

int init_syscall(void)
{
    unsigned long *sys_call_table=NULL;

    sys_call_table=get_sys_call_table();
    printk("2: address of sys_call_table : %x\n", (unsigned int)sys_call_table);
    oldsaved=(int(*)(void))(sys_call_table[__NR_pedagogictime]);
    sys_call_table[__NR_pedagogictime]=(unsigned long)sys_pedagogictime;

    return 0;
}

void exit_syscall(void)
{
    unsigned long *sys_call_table=NULL;

    sys_call_table=get_sys_call_table();
    sys_call_table[__NR_pedagogictime]=(unsigned long)oldsaved;

}

module_init(init_syscall);
module_exit(exit_syscall);
MODULE_LICENSE("GPL");

调用程序为:
#include<linux/unistd.h>
#include<sys/time.h>

#define __NR_pedagogictime 223

_syscall1(int,pedagogictime,struct timeval *,tv)


int main()
{
  struct timeval tv,dtv;

  pedagogictime(&tv);
  gettimeofday(&dtv,NULL);
  printf("tv_sec:%ld         dtv_sec:%ld\n",tv.tv_sec,dtv.tv_sec);
  printf("tv_usec:%ld        dtv_usec:%ld\n",tv.tv_usec,dtv.tv_usec);

  printf("em...,let me sleep for 2 second.\n");
  sleep(2);
  pedagogictime(&tv);
  printf("tv_sec:%ld\n",tv.tv_sec);
  printf("tv_usec:%ld\n",tv.tv_usec);
}

make文件为:
obj-m := pedagogictime.o
KERNELDIR = /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
clean:
        rm -f *.ko *.mod *.mod.o *.o

编译和调用时出现的问题:
[root@localhost zjf]# make
make -C /lib/modules/2.6.15-1.2054_FC5/build SUBDIRS=/zjf modules
make[1]: Entering directory `/usr/src/redhat/BUILD/kernel-2.6.15/linux-2.6.15.i6 86'
  CC [M]  /zjf/pedagogictime.o
/zjf/pedagogictime.c: 在函数 ‘get_sys_call_table’ 中:
/zjf/pedagogictime.c:42: 警告:格式 ‘%x’ 需要类型 ‘unsigned int’,但实参 2 的类 型为 ‘struct <anonymous> *’
/zjf/pedagogictime.c:45: 警告:传递参数 2 (属于 ‘__constant_memcpy’)时将整数赋给 指针,未作类型转换
/zjf/pedagogictime.c:45: 警告:传递参数 2 (属于 ‘__memcpy’)时将整数赋给指针,未 作类型转换
/zjf/pedagogictime.c:55: 警告:赋值时将整数赋给指针,未作类型转换
/zjf/pedagogictime.c: 在函数 ‘sys_pedagogictime’ 中:
/zjf/pedagogictime.c:70: 警告:忽略声明有 warn_unused_result 属性的 ‘copy_to_use r’ 的返回值
  Building modules, stage 2.
  MODPOST
  CC      /zjf/pedagogictime.mod.o
  LD [M]  /zjf/pedagogictime.ko
make[1]: Leaving directory `/usr/src/redhat/BUILD/kernel-2.6.15/linux-2.6.15.i68 6'
[root@localhost zjf]# insmod pedagogictime.ko
段错误
[root@localhost zjf]#
Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: Oops: 0003 [#1]

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: CPU:    0

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: EIP is at init_module+0x1e/0x2e [pedagogictime]

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: eax: c012a524   ebx: c02e04a0   ecx: c9350e6c   edx: d0275197

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: esi: d0275700   edi: ca60ae48   ebp: d0275748   esp: c9350e68

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: ds: 007b   es: 007b   ss: 0068

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: Process insmod (pid: 2900, threadinfo=c9350000 task=c6398000)

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: Stack: <0>d0275197 c02e04a0 ca60ae48 c0130506 0000b0b6 0000043 8 00000300 d0275700

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel:        00000000 00000000 00000000 00000000 00000000 00000000 0 0000000 d03359b4

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel:        00000000 c7132340 d03325cc d03322d4 d03325f4 d0327000 0 0000004 00000004

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: Call Trace:

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel:  [<c0130506>] sys_init_module+0x1382/0x1514     [<c015240f>] d o_sync_read+0xb8/0xf3

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel:  [<c0172fd1>] inotify_inode_queue_event+0x44/0x131     [<c01c0 66e>] _atomic_dec_and_lock+0x22/0x2c

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel:  [<c0169c2e>] mntput_no_expire+0x11/0x6d     [<c0102bc1>] sysc all_call+0x7/0xb

Message from syslogd@localhost at Wed Jun  6 12:26:07 2007 ...
localhost kernel: Code: 8b 15 10 59 27 d0 89 90 7c 03 00 00 c3 53 e8 4a ff ff ff  89 c3 50 68 97 51 27 d0 e8 5e 5c ea ef 8b 83 7c 03 00 00 a3 10 59 27 d0 <c7> 83  7c 03 00 00 de 50 27 d0 5b 58 31 c0 5b c3 53 83 ec 08 89

[root@localhost zjf]# ./test5
tv_sec:134513990         dtv_sec:1181103993
tv_usec:3214912        dtv_usec:951909
em...,let me sleep for 2 second.
tv_sec:134513990
tv_usec:3214912
[root@localhost zjf]#
大家注意上面的输出:tv_sec:134513990 这是自定义系统调用输出的结果,                                        dtv_sec:1181103993这是调用系统函数gettimeofday()输出的
结果,两者显然不对,谁知道错那儿了?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表