1.总览
- linux字符设备驱动创建基本流程图
2.整体框架
static int xxx_open(struct inode *inode, struct file *filp)
{
printk("xxx_open\n");
return 0;
}
static int xxx_release(struct inode *inode, struct file *filp)
{
printk("xxx_release\n");
return 0;
}
static ssize_t xxx_read(struct file *filp, char __user *user, size_t size, loff_t *loff)
{
printk("xxx_read\n");
return 0;
}
static ssize_t xxx_write(struct file *filp, const char __user *user, size_t size, loff_t *loff)
{
return 0;
}
static const struct file_operations xxx_fops = {
.owner = THIS_MODULE,
.open = xxx_open,
.release = xxx_release,
.write = xxx_write,
.read = xxx_read,
};
static int __init xxx_init(void)
{
.....
add_cdev(xxx, &xxx_fops);
.....
return 0;
}
static void __exit xxx_exit(void)
{
...
del_cdev(xxx);
...
}
module_init(xxx_init);
module_exit(xxx_exit);
MODULE_AUTHOR("yourname");
MODULE_LICENSE("GPL");
3.简化是例代码
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#define NEWCHRLED_MAJOR 200
#define NEWCHRLED_COUNT 1
#define NEWCHRLED_NAME "newchrled"
struct newchrled_dev {
struct cdev newchrled_cdev;
struct class *newchrled_class;
struct device *newchrled_device;
dev_t devid;
int major;
int minor;
};
static struct newchrled_dev newchrled;
static int newchrled_open(struct inode *inode, struct file *filp)
{
printk("newchrled_open\n");
return 0;
}
static int newchrled_release(struct inode *inode, struct file *filp)
{
printk("newchrled_release\n");
return 0;
}
static ssize_t newchrled_read(struct file *filp, char __user *user, size_t size, loff_t *loff)
{
printk("newchrled_read\n");
return 0;
}
static ssize_t newchrled_write(struct file *filp, const char __user *user, size_t size, loff_t *loff)
{
return 0;
}
static const struct file_operations newchrled_fops = {
.owner = THIS_MODULE,
.open = newchrled_open,
.release = newchrled_release,
.write = newchrled_write,
.read = newchrled_read,
};
static int __init newchrled_init(void)
{
printk("newchrled_init\n");
alloc_chrdev_region(&newchrled.devid, 0, NEWCHRLED_COUNT, NEWCHRLED_NAME)
newchrled.major = MAJOR(newchrled.devid);
newchrled.minor = MINOR(newchrled.devid);
printk("newchrled major:%d\tnewchrled minor:%d\n", newchrled.major, newchrled.minor);
newchrled.newchrled_cdev.owner = newchrled_fops.owner;
cdev_init(&newchrled.newchrled_cdev, &newchrled_fops);
cdev_add(&newchrled.newchrled_cdev, newchrled.devid, NEWCHRLED_COUNT
class_create(THIS_MODULE, "newchrled");
device_create(newchrled.newchrled_class, NULL , newchrled.devid, NULL, NEWCHRLED_NAME);
return 0;
}
module_init(newchrled_init);
static void __exit newchrled_exit(void)
{
printk("newchrled_exit\n");
device_destroy(newchrled.newchrled_class, newchrled.devid);
class_destroy(newchrled.newchrled_class);
cdev_del(&newchrled.newchrled_cdev);
unregister_chrdev_region(newchrled.devid, NEWCHRLED_COUNT);
}
module_exit(newchrled_exit);
MODULE_AUTHOR("yourname");
MODULE_LICENSE("GPL");