现在的位置: 首页 > 综合 > 正文

字符设备驱动学习(二) 设备接点的创建

2013年10月24日 ⁄ 综合 ⁄ 共 4777字 ⁄ 字号 评论关闭

驱动程序编写好后,还需要创建设备节点,有两种方式:

一是通过mknod命令去手动创建,例如:mknod /dev/hello c 250 0,/dev/hello为设备节点名字,c代表字符设备,250和0代表它的主次设备号。

二是使用udev或mdev来实现自动创建设备节点。

使用mknod手动创建设备节点不够灵活,如果是动态分配的设备号怎么办,难道每次加载驱动后去查看/proc/devices文件中查看它的主设备号,要是产品发布时怎么办,显然不太现实利用udev(mdev)来实现设备节点的自动创建,udev(mdev)存在于应用层。

包含头文件

#include<linux/device.h>


新建一个class结构体指针

static struct class *my_class;

在初始化函数中调用class_create()函数创建一个类,参数分别为模块所有者和class结构name字段,在/sys/class/下体现。

my_class= class_create(THIS_MODULE, "my_class");

if(IS_ERR(my_class)) 
{
       printk("Err: failed increating class.\n");

       return -1;

 }

调用device_create()函数创建设备节点,参数分别为所从属类,这个设备的父设备,没有就制定NULL,设备号,设备的私有数据,最后一组参数指定设备节点名,比如这里的名为hello。函数原型:

extern struct device *device_create(struct class *cls, structdevice *parent,

                                dev_t devt, void *drvdata,

                                const char *fmt, ...)

具体实现在drivers/base/core.c中

程序中使用

device_create(my_class,NULL,dev_n,NULL,"%s","hello");

或者

device_create(my_class,NULL,dev_n,NULL,"hello");

设备卸载删除类和设备节点

device_destroy(my_class,dev_n);

class_destroy(my_class);


使用class_create()和device_create()函数可以自动创建节点。

    class_create                 :    创建class
    class_destroy               :    销毁class
    class_device_create     :    创建device
    class_device_destroy   :    销毁device

class_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class *class_create(struct module *owner, const char *name)
    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.
在/sys/class/下创建类目录

class_device_create()
-------------------------------------------------
linux-2.6.22/include/linux/device.h
struct class_device *class_device_create(struct class        *cls,
                                         struct class_device *parent,
                                         dev_t               devt,
                                         struct device       *device,
                                         const char          *fmt, ...)

    class_device_create - creates a class device and registers it with sysfs
    @cls: pointer to the struct class that this device should be registered to.
    @parent: pointer to the parent struct class_device of this new device, if any.
    @devt: the dev_t for the char device to be added.
    @device: a pointer to a struct device that is assiociated with this class device.
    @fmt: string for the class device's name
在驱动模块初始化函数中实现设备节点的自动创建

设备驱动文件char01.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
/////////////////////////////////////////////////
int char01_open(struct inode *inode, struct file *filp)
{
    printk("char01 open!/n");
    return 0;
}

int char01_release(struct inode *inode, struct file *filp)
{
    printk("char01 release!/n");
    return 0;
}

ssize_t char01_read(struct file *filp, char *buf,
        size_t count, loff_t *fpos)
{
    printk("char01 read!/n");
    return 0;
}

ssize_t char01_write(struct file *filp, const char *buf,
        size_t count, loff_t *fpos)
{
    printk("char01 write!/n");
    return 0;
}

int char01_ioctl(struct inode *inode, struct file *filp,
        unsigned int cmd, unsigned long param)
{
    printk("char01 ioctl!/n");
    printk("cmd:%d param:%ld/n", cmd, param);
    return 0;
}
/////////////////////////////////////////////////
struct file_operations fops = 
{
    .owner      =   THIS_MODULE,
    .open       =   char01_open,
    .release    =   char01_release,
    .read       =   char01_read,
    .write      =   char01_write,
    .ioctl      =   char01_ioctl
};
dev_t   devno;
struct class *pclass;
struct cdev dev;

int char01_dev_init(void)
{
    int result;
    result = alloc_chrdev_region(&devno, 0, 1, "char01");
    if (result != 0)
    {
        printk("alloc_chrdev_region failed!/n");
        goto ERR1;
    }
    
    cdev_init(&dev, &fops);
    dev.owner   =   THIS_MODULE;
    dev.ops     =   &fops;
    result = cdev_add(&dev, devno, 1);
    if (result != 0)
    {
        printk("cdev_add failed!/n");
        goto ERR2;
    }

    pclass = class_create(THIS_MODULE, "char01");
    if (IS_ERR(pclass))
    {
        printk("class_create failed!/n");
        goto ERR3;
    }
    
    device_create(pclass, NULL, devno, NULL, "char01");

    return 0;
ERR3:
    cdev_del(&dev);
ERR2:
    unregister_chrdev_region(devno, 1);
ERR1:
    return -1;
}
/////////////////////////////////////////////////
/////////////////////////////////////////////////
/////////////////////////////////////////////////
static int __init char01_init(void)
{
    printk("module char01 init!/n");
    return char01_dev_init();
}

static void __exit char01_exit(void)
{
    printk("module char01 exit!/n");
    class_destroy(pclass);
    device_destroy(pclass,devno);
    cdev_del(&dev);
    unregister_chrdev_region(devno, 1);
}
/////////////////////////////////////////////////
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Yao.GUET");
module_init(char01_init);
module_exit(char01_exit);
/////////////////////////////////////////////////

测试文件char01_test.c

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
/////////////////////////////////////////////////
int main(int argc, char *argv)
{
    int fd;
    fd = open("/dev/char01", O_RDWR);
    if (fd<0)
    {
        printf("open /dev/char01 failed!/n");
        printf("%s/n", strerror(errno));
        return -1;
    }
    printf("open /dev/char01 ok!/n");
    ioctl(fd, 0);
    close(fd);
}

【上篇】
【下篇】

抱歉!评论已关闭.