如果构建为外部模块,Linux Char设备驱动程序不起作用,但如果构建为运行内核,则工作。但为什么?

问题描述:

OS:Fedora的26阿尔法如果构建为外部模块,Linux Char设备驱动程序不起作用,但如果构建为运行内核,则工作。但为什么?

内核:Linux的4.11

内核手动通过以下命令编译:

1)使oldconfig这个

2)的make menuconfig

3)使所有

4)make module_install

5)使安装

在成功编译和安装最新的内核, 我建立了一些模块,但为通过make -C /root/linux-4.11/ M=$(pwd) modules一个外部模块不是针对运行的内核。 我开发的所有基本模块都是按照预期编译,安装和工作的,但后来我编写了基本的字符设备驱动程序,但后来发现了一些奇怪的问题。也就是说,在通过insmod成功编译和插入模块之后,我没有收到关于此模块的任何内核消息,也没有在/ dev /目录中生成char设备,然后我也搜索了有关此问题但没有得到任何更好的回答这个问题。

然后,突然我试图将其编译并通过make -C /lib/modules/$(uname -r)/build/ M=$(pwd) modules作为运行内核,然后插入模块后,我得到了我的预期结果。 但是现在,我想知道为什么会发生这种情况,因为其他简单模块在构建为外部模块时工作正常,但为什么不是这个?

#include <linux/init.h> 
#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/device.h> 
#include <linux/kdev_t.h> 
#include <linux/uaccess.h> 
#include <linux/types.h> 
#include <linux/fs.h> 
#include <linux/cdev.h> 
#include <linux/version.h> 

MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("Neeraj Pal <[email protected]>"); 
MODULE_DESCRIPTION("Sample Character Driver"); 


static dev_t first; 
static struct device *dev_ret; 
static struct cdev c_dev; 
static struct class *cl; 


static int dev_open(struct inode *,struct file *); 
static int dev_release(struct inode *,struct file *); 
static ssize_t dev_read(struct file *, char __user *,size_t count, loff_t *); 
static ssize_t dev_write(struct file *, const char __user *,size_t count, loff_t *); 

static struct file_operations fops = { 
    .owner = THIS_MODULE, 
    .open = dev_open, 
    .read = dev_read, 
    .write = dev_write, 
    .release = dev_release 
}; 

static int __init chardev_init(void) 
{ 
    int ret; 
    printk(KERN_ALERT "char device registered\n"); 
    if ((ret = alloc_chrdev_region(&first,0,1,"Namastey")) < 0) 
    { 
     return ret; 
    } 
    if (IS_ERR(cl = class_create(THIS_MODULE,"hello"))) 
    { 
     unregister_chrdev_region(first,1); 
     return PTR_ERR(cl); 
    } 
    if (IS_ERR(dev_ret = device_create(cl,NULL,first,NULL,"mychar"))) 
    { 
     class_destroy(cl); 
     unregister_chrdev_region(first,1); 
     return PTR_ERR(dev_ret); 
    } 

    cdev_init(&c_dev,&fops); 

    if ((ret = cdev_add(&c_dev, first, 1)) < 0) 
    { 
     device_destroy(cl, first); 
     class_destroy(cl); 
     unregister_chrdev_region(first, 1); 
     return ret; 
    } 
    return 0; 
} 

static void __exit chardev_exit(void) 
{ 
    cdev_del(&c_dev); 
    device_destroy(cl, first); 
    class_destroy(cl); 
    unregister_chrdev_region(first, 1); 
    printk(KERN_INFO " Unloaded \n"); 
} 


static int dev_open(struct inode *i, struct file *f) 
{ 
    printk(KERN_INFO "Driver: open()\n"); 
    return 0; 
} 
static int dev_release(struct inode *i, struct file *f) 
{ 
    printk(KERN_INFO "Driver: close()\n"); 
    return 0; 
} 
static ssize_t dev_read(struct file *f, char __user *buf, size_t len, loff_t *off) 
{ 
    printk(KERN_INFO "Driver: read()\n"); 
    return 0; 
} 
static ssize_t dev_write(struct file *f, const char __user *buf, size_t len, 
    loff_t *off) 
{ 
    printk(KERN_INFO "Driver: write()\n"); 
    return len; 
} 


