目錄
一、register_chrdev
二、解決方法
2.1?alloc_chrdev_region函數(shù):注冊一系列字符設(shè)備編號
2.2?cdev_init函數(shù):初始化cdev結(jié)構(gòu)體?
2.3??cdev_add函數(shù):將字符設(shè)備添加到系統(tǒng)中
?三、驅(qū)動程序
一、register_chrdev
major = register_chrdev(0, "100ask_hello", &hello_drv);
【IMX6ULL驅(qū)動開發(fā)學(xué)習(xí)】01.編寫第一個hello驅(qū)動+自動創(chuàng)建設(shè)備節(jié)點(不涉及硬件操作)_阿龍還在寫代碼的博客-CSDN博客
在之前的hello驅(qū)動程序中,入口函數(shù)會用?register_chrdev來注冊字符設(shè)備驅(qū)動程序,好處是方便快捷,缺點是霸占了主設(shè)備號下的所有此設(shè)備號。當我們手動創(chuàng)建一個設(shè)備節(jié)點(主設(shè)備號相同),因為有多個次設(shè)備號,所以用上面的設(shè)備節(jié)點也可以訪問hello驅(qū)動程序。
Linux內(nèi)核提供的主設(shè)備號是有限的,如果設(shè)備很多的情況下主設(shè)備號就可能不夠用了,那怎么辦呢?
解決辦法:可以在注冊驅(qū)動設(shè)備的時候,給設(shè)備分配好固定的次設(shè)備號。
二、解決方法
先定義兩個靜態(tài)全局變量
static struct cdev hello_cdev;
static dev_t dev;
2.1?alloc_chrdev_region函數(shù):注冊一系列字符設(shè)備編號
int ret;
// major = register_chrdev(0, "100ask_hello", &hello_drv);
ret = alloc_chrdev_region(&dev, 0, 2, "hello"); // dev/hello c 245 0
if (ret < 0) {
printk(KERN_ERR "alloc_chrdev_region() failed for hello\n");
return -EINVAL;
}
-
register_chrdev 該函數(shù)會把主設(shè)備號下所有次設(shè)備號都霸占了
-
dev為輸出變量,這個結(jié)構(gòu)體里會含有設(shè)備的主次設(shè)備號
-
0為次設(shè)備號,2為想獲得幾個次設(shè)備號,hello為名字
-
如果自己創(chuàng)建設(shè)備節(jié)點 mknod /dev/xyz c 245(具體數(shù)字看對應(yīng)的主設(shè)備號) 1
-
因為有兩個次設(shè)備號,所以用上面的設(shè)備節(jié)點也可以訪問驅(qū)動程序
2.2?cdev_init函數(shù):初始化cdev結(jié)構(gòu)體?
cdev_init(&hello_cdev, &hello_drv);
-
初始化hello_cdev,讓hello_cdev與hello_drv結(jié)構(gòu)體掛鉤
2.3??cdev_add函數(shù):將字符設(shè)備添加到系統(tǒng)中
ret = cdev_add(&hello_cdev, dev, 2);
if (ret)
{
printk(KERN_ERR "cdev_add() failed for hello\n");
return -EINVAL;
}
-
添加hello_cdev 2為此設(shè)備號個數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-634915.html
?三、驅(qū)動程序
hello_drv.c文章來源地址http://www.zghlxwxcb.cn/news/detail-634915.html
#include "asm-generic/errno-base.h"
#include "asm/cacheflush.h"
#include "linux/cdev.h"
#include "linux/fs.h"
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/backing-dev.h>
#include <linux/shmem_fs.h>
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/uio.h>
#include <linux/uaccess.h>
static struct class *hello_class;
static struct cdev hello_cdev;
static dev_t dev;
static unsigned char hello_buf[100];
static int hello_open (struct inode *node, struct file *filp)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
static ssize_t hello_read (struct file *filp, char __user *buf, size_t size, loff_t *offset)
{
unsigned long len = size > 100 ? 100 : size;
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
copy_to_user(buf, hello_buf, len);
return len;
}
static ssize_t hello_write(struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{
unsigned long len = size > 100 ? 100 : size;
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
copy_from_user(hello_buf, buf, len);
return len;
}
static int hello_release (struct inode *node, struct file *filp)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
/* 1. create file_operations */
static const struct file_operations hello_drv = {
.owner = THIS_MODULE,
.read = hello_read,
.write = hello_write,
.open = hello_open,
.release = hello_release,
};
/* 2. register_chrdev */
/* 3. entry function */
static int hello_init(void)
{
int ret;
//申請主次設(shè)備號的空間 主次設(shè)備號放在dev結(jié)構(gòu)體中
//dev為輸出變量,這個結(jié)構(gòu)體里會含有設(shè)備的主次設(shè)備號
//0為次設(shè)備號,2為想獲得幾個次設(shè)備號,hello為名字
ret = alloc_chrdev_region(&dev, 0, 2, "hello");// dev/hello c 245 0
if (ret < 0) {
printk(KERN_ERR "alloc_chrdev_region() failed for hello\n");
return -EINVAL;
}
//初始化hello_cdev,讓hello_cdev與hello_drv結(jié)構(gòu)體掛鉤
cdev_init(&hello_cdev, &hello_drv);
//添加hello_cdev 2為此設(shè)備號個數(shù)
ret = cdev_add(&hello_cdev, dev, 2);
if (ret)
{
printk(KERN_ERR "cdev_add() failed for hello\n");
return -EINVAL;
}
hello_class = class_create(THIS_MODULE, "hello_class");
if (IS_ERR(hello_class)) {
printk("failed to allocate class\n");
return PTR_ERR(hello_class);
}
device_create(hello_class, NULL, dev, NULL, "hello"); /* /dev/hello */
return 0;
}
/* 4. exit function */
static void hello_exit(void)
{
device_destroy(hello_class, dev);
class_destroy(hello_class);
//unregister_chrdev(major, "100ask_hello");
cdev_del(&hello_cdev);
unregister_chrdev_region(dev, 2);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
到了這里,關(guān)于【IMX6ULL驅(qū)動開發(fā)學(xué)習(xí)】02.hello驅(qū)動程序之cdev注冊字符設(shè)備驅(qū)動程序和設(shè)置次設(shè)備號的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!