简体   繁体   中英

Linux Char device driver not working if build as external module but worked if build as against running kernel.But why?

OS : Fedora 26 Alpha

Kernel : Linux 4.11

Kernel Manually compiled by following commands:

1) make oldconfig

2) make menuconfig

3) make all

4) make module_install

5) make install

After successfully compilation and installation of Latest Kernel , i build some modules but as a external modules via make -C /root/linux-4.11/ M=$(pwd) modules not as against running kernel. All basic modules that i developed compiled and installed and worked as expected , but then i code basic character device driver , but then some strange problem i detected. That is, after successfully compilation and insertion of module via insmod , i didn't get any kernel messages regarding this module and also no char device was generated in /dev/ directory then I also searched regarding this issue but didn't get any better answer for this same issue.

Then , suddenly i tried it to be compiled and build against as running kernel via make -C /lib/modules/$(uname -r)/build/ M=$(pwd) modules then after inserting module , i get my expected result. But now , i want to figure out why this is happening because other simple modules are working fine when build as external module , but then why not this one?

#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);

Compilation & kernel logs & kernel , OS Details (Both as external module and then as against running kernel) :

[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 

You can also see screen-shots available below for above logs and output details (click on link , if you aren't satisfied with textual details ):

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 )

The warning about the missing Module.symvers indicates that the kernel you're building against is missing the CONFIG_MODVERSIONS option. You need to enable this option to be able to sometimes load modules built against a different kernel. The problem can also happen if the kernel source that you're building against is not fully compiled and the file has not been generated yet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM