linux 设备节点 驱动,【Linux驱动】自动创建设备节点
開始學習驅動的時候,是將驅動程序編譯成模塊然后用mknod命令手動建立設備節點以提供給應用程序調用。這對于剛開始調試驅動程序的時候常用的一種方法。但是,當有種需要必須在系統啟動的時候就將驅動程序就緒,來供應用層程序調用。這時就不能再手動的建立設備節點了,而必須自動的創建設備節點(不需要人為的操作)。
★注冊類
注冊類的目的是為了使mdev可以在/dev/目錄下建立設備節點。
首先要定義一個類,利用struct class結構體。這個結構體定義在頭文件include/linux/device.h中
struct class {
const char* name;
struct module* owner;
struct subsystemsubsys;
struct list_headchildren;
struct list_headdevices;
struct list_headinterfaces;
struct semaphoresem;/* locks both the children and interfaces lists */
struct kobject*virtual_dir;
struct class_attribute* class_attrs;
struct class_device_attribute* class_dev_attrs;
struct device_attribute* dev_attrs;
int(*uevent)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
int(*dev_uevent)(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size);
void(*release)(struct class_device *dev);
void(*class_release)(struct class *class);
void(*dev_release)(struct device *dev);
int(*suspend)(struct device *, pm_message_t state);
int(*resume)(struct device *);
}
然后使用
完成對類的注冊。其中第一個參數一般為:THIS_MODULE。第二個參數為:設備節點的名稱
舉個例子:
★創建設備節點
創建設備節點的函數:
struct device *device_create(struct class *class, struct device *parent,dev_t devt, const char *fmt, ...){
va_list args;
struct device *dev = NULL;
int retval = -ENODEV;
if (class == NULL || IS_ERR(class))
goto error;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
retval = -ENOMEM;
goto error;
}
dev->devt = devt;
dev->class = class;
dev->parent = parent;
dev->release = device_create_release;
va_start(args, fmt);
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
va_end(args);
retval = device_register(dev);
if (retval)
goto error;
return dev;
error:
kfree(dev);
return ERR_PTR(retval);
}
該函數的四個參數從左到右以此為:創建設備節點所屬的類、該設備的父節點(若果沒有就指定為NULL)、設備號、設備名稱、次設備號。
★銷毀類和設備節點
注意不要忘記了還要銷毀類和銷毀設備節點。
銷毀類:參數為用struct class結構體定義的變量
void class_destroy(struct class *cls)
{
if ((cls == NULL) || (IS_ERR(cls)))
return;
class_unregister(cls);
}銷毀設備節點:
void device_destroy(struct class *class, dev_t devt)
{
struct device *dev = NULL;
struct device *dev_tmp;
down(&class->sem);
list_for_each_entry(dev_tmp, &class->devices, node) {
if (dev_tmp->devt == devt) {
dev = dev_tmp;
break;
}
}
up(&class->sem);
if (dev)
device_unregister(dev);
}
★例子(自己寫的延時驅動)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define NAME"ralink_drive_delay"
#define RALINK_GPIO_DEVNAME "my_delay"
#define delay_us 0 //most least is 10 US
#define delay_ms 1 //Ms
int delay_MAJOR = 109;
MODULE_LICENSE("Dual BSD/GPL");
static long Ralink_delay_ioctl(struct inode * inode, struct file * file, unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
case delay_us:
udelay(10 * arg);
return 0;
case delay_ms:
udelay(1000);
return 0;
default:
return -1;
}
}
static struct file_operations My_delay_fops =
{
.owner = THIS_MODULE,
.ioctl = Ralink_delay_ioctl,
};
static struct class *delay_class;
static int __init my_delay_init(void)
{
int ret = 0;
ret = register_chrdev(delay_MAJOR, RALINK_GPIO_DEVNAME,&My_delay_fops);
if(ret < 0)
{
printk("unable to register character device\n");
return ret;
}
if (delay_MAJOR == 0)
{
delay_MAJOR = ret;
printk(KERN_DEBUG NAME ": got dynamic major %d\n", ret);
}
//注冊一個類,使mdev可以在"/dev/目錄下建立設備節點"
delay_class = class_create(THIS_MODULE, RALINK_GPIO_DEVNAME);
if(IS_ERR(delay_class))
{
printk("failed in My_led class.\n");
return -1;
}
device_create(delay_class, NULL, MKDEV(delay_MAJOR, 0),RALINK_GPIO_DEVNAME 0);//
//第一個參數是所要創建的設備所從屬的類
//第二個參數是這個設備的父節點,沒有指定就是NULL
//第三個參數是設備號
//第四個參數是設備名稱
//第五個參數是從設備號
printk("my_delay driver initialized\n");
return 0;
}
void __exit my_delay_exit(void)
{
unregister_chrdev(delay_MAJOR,RALINK_GPIO_DEVNAME);
device_destroy(delay_class,MKDEV(delay_MAJOR,0));//注銷設備節點
class_destroy(delay_class);//銷毀類
printk("my_delay driver exited\n");
}
module_init(my_delay_init);
module_exit(my_delay_exit);
原文:http://blog.csdn.net/xgsilence/article/details/35650849
總結
以上是生活随笔為你收集整理的linux 设备节点 驱动,【Linux驱动】自动创建设备节点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 记事本程序,Linux记事本
- 下一篇: linux彻底卸载multipath,深