如果构建为外部模块,则Linux Char设备驱动程序无法工作,但如果构建与运行内核相同,则无法工作。但为什么?

时间:2017-05-04 11:32:43

标签: c linux linux-kernel linux-device-driver

操作系统:Fedora 26 Alpha

内核:Linux 4.11

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

1)make oldconfig

2)make menuconfig

3)全部

4)make module_install

5)make install

成功编译和安装Latest Kernel后, 我构建了一些模块但通过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 <xyz@gmail.com>");
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);

编译&amp;内核日志&amp; kernel,OS Details(作为外部模块,然后是运行内核):

[root@localhost 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
[root@localhost ldd]# 
#NOW,BUILD as external module
[root@localhost 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'
[root@localhost ldd]# insmod char
char_driver/ char.ko      char.mod.o   char.o       
[root@localhost ldd]# insmod char.ko
insmod: ERROR: could not insert module char.ko: File exists
[root@localhost ldd]# rmmod char 
[root@localhost ldd]# insmod char.ko
[root@localhost 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)
[root@localhost 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

[root@localhost ldd]# make -C /lib/modules
modules/        modules-load.d/ 
[root@localhost ldd]# make -C /lib/modules/4.11.0
4.11.0/                          4.11.0-0.rc3.git0.2.fc26.x86_64/ 
[root@localhost ldd]# make -C /lib/modules/4.11.0/
build/  kernel/ source/ 
#Now, Build against running kernel
[root@localhost 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'
[root@localhost ldd]# rmmod char 
[root@localhost ldd]# insmod char.ko
[root@localhost 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
[root@localhost ldd]# ls -la /dev/mychar
crw------- 1 root root 244, 0 May  5 12:33 /dev/mychar
[root@localhost ldd]# echo "" > /dev/mychar
[root@localhost ldd]# cat /dev/mychar 
[root@localhost ldd]# rmmod char 
[root@localhost 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 )

1 个答案:

答案 0 :(得分:0)

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