Я пишу этот базовый 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