日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 设备节点 驱动,【Linux驱动】自动创建设备节点

發(fā)布時間:2024/1/23 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 设备节点 驱动,【Linux驱动】自动创建设备节点 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

開始學(xué)習(xí)驅(qū)動的時候,是將驅(qū)動程序編譯成模塊然后用mknod命令手動建立設(shè)備節(jié)點以提供給應(yīng)用程序調(diào)用。這對于剛開始調(diào)試驅(qū)動程序的時候常用的一種方法。但是,當(dāng)有種需要必須在系統(tǒng)啟動的時候就將驅(qū)動程序就緒,來供應(yīng)用層程序調(diào)用。這時就不能再手動的建立設(shè)備節(jié)點了,而必須自動的創(chuàng)建設(shè)備節(jié)點(不需要人為的操作)。

★注冊類

注冊類的目的是為了使mdev可以在/dev/目錄下建立設(shè)備節(jié)點。

首先要定義一個類,利用struct class結(jié)構(gòu)體。這個結(jié)構(gòu)體定義在頭文件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 *);

}

然后使用

完成對類的注冊。其中第一個參數(shù)一般為:THIS_MODULE。第二個參數(shù)為:設(shè)備節(jié)點的名稱

舉個例子:

★創(chuàng)建設(shè)備節(jié)點

創(chuàng)建設(shè)備節(jié)點的函數(shù):

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);

}

該函數(shù)的四個參數(shù)從左到右以此為:創(chuàng)建設(shè)備節(jié)點所屬的類、該設(shè)備的父節(jié)點(若果沒有就指定為NULL)、設(shè)備號、設(shè)備名稱、次設(shè)備號。

★銷毀類和設(shè)備節(jié)點

注意不要忘記了還要銷毀類和銷毀設(shè)備節(jié)點。

銷毀類:參數(shù)為用struct class結(jié)構(gòu)體定義的變量

void class_destroy(struct class *cls)

{

if ((cls == NULL) || (IS_ERR(cls)))

return;

class_unregister(cls);

}銷毀設(shè)備節(jié)點:

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);

}

★例子(自己寫的延時驅(qū)動)

#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/目錄下建立設(shè)備節(jié)點"

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);//

//第一個參數(shù)是所要創(chuàng)建的設(shè)備所從屬的類

//第二個參數(shù)是這個設(shè)備的父節(jié)點,沒有指定就是NULL

//第三個參數(shù)是設(shè)備號

//第四個參數(shù)是設(shè)備名稱

//第五個參數(shù)是從設(shè)備號

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));//注銷設(shè)備節(jié)點

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

總結(jié)

以上是生活随笔為你收集整理的linux 设备节点 驱动,【Linux驱动】自动创建设备节点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。