Linux驱动 字符设备驱动程序(二)

实现字符设备启动程序的基本框架

  1. 申请设备号,使用alloc_chrdev_region动态分配一个或多个设备号;
  2. 创建设备类,使用class_create函数创建自己的设备类,在 sys/class 可见;
  3. 注册设备,通过cdev_init和cdev_add注册设备,并实现file_operations,与之建立关联;
  4. 创建设备,使用device_create将注册的设备建立关联,设备会在 /dev 目录创建。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/err.h>

static dev_t led_devt;
struct cdev *led_cdev;
struct class *led_cls;
struct device *led_dev;

int led_dev_open(struct inode *inode, struct file *file) {

	printk(KERN_ALERT "%s\n", __FUNCTION__);

	return 0;
}

int led_dev_release(struct inode *inode, struct file *file) {

	printk(KERN_ALERT "%s\n", __FUNCTION__);

	return 0;
}

long led_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {

	printk(KERN_ALERT "%s\n", __FUNCTION__);

	return 0;
}


/* 创建 file_operations */
static const struct file_operations led_dev_fops = {

	.open = led_dev_open,
	.release = led_dev_release,
	.unlocked_ioctl = led_dev_ioctl,
};

static int __init drv_led_init(void) {

	int err;
	
	printk(KERN_ALERT "%s\n", __FUNCTION__);

	/* 申请设备号 */
	err = alloc_chrdev_region(&led_devt, 0, 1, "dev_led");
	if(err < 0) {
		pr_err("alloc_chrdev_region error!\n");
		goto err_alloc_chrdev;
	}

	/* 创建设备类,可在系统中 /sys/class 中可见 */
	led_cls = class_create(THIS_MODULE, "drv_leds");
	if(IS_ERR(led_cls)) {
		pr_err("class_create error!\n");
		err = PTR_ERR(led_cls);
		goto err_class_create;
	}

	/* 创建一个cdev对象 */
	led_cdev = cdev_alloc();
	if(IS_ERR(led_cdev)) {
		pr_err("cdev_alloc error!\n");
		err = PTR_ERR(led_cdev);
		goto err_cdev_alloc;
	}

	/* 初始化cdev对象,将cdev对象与对印的file_operations建立关联 */
	cdev_init(led_cdev, &led_dev_fops);

	/* 注册设备,让用户访问设备 */
	err = cdev_add(led_cdev, led_devt, 1);
	if(err < 0) {
		pr_err("cdev_add error!\n");
		goto err_cdev_add;
	}

	/* 创建设备 */
	led_dev = device_create(led_cls, NULL, led_devt, NULL, "led0");
	if(IS_ERR(led_dev)) {
		pr_err("device_create error!\n");
		err = PTR_ERR(led_dev);
		goto err_device_create;
	}

	return 0;

err_device_create:
err_cdev_add:
	cdev_del(led_cdev);
err_cdev_alloc:
	class_destroy(led_cls);
err_class_create:
	unregister_chrdev_region(led_devt, 1);
err_alloc_chrdev:
	return err;
}

static void __exit drv_led_exit(void) {

    printk(KERN_ALERT "%s\n", __FUNCTION__);
	device_destroy(led_cls, led_devt);
	class_destroy(led_cls);
	cdev_del(led_cdev);
	unregister_chrdev_region(led_devt, 1);
} 

module_init(drv_led_init);
module_exit(drv_led_exit);

MODULE_LICENSE("GPL");
MODULE_VERSION("V0.0.1");
MODULE_AUTHOR("dengcaixiang");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你好,工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值