Chinaunix

标题: 请问怎么把Linux 多个C文件编译成一个ko文件呢?(C文件里都有module_init) [打印本页]

作者: 牡丹岩    时间: 2014-08-26 11:50
标题: 请问怎么把Linux 多个C文件编译成一个ko文件呢?(C文件里都有module_init)
是这样的:我用platform平台总线做驱动,有两个文件:

(1)平台设备led_dev.c

(2)平台驱动led_drv.c

l现在问题是,

led_dev.c中有:

int __init led_dev_init(void)
{
    platform_device_register(&led_device);  
   
    return 0;
}

module_init(led_dev_init);



led_drv.c中有:

int __init led_drv_init(void)
{
    platform_driver_register(&led_driver);
   
    return 0;
}

module_init(led_drv_init);

采用编译成模块时,
Makefile这样写:obj-m += led_dev.o led_drv.o
是可以把led_dev.c编译成led_dev.ko
         把led_drv.c编译成led_drv.ko

然后加载时insmod两次就行了!

但现在我想:能不能仅编译成一个ko文件,

加载时只需insmod一次就行了?

为达到此效果,我的Makefile改成这样:
obj-m += led.o
led-objs := led_dev.o led_drv.o
但编译会报错: multiple definition of `init_module'

请问:各位有什么方法呢?不妨赐教啊!小弟谢过~
作者: lamp_lighter    时间: 2014-08-26 14:32
两个模块如果有关联,可以试试modprobe。要是觉得输入太多insmod麻烦,干脆写个脚本算了
作者: 牡丹岩    时间: 2014-08-26 16:49
谢谢  我的两个模块 有关联的,一个是平台设备,一个平台驱动。你说的写脚本 是指利用脚本去完成多个ko文件的insmod吗?还是编译成一个ko文件呢?
作者: lamp_lighter    时间: 2014-08-26 17:13
回复 3# 牡丹岩

关联的意思是模块具有依赖性,比如说一个模块会用到另一个模块的函数。modprobe会检查这种依赖性,然后先把依赖的模块的装上,再装其他的模块。脚本就是:
#/bin/bash
insmod **
insmod **
insmod **
*********
然后sudo运行
作者: 牡丹岩    时间: 2014-08-26 17:37
嗯 谢啦。不过 有没有办法 编译成一个ko文件呢?

再问个问题:我insmod 加载驱动模块时,开发板会自动重启,这是为啥啊?
作者: lamp_lighter    时间: 2014-08-26 17:45
回复 5# 牡丹岩
这我就不知道了,等其他人答吧
作者: 牡丹岩    时间: 2014-08-26 18:24
本帖最后由 牡丹岩 于 2014-08-26 18:27 编辑

写个脚本 效果 还真不错 相见恨晚啊  谢了 !

内核重启时提示错误如下:
kernel bug at kernel/timer.c:662!
Unable to handle kernel NULL pointer dereference at virtual address 00000000

自动重启.png (82.49 KB, 下载次数: 95)

自动重启.png

作者: baron_zz    时间: 2014-08-28 10:30
内核遇到空指针时,必然会重启。说明,你的驱动注册过程中,有野指针之类的错误出现。不信你把 platform_device_register(&led_device)和platform_driver_register(&led_driver)注释掉,看看,保证不重启。检查代码错误吧!
作者: baron_zz    时间: 2014-08-28 10:31
内核重启时提示错误如下:
kernel bug at kernel/timer.c:662!
Unable to handle kernel NULL pointer dereference at virtual address 00000000

另外看你的Log提示, NULL pointer ,分明就是野指针。。再看溢出文件:timer.c:662!,定时器/看门狗退出
所以,检查你的源文件吧
作者: 牡丹岩    时间: 2014-08-28 13:07
本帖最后由 牡丹岩 于 2014-08-28 13:13 编辑

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/input.h>
  4. #include <linux/interrupt.h>
  5. #include <asm/gpio.h>
  6. #include <linux/timer.h>


  7. static struct input_dev *p_button_dev = NULL;//定义输入设备

  8. struct timer_list my_timer;//定义定时器


  9. //定义定时器超时处理函数
  10. void timer_func(unsigned long data)
  11. {
  12.         int key_value = gpio_get_value(S5PV210_GPH2(0));

  13.         //上报事件给input核心层
  14.         input_report_key(p_button_dev, KEY_A, !key_value);//按下为1,释放为0

  15.              //告诉input子系统上报已经完成
  16.         input_sync(p_button_dev);
  17. }

  18. //中断处理函数
  19. static irqreturn_t button_interrupt(int irq, void *dev_id)
  20. {
  21.              mod_timer(&my_timer, jiffies + 5);//启动定时器以及设置超时时间
  22.    
  23.         return IRQ_HANDLED;
  24. }

  25. //初始化按钮
  26. static int __init button_init(void)
  27. {
  28.         int ret;
  29.         ret = gpio_request(S5PV210_GPH2(0), "key2");
  30.         if (ret)
  31.              {
  32.                 printk(KERN_ERR "gpio_request Failed to register device\r\n");

  33.                           goto error1;
  34.         }
  35.    
  36.              //为新输入设备分配内存并初始化
  37.         p_button_dev = input_allocate_device();
  38.         if (!p_button_dev)
  39.              {
  40.                 printk(KERN_ERR "can't allocate input mem!\r\n");

  41.                          goto error2;
  42.         }
  43.    
  44.         p_button_dev->name = "gec_input";
  45.         p_button_dev->id.bustype = 0x1;
  46.         p_button_dev->id.product = 0x2;
  47.         p_button_dev->id.vendor  = 0x3;
  48.         p_button_dev->id.version = 0x4;
  49.         p_button_dev->evbit[BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY);       
  50.              p_button_dev->keybit[BIT_WORD(KEY_A)] = BIT_MASK(KEY_A);   
  51.              //注册一个输入设备
  52.         ret = input_register_device(p_button_dev);
  53.         if (ret)
  54.              {
  55.                 printk(KERN_ERR "Failed to register device\r\n");

  56.                           goto error3;
  57.         }
  58.    
  59.                //申请中断注册中断处理函数
  60.         ret = request_irq(IRQ_EINT(16), button_interrupt,
  61.                                  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_DISABLED,
  62.                                       "button", NULL);
  63.         if (ret)
  64.         {
  65.                 printk(KERN_ERR "Can't request irq %d\r\n", IRQ_EINT(16));

  66.                           goto error4;
  67.         }   
  68.    
  69.         //定时器
  70.         init_timer(&my_timer);//初始化定时器
  71.         my_timer.function = timer_func;//注册定时器超时处理函数

  72.          return 0;
  73.    

  74. error4:
  75.             free_irq(IRQ_EINT(16), NULL);//释放分配给已定中断的内存
  76.          input_unregister_device(p_button_dev);
  77.    
  78. error3:
  79.             input_free_device(p_button_dev);

  80. error2:
  81.            ret = -ENOMEM;

  82. error1:
  83.            gpio_free(S5PV210_GPH2(0));
  84.    
  85.            return ret;
  86. }

  87. static void __exit button_exit(void)
  88. {
  89.         gpio_free(S5PV210_GPH2(0));       
  90.         free_irq(IRQ_EINT(16), NULL);
  91.         input_unregister_device(p_button_dev);
  92.         del_timer(&my_timer);//删除内核定时器
  93. }

  94. module_init(button_init);
  95. module_exit(button_exit);

  96. MODULE_LICENSE("Dual BSD/GPL");
  97. MODULE_LICENSE("GPL");

复制代码

作者: chzfmx    时间: 2015-06-07 00:47
回复 1# 牡丹岩

多个.c文件变异成一个.ko文件时,多个.c文件中只能有一个module_init()和module_exit(),不能有多个
   
作者: 牡丹岩    时间: 2015-06-13 20:12
回复 11# chzfmx
好的

   




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2