Команда insmod висит в Linux ядре - PullRequest
1 голос
/ 28 февраля 2020

Я пишу этот базовый c символьный драйвер, в котором будут сгенерированы и уничтожены двухсимвольные устройства при необходимости. Сборки для этого драйвера идут нормально, но при загрузке его в ядро ​​команда sudo insmod driver зависает и не возвращается. Кроме того, я наблюдал это однажды:

$ sudo insmod char_driver.ko 
  Killed

Кроме того, я затрудняюсь освободить 2 устройства по одному с одним старшим номером.

Код выглядит следующим образом:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/device.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/uaccess.h>
#include<linux/err.h> 

#define DEV_NAME "MyCdev"
#define MAX_DEVICES 2
#define MAX_DATA_SIZE 256

/*Data Buffers to Interact with Userspace*/
struct Data_Buffer{
    char message[MAX_DATA_SIZE];
    short int msg_size;
};

/*Common Driver Global variables*/
struct MyCdev_common{

    dev_t Major;                            // To be received by Allocating major no.
    int major_num;                          // Major no.
    int numOpen;                            // No of times device is opened.
    struct device *device[2];               // Generated devices
    struct file_operations fops;            // File operations.
    struct class *dev_class;                // Class of devices to be created.
    struct cdev devices[MAX_DEVICES];       // 
};


/*Varibles for Critical data strutures*/
static struct Data_Buffer buffer;
static struct MyCdev_common Global;


*Function definitions*/

void cleanup_fun(char num)
{
    if( num == 1 ){
        class_unregister(Global.dev_class);
        class_destroy(Global.dev_class);
    }
    unregister_chrdev_region(Global.Major,2);
}

static int  char_driver_init(void)
{
    int err_code, i;

     /*File operations are filled as usual with Dummy functions*/

   /*Step 1: Allocate Major no. fro two devices*/

     err_code = alloc_chrdev_region( &(Global.Major), 0, 2, DEV_NAME);
     if( err_code < 0 ){
             printk(KERN_ALERT"%s: Failed to Allocate Major number. Exiting\n",DEV_NAME);
             return err_code;
     }

     Global.major_num = MAJOR(Global.Major);
     pr_alert("%s: %d Major no. registered\n",DEV_NAME,  Global.major_num);

   /*Step 2: Create sysfs class*/

     Global.dev_class = class_create(THIS_MODULE, DEV_NAME);
     if( IS_ERR(Global.dev_class) )
     {
             cleanup_fun(0);
             printk(KERN_ALERT"%s: Failed to register device class\n",DEV_NAME);
             return PTR_ERR(Global.dev_class);
     }

     pr_alert("%s: class created successfully registered\n",DEV_NAME);

     for( i=0; i<MAX_DEVICES; i++)
     {
         /*Step 3: Allocate & Initialise Character device structure*/

         cdev_init(&Global.devices[i], &Global.fops);
         Global.devices[i].owner = THIS_MODULE;

       /*Step 4: Create Device Class and Initialise the device*/

         Global.device[i] = device_create(Global.dev_class, NULL/*Parent*/,MKDEV(Global.major_num, i), "MyCdev-%d",i);
         if( IS_ERR( Global.device[i] ) ){

             if( i == 1 ){   //If one device is registered successfully, exit the loop.

                 cdev_del(&Global.devices[i] );
                 printk(KERN_ALERT"%s: Failed to create a device %d. Continuing with device 0\n",DEV_NAME, i);
                 err_code = 0xFFFF;
                 goto End;
             }

             cdev_del(&Global.devices[i] );
             cleanup_fun(1);
             printk(KERN_ALERT"%s: Failed to create a device %d\n",DEV_NAME, i);
             return PTR_ERR(Global.device[i]);
         }

         pr_alert("%s: Device %d created successfully\n",DEV_NAME,i);

       /*Step 5: Add the character device to kernel*/
         err_code = cdev_add(&Global.devices[i], MKDEV(Global.major_num, i), 1);
         if(err_code < 0 ){
             device_destroy(Global.dev_class, MKDEV(Global.major_num, i));
             if(i == 1){ //if One device got registered, we can work with one, so exit.
                 cdev_del(&Global.devices[i] );
                 printk(KERN_ALERT"%s: Failed to create a device %d. Continuing with device 0\n",DEV_NAME, i);
                 err_code = 0xFFFF;      //Flag to Indicate that one device has failed.
                 goto End;
             }

             cdev_del( &Global.devices[i] );
             cleanup_fun(1);
             printk(KERN_ALERT"%s: Failed to Add driver to kernel\n",DEV_NAME);
             return err_code;

         }

         pr_alert("%s: Device %d added successfully\n",DEV_NAME,i);

 End:
         if(err_code == 0xFFFF )
             printk(KERN_ALERT"%s-%d:Device 0 Registered with major number %d\n",DEV_NAME,0 ,Global.major_num);
         else
             printk(KERN_ALERT"%s:Devices Registered with major number %d\n",DEV_NAME ,Global.major_num);
        return 0;

 }

 void char_driver_exit(void)
 {

     int i=0;
     for(i=0;i<MAX_DEVICES;i++)   {
         device_destroy(Global.dev_class, MKDEV(Global.major_num, i) );
         cdev_del(&Global.devices[i] );
     }

     pr_alert("%s: devices destroyed!!!\n",DEV_NAME);

     class_unregister(Global.dev_class);
     class_destroy(Global.dev_class);
     pr_alert("%s: class destroyed!!!\n",DEV_NAME);

     unregister_chrdev_region(Global.Major,2);
     pr_alert("%s: Driver removed successfully\n",DEV_NAME);
 }

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("First character driver");

module_init(char_driver_init);
module_exit(char_driver_exit);

Утилита modprobe возвращает следующее:

$ sudo modprobe char_driver.ko
  modprobe: FATAL: Module char_driver.ko not found in directory 
  /lib/modules/4.15.0-88-generic
...