在Linux内核学习-字符设备驱动学习(一)中编写字符设备驱动的一种方法,但是需要手动创建设备节点。
有没有能够自动的创建设备节点的呢?
有!使用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);
- }
Makefile文件:
- obj-m := char01.o
- PWD := $(shell pwd)
- K_DIR := /lib/modules/$(shell uname -r)/build
- all:
- $(MAKE) -C $(K_DIR) M=$(PWD) modules
- clean:
- $(MAKE) -C $(K_DIR) M=$(PWD) clean
- test:char01_test.o
- gcc -o $@ $^