为什么在/dev的此程序中未在此处列出次要设备的数量? [英] Why the number of minor devices are not listed here in this program in /dev?

查看:124
本文介绍了为什么在/dev的此程序中未在此处列出次要设备的数量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为我的模块创建一些次要字符驱动程序.我想在/dev/上看到它.但是,我只看到一个驱动程序.我的代码有什么问题?什么是正确的代码?

I want to create the number of minor character drivers for my module. I want to see it at the /dev/ . However, I see only one driver. What is the problem in my code? What should be the right code?

#include <linux/init.h>
#include <linux/module.h> /** needed by all modules **/
#include <linux/kernel.h>  /** This is for KERN_ALERT **/
#include <linux/fs.h> /** for file operations **/
#include <linux/cdev.h>  /** character device **/
#include <linux/device.h>  /** for sys device registration in /dev/ and /sys/class **/
/** for copy_to_user **/
#include <asm/uaccess.h>


/** For class registration to work, you need GPL license **/
MODULE_LICENSE("GPL");


static struct cdev basicCdev;
static struct class *basicDriverClass;

static int  basicMajorNumber = 0;

#define NUMBER_OF_MINOR_DEVICE (5)

/** Prototype for read, this will be invoked when the read function is done on to the driver **/
/** The declaration type is file operations based function pointer - read **/
static ssize_t basicRead(struct file *filp, char *buffer, size_t length,loff_t *offset);

static int basicOspen(struct inode *inode, struct file *file);   

/** File Operations function pointer table **/
/** There are plenty of file operations  **/

static struct file_operations fops = {
  .read = basicRead,
  .write = NULL,
  .open = basicOspen,
  .release = NULL
};

static ssize_t basicRead(struct file *filp, char *buffer, size_t length, loff_t *offset)
{
     char msg[1024] = "Hello SJ_read\0";
     printk(KERN_ALERT "The Read operation called\r\n");
     copy_to_user( buffer, msg, sizeof(msg) );
     return sizeof(msg);
}

static int basicOspen(struct inode *inode, struct file *file)
{

   printk("Kernel.Basic Driver Opened now!!\r\n");

   return 0;
}

static void setup_cdev(struct cdev *dev, int minor, struct file_operations *fops)
{
         int err = -1;
         /** MKDEV call creates a device number i.e. combination of major and minor number **/
         int devno = MKDEV(basicMajorNumber, minor);
         /** Initiliaze character dev with fops **/
         cdev_init(dev, fops);
         /**owner and operations initialized **/
         dev->owner = THIS_MODULE;
         dev->ops = fops;
         /** add the character device to the system**/
         /** Here 1 means only 1 minor number, you can give 2 for 2 minor device, the last param is the count of minor number enrolled **/
         err = cdev_add (dev, devno, 1);

         if (err)
         {
                 printk (KERN_NOTICE "Couldn't add cdev");
         }
 }

static int chrDriverInit(void)
{

    int result;
    dev_t dev; 

    printk("Welcome!! Device Init now..");

    /** int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name);  **/
    /** dev -> The dev_t variable type,which will get the major number that the kernel allocates.  **/
    /**The same name will appear in /proc/devices.  **/

    /** it is registering the character device **/   
    /** a major number will be dynamically allocated here **/
    /**  alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME); **/
    result = alloc_chrdev_region(&dev, 0, NUMBER_OF_MINOR_DEVICE, "pSeudoDrv");

    if( result < 0 )
    {
      printk("Error in allocating device");
      return -1;    
    }

    /** From these two if's we are avoiding the manual mknod command to create the /dev/<driver> **/
    /**  creating class, and then device created removes the dependency of calling mknod  **/
    /** A good method - the mknod way is depreciated **/
    /** mknod way is -  mknod /dev/<driver_name> c <majorNumber> <minorNumber>


    /** add the driver to /sys/class/chardrv **/
    if ((basicDriverClass = class_create(THIS_MODULE, "chardrv")) == NULL)    //$ls /sys/class
    {
        unregister_chrdev_region(dev, 1);
        return -1;
    }

     /** add the driver to /dev/pSeudoDrv -- here **/
    if (device_create(basicDriverClass, NULL, dev, NULL, "pSeudoDrv") == NULL) //$ls /dev/
    {
        class_destroy(basicDriverClass);
        unregister_chrdev_region(dev, 1);
        return -1;
    }

     /** let's see what major number was assigned by the Kernel **/
     basicMajorNumber = MAJOR(dev);
     printk("Kernel assigned major number is %d ..\r\n",basicMajorNumber );

    /** Now setup the cdev **/
    setup_cdev(&basicCdev,NUMBER_OF_MINOR_DEVICE, &fops);

    return 0;   

}


static void chrDriverExit(void)
{
    /** A reverse - destroy mechansim -- the way it was created **/
    printk("Releasing Simple Devs -- %s\r\n",  __FUNCTION__);
    /** delete the character driver added **/
    cdev_del(&basicCdev);
    /** destroy the device created **/
    device_destroy(basicDriverClass, MKDEV(basicMajorNumber, 0));
    /** destroy the class created **/
    class_destroy(basicDriverClass);
    /** unregister the chr dev **/
    unregister_chrdev(basicMajorNumber, NUMBER_OF_MINOR_DEVICE);

}


module_init(chrDriverInit);
module_exit(chrDriverExit);

如果我将init函数修改为以下内容,则会出错.

I get errors, if I modify the init function to the following.

