chrdevbase字符设备驱动开发实验学习--基于MX6U(01)

chrdevbase设备有两个缓冲区(读/写),大小均为100字节,可在应用程序中进行基础的写入和读取数据操作。

应用程序实现步骤为:1)调用open函数打开chrdevbase设备;2)使用write函数向chrdevbase设备的缓冲区writebuf中写入数据或使用read函数读取缓冲区readbuf中的数据;3)使用close函数关闭chrdevbase设备。

驱动程序及解析

1 头文件导入

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>

这些头文件为开发字符设备驱动程序提供了必要的工具和接口。在一个字符设备驱动程序中,开发者通常需要管理设备的打开、读写、关闭等操作,同时与硬件进行交互,并处理可能出现的延迟或错误。通过包含这些头文件,开发者可以使用 Linux 内核提供的标准化工具和功能来简化驱动程序的开发过程

2 参数定义

#define CHRDEVBASE_MAJOR    200               /* 主设备号   */
#define CHRDEVBASE_NAME    "chrdevbase"       /* 设备名称   */
static char readbuf[100];                     /* 读缓冲区   */
static char writebuf[100];                    /* 写缓冲区   */
static char kerneldata[] = {"kernel data"}:

主设备号用于区分不同的设备驱动程序,设备名称是字符设备的标识符,"static"关键字用于指定"readbuf"的存储类为静态,意味着它的生命周期贯穿整个驱动程序的运行过程,100表示字节长度,"kerneldata"是一个静态字符数组,被初始化成一个字符串。

3 打开设备

static int chrdevbase_open(struct inode *inode, struct file *filp)
{
    //printk("chrdevbase open!\r\n")
    return 0;
}

"static"表示这个函数的作用域仅限于这个源文件内,其他文件不能直接调用这个函数。"struct inode *inode"为指向"inode"结构体的指针,表示正在被打开的设备文件的索引节点,"struct file *filp"是指向"file"结构体的指针,表示与文件操作相关的信息。

4 从设备读取数据

static ssize_t chrdevbase_read(struct file *filp, char __user *buf,  size_t cnt, loff_t *offt) 
{ 
    int retvalue = 0; 
    /* 向用户空间发送数据 */ 
    memcpy(readbuf, kerneldata, sizeof(kerneldata)); 
    retvalue = copy_to_user(buf, readbuf, cnt); 
    if(retvalue == 0){ 
        printk("kernel senddata ok!\r\n"); 
    }else{ 
        printk("kernel senddata failed!\r\n"); 
    }  
    //printk("chrdevbase read!\r\n"); 
    return 0; 
} 

"ssize_t"表示可以返回读取的字节数,或错误代码(如负值),cnt为需要读取的字节数,offt为文件的偏移量指针,表示从文件的哪个位置开始读。memcpy函数从kerneldata拷贝数据到readbuf,sizeof(kerneldata)确保了memcpy的字节数与kerneldata的大小一致。copy_to_user是一个内核函数,尝试将readbuf中cnt个字节的数据复制到用户空间的buf。

5 向设备写数据

static ssize_t chrdevbase_write(struct file *filp, const char __user *buf,  size_t cnt, loff_t *offt) 
{ 
    int retvalue = 0; 
    /*  接收用户空间传递给内核的数据并且打印出来 */ 
    retvalue = copy_to_user(writebuf, buf, cnt); 
    if(retvalue == 0){ 
        printk("kernel recevdata:%s\r\n", writebuf); 
    }else{ 
        printk("kernel recevdata failed!\r\n"); 
    }  
    //printk("chrdevbase write!\r\n"); 
    return 0; 
} 

注意copy_to_user的参数格式一般如下:

long copy_to_user(void *to, const void *from, unsigned long n);

其中,to表示目标地址、from为源地址、n为要复制的字节数。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值