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

http://tech.ccidnet.com/art/302/20080304/1379211_1.html

http://blog.csdn.net/chchchdx123/article/details/6248486

时间: 2024-10-08 16:39:36

Class create, device create, device create file【转】的相关文章

sql入门教程:sql 创建表create table 与数据库[create databse]

sql入门教程:sql 创建表create table 与数据库[create databse] 在创建数据库的声明 在CREATE DATABASE语句是用来建立一个数据库. 创建数据库的SQL语法 CREATE DATABASE database_name 创建数据库的例子现在,我们要建立一个数据库,所谓的" my_db " . 我们使用下面的CREATE DATABASE语句:CREATE DATABASE my_db   下面来看看sql 创建表create table 在创建

create index online 和create index 不同及注意点

CREATE INDEX ONLINE 锁模式变化模拟 SESSION 139 SQL>  insert into test123   2  select * from dba_objects;   50062 rows inserted 不提交 SESSION 148 SQL> create index test123_i on test123(owner) online; 回话148堵塞 SQL>  select * from v$lock where sid in ('139','

二维码扫描-安卓开发中的Device device = new Device();是什么意思啊!

问题描述 安卓开发中的Device device = new Device();是什么意思啊! Device device = new Device(); device.setKeyNum(""); device.setcodingNum(scanResult); 这几句代码什么意思啊 百度不出来怎么 安卓项目里 的 解决方案 Device device = new Device(); //创建一个Device对象实例 device.setKeyNum("");//

Windows 7 出错:Cann&amp;#39;t access Input/Mic device or device is already in use.

在Web中使用vaxsip时,拨号 出错:Windows 7 出错:Cann't access Input/Mic device or device is already in use. 解决方法: 系统右下角声音图标 右键->声音(S)->录制->麦克风->"右键"设置为默认设备(不是默认通信设备)  

MySQL create table as与create table like对比

      在MySQL数据库中,关于表的克隆有多种方式,比如我们可以使用create table ..as .. ,也可以使用create table .. like ..方式.然而这2种不同的方式还是有些差异的,他的差异到底在哪里呢,本文通过演示对此展开描述. 1.mysql sakila表上的结构 --actor表状态 robin@localhost[sakila]> show table status like 'actor'\G ***************************

MySQL中表复制:create table like 与 create table as select_Mysql

复制代码 代码如下: CREATE TABLE A LIKE B 此种方式在将表B复制到A时候会将表B完整的字段结构和索引复制到表A中来. 复制代码 代码如下: CREATE TABLE A AS SELECT x,x,x,xx FROM B LIMIT 0 此种方式只会将表B的字段结构复制到表A中来,但不会复制表B中的索引到表A中来.这种方式比较灵活可以在复制原表表结构的同时指定要复制哪些字段,并且自身复制表也可以根据需要增加字段结构. 两种方式在复制表的时候均不会复制权限对表的设置.比如说原

How to Create a Framework for iOS[RE]

In the previous tutorial, you learned how to create a reusable knob control. However, it might not be obvious how to make it easy for other developers to reuse it. One way to share it would be to provide the source code files directly. However, this

Unable To Create Database Using ASM ORA-15055

不能在asm 实例上创建oracle 10g 数据库,报错如下: CREATE DATABASE "ekbkprd1" ORA-01501: CREATE DATABASE failed ORA-00200: controlfile could not be created ORA-00202: controlfile: '+DG1_NR/ekbkprd1/control/ekbkprd1_control.ctl' ORA-17502: ksfdcre:4 Failed to crea

13.1.17 CREATE TABLE Syntax

13.1.17 CREATE TABLE Syntax   13.1.17.1 CREATE TABLE ... LIKE Syntax 13.1.17.2 CREATE TABLE ... SELECT Syntax 13.1.17.3 Using FOREIGN KEY Constraints 13.1.17.4 Silent Column Specification Changes CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name (cre