在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><br />#include <linux/module.h><br />#include <linux/cdev.h><br />#include <linux/device.h><br />#include <linux/kdev_t.h><br />#include <linux/fs.h><br />/////////////////////////////////////////////////<br />int char01_open(struct inode *inode, struct file *filp)<br />{<br /> printk("char01 open!/n");<br /> return 0;<br />}</p><p>int char01_release(struct inode *inode, struct file *filp)<br />{<br /> printk("char01 release!/n");<br /> return 0;<br />}</p><p>ssize_t char01_read(struct file *filp, char *buf,<br /> size_t count, loff_t *fpos)<br />{<br /> printk("char01 read!/n");<br /> return 0;<br />}</p><p>ssize_t char01_write(struct file *filp, const char *buf,<br /> size_t count, loff_t *fpos)<br />{<br /> printk("char01 write!/n");<br /> return 0;<br />}</p><p>int char01_ioctl(struct inode *inode, struct file *filp,<br /> unsigned int cmd, unsigned long param)<br />{<br /> printk("char01 ioctl!/n");<br /> printk("cmd:%d param:%ld/n", cmd, param);<br /> return 0;<br />}<br />/////////////////////////////////////////////////<br />struct file_operations fops =<br />{<br /> .owner = THIS_MODULE,<br /> .open = char01_open,<br /> .release = char01_release,<br /> .read = char01_read,<br /> .write = char01_write,<br /> .ioctl = char01_ioctl<br />};<br />dev_t devno;<br />struct class *pclass;<br />struct cdev dev;</p><p>int char01_dev_init(void)<br />{<br /> int result;<br /> result = alloc_chrdev_region(&devno, 0, 1, "char01");<br /> if (result != 0)<br /> {<br /> printk("alloc_chrdev_region failed!/n");<br /> goto ERR1;<br /> }</p><p> cdev_init(&dev, &fops);<br /> dev.owner = THIS_MODULE;<br /> dev.ops = &fops;<br /> result = cdev_add(&dev, devno, 1);<br /> if (result != 0)<br /> {<br /> printk("cdev_add failed!/n");<br /> goto ERR2;<br /> }</p><p> pclass = class_create(THIS_MODULE, "char01");<br /> if (IS_ERR(pclass))<br /> {<br /> printk("class_create failed!/n");<br /> goto ERR3;<br /> }</p><p> device_create(pclass, NULL, devno, NULL, "char01");</p><p> return 0;<br />ERR3:<br /> cdev_del(&dev);<br />ERR2:<br /> unregister_chrdev_region(devno, 1);<br />ERR1:<br /> return -1;<br />}<br />/////////////////////////////////////////////////<br />/////////////////////////////////////////////////<br />/////////////////////////////////////////////////<br />static int __init char01_init(void)<br />{<br /> printk("module char01 init!/n");<br /> return char01_dev_init();<br />}</p><p>static void __exit char01_exit(void)<br />{<br /> printk("module char01 exit!/n");<br /> class_destroy(pclass);<br /> device_destroy(pclass,devno);<br /> cdev_del(&dev);<br /> unregister_chrdev_region(devno, 1);<br />}<br />/////////////////////////////////////////////////<br />MODULE_LICENSE("Dual BSD/GPL");<br />MODULE_AUTHOR("Yao.GUET");<br />module_init(char01_init);<br />module_exit(char01_exit);<br />/////////////////////////////////////////////////
測試檔案char01_test.c
#include <stdio.h><br />#include <fcntl.h><br />#include <errno.h><br />#include <sys/stat.h><br />/////////////////////////////////////////////////<br />int main(int argc, char *argv)<br />{<br /> int fd;<br /> fd = open("/dev/char01", O_RDWR);<br /> if (fd<0)<br /> {<br /> printf("open /dev/char01 failed!/n");<br /> printf("%s/n", strerror(errno));<br /> return -1;<br /> }<br /> printf("open /dev/char01 ok!/n");<br /> ioctl(fd, 0);<br /> close(fd);<br />}<br />
Makefile檔案:
obj-m:=char01.o<br />PWD:=$(shell pwd)<br />K_DIR:=/lib/modules/$(shell uname -r)/build</p><p>all:<br />$(MAKE) -C $(K_DIR) M=$(PWD) modules<br />clean:<br />$(MAKE) -C $(K_DIR) M=$(PWD) clean<br />test:char01_test.o<br />gcc -o $@ $^