module_init(chardev_init); 
module_exit(chardev_exit); 

编译&内核日志&内核,操作系统详细资料(既是外部模块,然后作为对运行内核):

[[email protected] ldd]# uname -a 
Linux localhost.localdomain 4.11.0 #1 SMP Tue May 2 14:34:09 IST 2017 x86_64 x86_64 x86_64 GNU/Linux 
[[email protected] ldd]# 
#NOW,BUILD as external module 
[[email protected] ldd]# make -C /root/linux-4.11/ M=$(pwd) modules 
make: Entering directory '/root/linux-4.11' 

    WARNING: Symbol version dump ./Module.symvers 
      is missing; modules will have no dependencies and modversions. 

    Building modules, stage 2. 
    MODPOST 1 modules 
make: Leaving directory '/root/linux-4.11' 
[[email protected] ldd]# insmod char 
char_driver/ char.ko  char.mod.o char.o  
[[email protected] ldd]# insmod char.ko 
insmod: ERROR: could not insert module char.ko: File exists 
[[email protected] ldd]# rmmod char 
[[email protected] ldd]# insmod char.ko 
[[email protected] ldd]# journalctl -n 10 
-- Logs begin at Tue 2017-05-02 11:28:36 IST, end at Fri 2017-05-05 12:14:01 IST. -- 
May 05 12:12:11 localhost.localdomain systemd[1]: Started Network Manager Script Dispatcher Service. 
May 05 12:12:11 localhost.localdomain nm-dispatcher[1356]: req:1 'dhcp4-change' [ens3]: new request (4 scripts) 
May 05 12:12:11 localhost.localdomain nm-dispatcher[1356]: req:1 'dhcp4-change' [ens3]: start running ordered scripts... 
May 05 12:12:11 localhost.localdomain dhclient[564]: bound to xxx.xxx.xxx.xx-- renewal in 1401 seconds. 
May 05 12:12:21 localhost.localdomain audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=NetworkManager-dispatcher comm="syst 
May 05 12:14:01 localhost.localdomain anacron[1345]: Job `cron.daily' started 
May 05 12:14:01 localhost.localdomain run-parts[1377]: (/etc/cron.daily) starting logrotate 
May 05 12:14:01 localhost.localdomain run-parts[1382]: (/etc/cron.daily) finished logrotate 
May 05 12:14:01 localhost.localdomain anacron[1345]: Job `cron.daily' terminated 
May 05 12:14:01 localhost.localdomain anacron[1345]: Normal exit (1 job run) 
[[email protected] ldd]# uname -a;cat /etc/redhat-release ;cat Makefile 
Linux localhost.localdomain 4.11.0 #1 SMP Tue May 2 14:34:09 IST 2017 x86_64 x86_64 x86_64 GNU/Linux 
Fedora release 26 (Twenty Six) 
obj-m := char.o 

[[email protected] ldd]# make -C /lib/modules 
modules/  modules-load.d/ 
[[email protected] ldd]# make -C /lib/modules/4.11.0 
4.11.0/       4.11.0-0.rc3.git0.2.fc26.x86_64/ 
[[email protected] ldd]# make -C /lib/modules/4.11.0/ 
build/ kernel/ source/ 
#Now, Build against running kernel 
[[email protected] ldd]# make -C /lib/modules/4.11.0/build/ M=$(pwd) modules 
make: Entering directory '/usr/src/linux-4.11' 
    CC [M] /root/ldd/char.o 
    Building modules, stage 2. 
    MODPOST 1 modules 
    CC  /root/ldd/char.mod.o 
    LD [M] /root/ldd/char.ko 
