Linux字符设备驱动

Linux字符设备驱动

  • Fang XS.
  • 1452512966@qq.com
  • 如果有错误,希望被指出

关于字符设备驱动

  • Linux设备的驱动分为字符设备驱动,块设备驱动,网络设备驱动。
  • 字符设备即以字节流进行读写的设备。

字符设备驱动框架

  1. 头文件
#include <linux/init.h>				// 提供模块初始化和注销
#include <linux/module.h>			// 提供初始化加载,卸载模块相关操作
#include <linux/fs.h>				// 提供文件系统相关定义
#include <linux/kdev_t.h>			// 提供设备号相关宏
#include <linux/cdev.h>				// 提供cdev结构体及相关函数定义
#include <linux/device.h>			// 提供class和device结构体相关定义
  1. 驱动初始化
/* 定义一个结构体,方便管理设备相关数据 */
struct dev{
     dev_t devnum;
     struct cdev cdev;
     struct class* pclass;
     struct device* pdevice;
}dev;

/* 驱动加载 */
static int dev_test_init(void){
    int ret;
    /* 动态申请字符设备号 */
    /* 查看设备号命令 cat /proc/devices */
    ret = alloc_chrdev_region(&dev.devnum,0,1,"dev_test");
    if(ret<0){		// 申请失败
        printk("alloc_chrdev_region err.\n");
        goto err_alloc_region;
    }
    // 初始化cdev结构体
    dev.cdev.owner = THIS_MODULE;
    // 关联 fops
    cdev_init(&dev.cdev,&fops);
    ret = cdev_add(&dev.cdev,dev.devnum,1);
    if(ret < 0){
        printk("cdev_add err.\n");
        goto err_cdev_add;
    }
    /*<- 创建类和设备生成设备节点 /dev/目录下 ->*/
    /* 创建类 /sys/class/下的类名即class_create第二个参数 */
    /* ls /sys/class */
    dev.pclass = class_create(THIS_MODULE,"dev_test");
    if(IS_ERR(dev.pclass)){
        goto err_class_create;
    }
    /* 创建设备 /dev/下的设备名即device_create第五个参数 */
    /* ls /dev/ */
    dev.pdevice = device_create(dev.pclass,NULL,dev.devnum,NULL,"dev_test");
    if(IS_ERR(dev.pdevice)){
        goto err_device_create;
    }
    printk("dev_test_init..\n");
    return 0;

/* 错误处理 */
err_device_create:
    class_destroy(dev.pclass);
err_class_create:
    cdev_del(&dev.cdev);
err_cdev_add:
    unregister_chrdev_region(dev.devnum,1);
err_alloc_region:
   return -1; 
}

  1. 填充file_operations结构体
ssize_t dev_read (struct file *file, char __user *buf, size_t size, loff_t *off){
    printk("dev_read.. \n");
    return 0;
}
ssize_t dev_write (struct file *file, const char __user *buf,
		size_t size, loff_t *off){
    printk("dev_write.. \n");
    return 0;
}
int dev_open (struct inode *inode, struct file *file){
    printk("dev_open.. \n");
    return 0;
}
int dev_release (struct inode *inode, struct file *file){
    printk("dev_release.. \n");
    return 0;
}

/** 
 * 应用对设备节点的open read write release 通过系统调用
 * 对应驱动的file_operations所定义的open read write release
*/
static struct file_operations fops = {
    .owner      = THIS_MODULE,
    .read       = dev_read,
    .write      = dev_write,
    .open       = dev_open,
    .release    = dev_release
};

  1. 驱动卸载
static void dev_test_exit(void){
    unregister_chrdev_region(dev.devnum,1);		// 先释放设备号
    cdev_del(&dev.cdev);						// 删除设备
    device_destroy(dev.pclass,dev.devnum);		// 注销设备
    class_destroy(dev.pclass);					// 删除类
    printk("dev_test_exit..\n");
}
  1. 模块入口出口
module_init(dev_test_init);
module_exit(dev_test_exit);

/* 必须的开源协议 */
MODULE_LICENSE("GPL");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值