使用linux2.6版本方式創建字符設備,自動生成設備節點,靜態申請設備號,中間使用cdev_alloc函式動態分配核心結構體struct cdev,最后能夠成功創建字符設備,也能夠使用函式指標集中指定的函式,能夠使用rmmod指令卸載模塊,但是卸載后再次使用insmod指令加載模塊,就會出現問題。我在__exit函式中按照從后往前的順序釋放了設備號,注銷等操作。不知道為啥將kfree函式屏蔽就正常了。如果需要,我可以把代碼和現象貼出來的,底層模塊代碼:
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/fs.h"
#include "linux/cdev.h"
#include "linux/device.h"
#include "linux/slab.h"
#define CDEV_CREAT_NAME "cdev_my_name_dynamic"
#define CLASS_CREAT_NAME "class_my_name_dynamic"
#define DEV_NAME_IN_ROOT_DEV "linux_26_dynamic_"
typedef struct __CHDEV {
dev_t char_dev;
unsigned major;
unsigned baseminor;
unsigned count;
char *name;
}__CHDEV_TypeDef;
__CHDEV_TypeDef chdev = {
.char_dev = 0,
.major = 250, //默認250
.baseminor = 8, //次設備號開始值
.count = 3,
.name = CDEV_CREAT_NAME,
};
struct cdev *p_chrdev = NULL;
int my_chrdev_open(struct inode *, struct file *);
int my_chrdev_close(struct inode *, struct file *);
struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_chrdev_open,
.release = my_chrdev_close,
};
struct class *p_class = NULL;
static int __init my_cdev_init(void)
{
int i = 0;
/*合成完整設備號*/
chdev.char_dev = MKDEV(chdev.major,chdev.baseminor);
/*申請設備號--靜態*/
if(register_chrdev_region(chdev.char_dev,chdev.count,chdev.name) != 0) {
printk("靜態申請設備號失敗!\n");
goto register_chr_err;
}
printk("靜態申請設備號成功!\n");
/*核心結構體初始化--動態分配*/
p_chrdev = cdev_alloc();
if(p_chrdev == NULL) {
printk("核心結構體初始化失敗!\n");
goto cdev_alloc_err;
}
printk("核心結構體初始化成功!\n");
p_chrdev->ops = &fops;
p_chrdev->owner = THIS_MODULE;
/*注冊設備*/
if(cdev_add(p_chrdev,chdev.char_dev,chdev.count) < 0) {
printk("注冊設備失敗!\n");
goto cdev_add_err;
}
printk("注冊設備成功!\n");
/*創建設備類*/
p_class = class_create(THIS_MODULE,CLASS_CREAT_NAME);
if(p_class < (struct class *)0) {
printk("創建設備類失敗!\n");
goto class_create_err;
}
printk("創建設備類成功!\n");
/*創建設備節點*/
for(i=MINOR(chdev.char_dev);i<chdev.count+chdev.baseminor;i++) {
if(device_create(p_class,NULL,MKDEV(chdev.major,i),NULL,"%s%d",DEV_NAME_IN_ROOT_DEV,i) < (struct device *)0) {
printk("創建設備節點失敗!\n");
goto dev_create_err;
}
else {
printk("創建設備節點%s%d成功!\n",DEV_NAME_IN_ROOT_DEV,i);
}
}
return 0;
dev_create_err :
for(i--;i>=MINOR(chdev.char_dev);i--) {
device_destroy(p_class,i);
}
class_destroy(p_class);
class_create_err :
cdev_del(p_chrdev);
cdev_add_err :
kfree(p_chrdev);
cdev_alloc_err :
unregister_chrdev_region(chdev.char_dev,chdev.count);
register_chr_err :
return -ENOMEM;
}
static void __exit my_cdev_exit(void)
{
int i = 0;
for(i=MINOR(chdev.char_dev);i<chdev.count+chdev.baseminor;i++) {
device_destroy(p_class,MKDEV(chdev.major,i));
printk("銷毀設備節點%s%d成功!\n",DEV_NAME_IN_ROOT_DEV,i);
}
class_destroy(p_class);
printk("銷毀%s類成功!\n",CLASS_CREAT_NAME);
cdev_del(p_chrdev);
printk("設備注銷成功!\n");
unregister_chrdev_region(chdev.char_dev,chdev.count);
printk("設備號釋放成功!\n");
kfree(p_chrdev);
printk("核心結構體釋放成功!\n");
printk("卸載模塊完成!\n");
}
int my_chrdev_open(struct inode *i, struct file *j)
{
printk("%d,%s\n",__LINE__,__FUNCTION__);
return 0;
}
int my_chrdev_close(struct inode *i, struct file *j)
{
printk("%d,%s\n",__LINE__,__FUNCTION__);
return 0;
}
module_init(my_cdev_init);
module_exit(my_cdev_exit);
MODULE_LICENSE("GPL");
上層測驗代碼:
#include<stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc,char *argv[])
{
FILE *fp = fopen(argv[1],"a");
if(fp == NULL)
{
perror("fopen");
return -1;
}
printf("main: open success\n");
sleep(3);
close(fp);
return 0;
}
加載模塊:

上層測驗:

卸載模塊:

重新加載模塊:


uj5u.com熱心網友回復:
找到原因,void unregister_chrdev_region(dev_t from, unsigned count)
{
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
}
在這個函式中包含了kfree函式,因此再次呼叫kfree函式會出現錯誤!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/71024.html
標籤:驅動開發/核心開發
上一篇:u盤一部分變成了DVD驅動器
下一篇:求助!啟天m420裝win7