static int chrDriverInit(void)
    {

        int result;
        dev_t dev; 
        dev_t dev2; 

        printk("Welcome!! Device Init now..");

        /** int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name);  **/
        /** dev -> The dev_t variable type,which will get the major number that the kernel allocates.  **/
        /**The same name will appear in /proc/devices.  **/

        /** it is registering the character device **/   
        /** a major number will be dynamically allocated here **/
        /**  alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME); **/
        result = alloc_chrdev_region(&dev, 0, NUMBER_OF_MINOR_DEVICE, "pSeudoDrv");

        if( result < 0 )
        {
          printk("Error in allocating device");
          return -1;    
        }

        /** From these two if's we are avoiding the manual mknod command to create the /dev/<driver> **/
        /**  creating class, and then device created removes the dependency of calling mknod  **/
        /** A good method - the mknod way is depreciated **/
        /** mknod way is -  mknod /dev/<driver_name> c <majorNumber> <minorNumber>


        /** add the driver to /sys/class/chardrv **/
        if ((basicDriverClass = class_create(THIS_MODULE, "chardrv")) == NULL)    //$ls /sys/class
        {
            unregister_chrdev_region(dev, 1);
            return -1;
        }

         /** add the driver to /dev/pSeudoDrv -- here **/
        if (device_create(basicDriverClass, NULL, dev, NULL, "pSeudoDrv") == NULL) //$ls /dev/
        {
            class_destroy(basicDriverClass);
            unregister_chrdev_region(dev, 1);
            return -1;
        }

         /** let's see what major number was assigned by the Kernel **/
         basicMajorNumber = MAJOR(dev);
         printk("Kernel assigned major number is %d ..\r\n",basicMajorNumber );

         dev2 = MKDEV(basicMajorNumber,2);

        #if 1

         if (device_create(basicDriverClass, NULL, dev2, NULL, "pSeudoDrv2") == NULL) //$ls /dev/
        {
            class_destroy(basicDriverClass);
            unregister_chrdev_region(dev, 1);
            return -1;
        }

        #endif


        /** Now setup the cdev **/
        setup_cdev(&basicCdev,NUMBER_OF_MINOR_DEVICE, &fops);







        return 0;   

    }

这是崩溃-

[19554.180535] CPU: 1 PID: 16636 Comm: insmod Tainted: GF       W  O 3.13.5-101.fc19.x86_64 #1
[19554.180537] Hardware name: Dell Inc. Studio 1558/0G939P, BIOS A07 06/24/2010
[19554.180539]  0000000000000009 ffff8800667d7ad8 ffffffff81680664 ffff8800667d7b20
[19554.180543]  ffff8800667d7b10 ffffffff8106d35d ffff880130f9e810 00000000ffffffef
[19554.180547]  0000000000000000 ffff880133432378 0000000000000000 ffff8800667d7b70
[19554.180551] Call Trace:
[19554.180555]  [<ffffffff81680664>] dump_stack+0x45/0x56
[19554.180558]  [<ffffffff8106d35d>] warn_slowpath_common+0x7d/0xa0
[19554.180562]  [<ffffffff8106d3cc>] warn_slowpath_fmt+0x4c/0x50
[19554.180566]  [<ffffffff81315be4>] kobject_add_internal+0x214/0x320
[19554.180570]  [<ffffffff81316115>] kobject_add+0x65/0xb0
[19554.180574]  [<ffffffff81315550>] ? kobject_put+0x30/0x60
[19554.180578]  [<ffffffff814138b5>] device_add+0x125/0x640
[19554.180582]  [<ffffffff81413fe0>] device_create_groups_vargs+0xe0/0x110
[19554.180586]  [<ffffffffa078d0e0>] ? basicRead+0xc0/0xc0 [character_driver]
[19554.180590]  [<ffffffff81414071>] device_create+0x41/0x50
[19554.180595]  [<ffffffffa078d1d3>] chrDriverInit+0xf3/0x160 [character_driver]
[19554.180598]  [<ffffffff8100214a>] do_one_initcall+0xfa/0x1b0
[19554.180602]  [<ffffffff81054803>] ? set_memory_nx+0x43/0x50
[19554.180609]  [<ffffffff810e060d>] load_module+0x1e1d/0x25b0
[19554.180613]  [<ffffffff810dc320>] ? store_uevent+0x40/0x40
[19554.180617]  [<ffffffff810e0f16>] SyS_finit_module+0x86/0xb0
[19554.180622]  [<ffffffff8168f629>] system_call_fastpath+0x16/0x1b
[19554.180624] ---[ end trace dd8ae4ccda100ad8 ]---

推荐答案

您的问题是您只为第一个设备调用device_create(). alloc_chrdev_region()仅分配主要/次要数字,但实际上并未在内核中创建设备结构. alloc_chrdev_region()返回的dev_t代表您的五个主要/次要数字中的第一个.您需要使用for循环,增加次设备号,然后在所有这些设备上调用device_create().

Your problem is that you only call device_create() for the first device. alloc_chrdev_region() only allocate major/minor numbers but it does not actually create the device structures in the kernel. The dev_t returned by alloc_chrdev_region() represents the first of your five major/minor numbers. You need to use a for loop, increment the minor number and then call device_create() on all of them.

别忘了在退出函数中销毁它们.

Don't forget to destroy all of them in the exit function.

这篇关于为什么在/dev的此程序中未在此处列出次要设备的数量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