Class create, device create, device create file (转)
来自:http://www.hovercool.com/en/Class_create,_device_create,_device_create_file
开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点(包括ldd3中不少例子也是这样),实际上现在Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录下创建相应设备节点,并在卸载模块时删除该节点。
内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建 好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
此外,利用device_create_file函数可以在/sys/class/下创建对应的属性文件,从而通过对该文件的读写实现特定的数据操作。
一、class_create
官方说明:
/* This is a #define to keep the compiler from merging different
* instances of the __key variable */
#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \
__class_create(owner, name, &__key); \
}) /**
* class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class
* @name: pointer to a string for the name of this class.
* @key: the lock_class_key for this class; used by mutex lock debugging
*
* This is used to create a struct class pointer that can then be used
* in calls to device_create().
*
* Returns &struct class pointer on success, or ERR_PTR() on error.
*
* Note, the pointer created here is to be destroyed when finished by
* making a call to class_destroy().
*/
struct class *__class_create(struct module *owner, const char *name,
struct lock_class_key *key)
关键的一句是:
* This is used to create a struct class pointer that can then be used
* in calls to device_create().
-->这个函数用来创建一个struct class的结构体指针,这个指针可用作device_create()函数的参数。
也就是说,这个函数主要是在调用device_create()前使用,创建一个struct class类型的变量,并返回其指针。
二、device_create
官方说明:
/**
* device_create - creates a device and registers it with sysfs
* @class: pointer to the struct class that this device should be registered to
* @parent: pointer to the parent struct device of this new device, if any
* @devt: the dev_t for the char device to be added
* @drvdata: the data to be added to the device for callbacks
* @fmt: string for the device's name
*
* This function can be used by char device classes. A struct device
* will be created in sysfs, registered to the specified class.
*
* A "dev" file will be created, showing the dev_t for the device, if
* the dev_t is not 0,0.
* If a pointer to a parent struct device is passed in, the newly created
* struct device will be a child of that device in sysfs.
* The pointer to the struct device will be returned from the call.
* Any further sysfs files that might be required can be created using this
* pointer.
*
* Returns &struct device pointer on success, or ERR_PTR() on error.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct device *device_create(struct class *class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt, ...)
首先解释一下"sysfs":sysfs是linux2.6所提供的一种虚拟档案系统;在设备模型中,sysfs文件系统用来表示设备的结构,将设 备的层次结构形象的反应到用户空间中,从而可以通过修改sysfs中的文件属性来修改设备的属性值;sysfs被挂载到根目录下的"/sys"文件夹下。
三、device_create_file
官方说明:
/**
* device_create_file - create sysfs attribute file for device.
* @dev: device.
* @attr: device attribute descriptor.
*/
int device_create_file(struct device *dev,
const struct device_attribute *attr)
使用这个函数时要引用 device_create所返回的device*指针,作用是在/sys/class/下创建一个属性文件,从而通过对这个属性文件进行读写就能完成对应的数据操作。
如:
a.在驱动程序中使用 device_create_file创建属性文件
static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store); /*读取寄存器val的值到缓冲区buf中,内部使用*/
static ssize_t __hello_get_val(struct xxx_dev* dev, char* buf) {
int val = 0; /*同步访问*/
if(down_interruptible(&(dev->sem))) {
return -ERESTARTSYS;
} val = dev->val;
up(&(dev->sem)); return snprintf(buf, PAGE_SIZE, "%d/n", val);
} /*把缓冲区buf的值写到设备寄存器val中去,内部使用*/
static ssize_t __hello_set_val(struct xxx_dev* dev, const char* buf, size_t count) {
int val = 0; /*将字符串转换成数字*/
val = simple_strtol(buf, NULL, 10); /*同步访问*/
if(down_interruptible(&(dev->sem))) {
return -ERESTARTSYS;
} dev->val = val;
up(&(dev->sem)); return count;
} /*读取设备属性val*/
static ssize_t hello_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
struct xxx_dev* hdev = (struct xxx_dev*)dev_get_drvdata(dev); return __hello_get_val(hdev, buf);
} /*写设备属性val*/
static ssize_t hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {
struct xxx_dev* hdev = (struct xxx_dev*)dev_get_drvdata(dev); return __hello_set_val(hdev, buf, count);
} /*模块加载方法*/
static int __init xxx_init(void){
... /*在/sys/class/xxx/xxx目录下创建属性文件val*/
err = device_create_file(temp, &dev_attr_val);
if(err < 0) {
printk(KERN_ALERT"Failed to create attribute val.");
goto destroy_device;
} ...
}
b.在用户空间读取属性
...
read(dev->fd, val, sizeof(*val));
...
write(dev->fd, &val, sizeof(val));
...
四、使用示例
/*在/sys/class/目录下创建设备类别目录xxx*/
g_vircdev_class = class_create(THIS_MODULE, VIRCDEV_CLASS_NAME);
if(IS_ERR(g_vircdev_class)) {
err = PTR_ERR(g_vircdev_class);
printk(KERN_ALERT "Failed to create class.\n");
goto CLASS_CREATE_ERR;
} /*在/dev/目录和/sys/class/xxx目录下分别创建设备文件xxx*/
dev = device_create(g_vircdev_class, NULL, devt, NULL, VIRCDEV_DEVICE_NAME);
if(IS_ERR(dev)) {
err = PTR_ERR(dev);
printk(KERN_ALERT "Failed to create device.\n");
goto DEVICE_CREATE_ERR;
} /*在/sys/class/xxx/xxx目录下创建属性文件val*/
err = device_create_file(dev, attr);
if(err < 0) {
printk(KERN_ALERT"Failed to create attribute file.");
goto DEVICE_CREATE_FILE_ERR;
}
参考资料:
sysfs:
http://blog.csdn.net/dianhuiren/article/details/6928500
Class create, device create, device create file (转)的更多相关文章
- Apache: No space left on device: Couldn’t create rewrite_map(XXXX)
启动apache的时候 有时候会遇到这样的错误:No space left on device: Couldn’t create rewrite_map(XXXX) 第一眼看以为是磁盘没有空间了,其实 ...
- [Hive - LanguageManual] Create/Drop/Alter Database Create/Drop/Truncate Table
Hive Data Definition Language Hive Data Definition Language Overview Create/Drop/Alter Database Crea ...
- 通过dbcp链接池对数据库操作报 Cannot create PoolableConnectionFactory (Could not create connection to database server. Attempted reconnect 3 times. Giving up.)--解决方案
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for ...
- create table as 和create table like的区别
create table as 和create table like的区别 对于MySQL的复制相同表结构方法,有create table as 和create table like 两种,区别是什么 ...
- Object.create(null)、Object.create({})、{} 三者创建对象的区别
参考 1.先看看我们经常使用的{}创建的对象是什么样子的: var o = {a:1}; console.log(o) 从上图可以看到,新创建的对象继承了Object自身的方法,如hasOwnProp ...
- jmeter连接mysql数据库报错Cannot create PoolableConnectionFactory (Could not create connection to database server.)
今天在学习jmeter的jdbc取样器,发现在配置完JDBC Connection Configuration和JDBC Request后,点击运行.在查看结果树中显示响应数据: Cannot cre ...
- Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Could not create connection to database server.
报错信息:Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQL ...
- 解决方案:android monkeyrunner:Timeout while trying to create chimp mananger(device = MonkeyRunner.waitForConnection()一直报错的问题)
monkeyrunner在执行device = MonkeyRunner.waitForConnection()一直报错的问题 (或者[main] [com.android.chimpchat.adb ...
- Create Shortcut to Get Jar File Meta Information
You have to get meta information of cobertura.jar with command "unzip -q -c cobertura.jar META- ...
- How to resize or create a thumbnail image from file stream on UWP
最近在搞Ocr相关的windows universal app, 用到了一些图像处理相关的知识. 涉及到了BitmapDecoder/BitmapEncoder/IRandomAccessStream ...
随机推荐
- Codeforces 735D:Taxes(哥德巴赫猜想)
http://codeforces.com/problemset/problem/735/D 题意:给出一个n,这个n可以分解成 n = n1 + n2 + -- + nk,其中k可以取任意数.要使得 ...
- [转]application windows are expected to have a root view controller错误
转载地址:http://blog.sina.com.cn/s/blog_6784e6ea01017jfy.html 最新更正:这个提示几乎不影响编译和运行,可以不用设置. 产生这个提示的操作: ...
- string xml json格式区别
string 是一种最普通的储存一串字符的数据格式 xml 是一种可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 它非常适合万维网传输,提供统一的方 ...
- 过滤器(Filter)案例:检测用户是否登陆的过滤器
*****检测用户是否登陆的过滤器:不需要用户跳转到每个页面都需要登陆,访问一群页面时,只在某个页面上登陆一次,就可以访问其他页面: 1.自定义抽象的 HttpFilter类, 实现自 Filter ...
- Uva 12186 工人的请愿书
题目链接:https://uva.onlinejudge.org/external/121/12186.pdf 题意: 给出一个树状关系图,公司里只有一个老板编号为0,其他人员从1开始编号.除了老板, ...
- Windows上Python3.5安装Scrapy(lxml) 以及与twisted有关错误的解决
转载于:http://www.cnblogs.com/silverbullet11/p/4966608.html 常用网址: Python 3.5: https://www.python.org/do ...
- linux poll 学习
一.poll介绍 函数原型: #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); struc ...
- 2016年10月27日 星期四 --出埃及记 Exodus 19:12
2016年10月27日 星期四 --出埃及记 Exodus 19:12 Put limits for the people around the mountain and tell them, `Be ...
- Myeclipse 添加server library
来自网络资料 (1)File->New->Other (2)弹出窗口勾上Show All Wizards,然后在type fiter text那里输入Server,选中server-> ...
- CentOS6.5下MAC
CentOS6.3安装Mac桌面主题 (2013-03-28 14:31:42) 转载▼ 首先下载Mac4Lin_Install_v1.0.zip 我给出个下载地址ht ...