make: Leaving directory '/usr/src/linux-4.11' 
[[email protected] ldd]# rmmod char 
[[email protected] ldd]# insmod char.ko 
[[email protected] ldd]# journalctl -n 10 
-- Logs begin at Tue 2017-05-02 11:28:36 IST, end at Fri 2017-05-05 12:33:04 IST. -- 
May 05 12:12:11 localhost.localdomain nm-dispatcher[1356]: req:1 'dhcp4-change' [ens3]: new request (4 scripts) 
May 05 12:12:11 localhost.localdomain nm-dispatcher[1356]: req:1 'dhcp4-change' [ens3]: start running ordered scripts... 
May 05 12:12:11 localhost.localdomain dhclient[564]: bound to xxx.xxx.xxx.xx-- renewal in 1401 seconds. 
May 05 12:12:21 localhost.localdomain audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=NetworkManager-dispatcher comm="syst 
May 05 12:14:01 localhost.localdomain anacron[1345]: Job `cron.daily' started 
May 05 12:14:01 localhost.localdomain run-parts[1377]: (/etc/cron.daily) starting logrotate 
May 05 12:14:01 localhost.localdomain run-parts[1382]: (/etc/cron.daily) finished logrotate 
May 05 12:14:01 localhost.localdomain anacron[1345]: Job `cron.daily' terminated 
May 05 12:14:01 localhost.localdomain anacron[1345]: Normal exit (1 job run) 
May 05 12:33:04 localhost.localdomain kernel: char device registered 
[[email protected] ldd]# ls -la /dev/mychar 
crw------- 1 root root 244, 0 May 5 12:33 /dev/mychar 
[[email protected] ldd]# echo "" > /dev/mychar 
[[email protected] ldd]# cat /dev/mychar 
[[email protected] ldd]# rmmod char 
[[email protected] ldd]# journalctl -n 10 
-- Logs begin at Tue 2017-05-02 11:28:36 IST, end at Fri 2017-05-05 12:33:57 IST. -- 
May 05 12:14:01 localhost.localdomain anacron[1345]: Job `cron.daily' terminated 
May 05 12:14:01 localhost.localdomain anacron[1345]: Normal exit (1 job run) 
May 05 12:33:04 localhost.localdomain kernel: char device registered 
May 05 12:33:40 localhost.localdomain kernel: Driver: open() 
May 05 12:33:40 localhost.localdomain kernel: Driver: write() 
May 05 12:33:40 localhost.localdomain kernel: Driver: close() 
May 05 12:33:51 localhost.localdomain kernel: Driver: open() 
May 05 12:33:51 localhost.localdomain kernel: Driver: read() 
May 05 12:33:51 localhost.localdomain kernel: Driver: close() 
May 05 12:33:57 localhost.localdomain kernel: Unloaded 

您还可以看到下面可用上述日志和输出屏幕截图细节(点击链接,如果你不满足于文本信息):

Build against external module (not working,don't know why and Kernel & OS Details and Makefile

Build against running kernel (working , don't know why)

+0

构建命令,日志等应该*在问题文章* **中作为文本**,而不是链接为图像。请编辑帖子并修复这些问题。 – Tsyvarev

+2

您收到关于缺少Module.symvers的警告。这就是允许你有时*加载针对不同内核构建的模块。我认为你正在构建的内核不是内置的,或者它已禁用CONFIG_MODVERSIONS(请参阅该选项的帮助文本)。 – fernan

+0

@Tsyvarev以文本格式更新并添加了所有信息,但如果有人不理解文本格式,那么对于这种情况,我还保留截图格式。 –

有关缺少Module.symvers的警告表明您正在构建的内核缺少CONFIG_MODVERSIONS选项。您需要启用此选项才能够有时针对不同内核构建的加载模块。如果您正在构建的内核源代码没有完全编译并且该文件尚未生成,那么问题也会发生。