linux 基础的字符设备驱动学习

驱动实现过程(使用应用程序调用驱动 方便测试:

在用户空间的应用程序调用某一个函数实现操作驱动中的设备———用户空间调用的API函数属于C库的一部分。这个应用程序的函数在驱动中的表现为操作函数

驱动加载成功后在 /dev 下生成文件

----------------------------------------------------------------

 /* 驱动入口函数 红色可改 */
 static int __init chrdevbase_init(void) 

    /* 入口函数具体内容 */
    int ret = 0;
    /*注册字符设备*/
    
    ret = register_chrdev(CHRDEVBASE_MAJOR,CHRDEVBASE_NAME, &chrdevbase_fops);
    if(ret < 0)
    {
        printk("chrdevbase init failed!\r\n");
    }
    else
    {
        printk("chrdevbase init !\r\n");
    }
    return 0; 

  
 /* 驱动出口函数 */
static void __exit chrdevbase_exit(void)
{
    printk("chrdevbase exit!\r\n");
    /* 出口函数具体内容 */
    /*注销字符设备*/
    unregister_chrdev(CHRDEVBASE_MAJOR,CHRDEVBASE_NAME);

}
/*模块入口*/
module_init(chrdevbase_init);//用此函数声明上述两个函数为驱动入口函数

/*模块出口*/
module_exit(chrdevbase_exit);

MODULE_LICENSE("GPL");
-----------------------------------------------------------------------------此时编译make 有.ko(模块)文件生成

第一次得用 :depmod

加载此模块——》 modprobe xxx.ko

卸载:rmmod xxx.ko

________________________________________________________

字符设备驱动:加载后需要注册

每个设备都有个设备号:设备号(32位)=主设备号:次设备号(高12 低20)
#define CHRDEVBASE_MAJOR    200                /* 主设备号 */

//cat /proc/device 查看的当前使用的设备号 选择没有使用的
#define CHRDEVBASE_NAME        "chrdevbase"     /* 设备名     */ 自己取

static struct file_operations chrdevbase_fops={
    .owner = THIS_MODULE, 
    .open = chrdevbase_open,
    .release = chrdevbase_release,
    .read = chrdevbase_read,
    .write = chrdevbase_write,
    //此部分就是实现与应用函数的函数调用的部分
 };/*定义内核操作函数结构体*/

ret = register_chrdev(CHRDEVBASE_MAJOR,CHRDEVBASE_NAME, &chrdevbase_fops);

——————————————————————————————————————

操作函数的具体实现(套用框架)

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

}

//用户在应用程序中读取程序 

static char readbuf[100];/*读缓冲*/
static char writebuf[100];/*写缓冲*/
static char kerneldate[] = {"kernel date!"};//在驱动中的字符数据 读到应用程序中

/dev/设备名
static ssize_t chrdevbase_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{

// 打开的设备文件 传给应用程序(用户空间的)缓冲区 读文件的大小 相对文件首地址的偏移
    int ret = 0 ;
    //printk("chrdevbase read!\r\n");
    memcpy(readbuf,kerneldate,sizeof(kerneldate));// kerneldate内存拷贝到readbuf
//将驱动中的数据放入缓冲区

//把中间的拷贝到第一个 读数据的大小由应用程序决定
    ret = copy_to_user(buf ,readbuf,count);//目的,来源:数量 #include <linux/uaccess.h>
    if (ret == 0)
    {
        /*拷贝成功*/
    }
    else
    {
        
    }
    
    return 0;

}

//将应用程序写到驱动中

// 设备 应用程序中的数据 数据长度 偏移

static ssize_t chrdevbase_write(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
    //printk("chrdevbase write!\r\n");
    int ret = 0;

//接收应用程序中的数据 

//把中间的拷贝到第一个 写数据的大小由应用程序决定
    ret = copy_from_user(writebuf,buf,count);
    if (ret == 0)
    {
        /* 写成功*/
        printk("kernel date = %s \r\n",writebuf);
    }
    else
    {
        
    }

    return 0;
}

————————————————————————————————————

在串口调试界面输入:

       . /chrdevbaseAPP /dev/chrdevbase 2 表示从驱动里面写数据

        ./chrdevbaseAPP /dev/chrdevbase 1 表示从驱动里面读数据

int main(int argc,char *argv[])
{

argc:应用程序参数个数  argv[]具体发参数内容 字符串形式 字符串数组 

argv[0]=./chrdevbaseAPP

argv[1]=/dev/chrdevbase

argv[2]=1/2

}

    filename = argv[1]; //为操作的文件名

/*open*/ 要打开的设备名 文件打开方式
    fd = open(filename,O_RDWR);

/*读命令 读驱动中的数据*/

   char readbuf[100], writebuf[100];
   static char usrdate[] = {"usr date!"};

 if(atoi(argv[2]) == 1)  //字符串的1 转换成数字1
ret = read(fd, readbuf,50);//50个字节

  /*写命令 将应用程序中的数据写到驱动中*/
 if(atoi(argv[2]) == 2)
        memcpy(writebuf,usrdate,sizeof(usrdate));//头文件#include <string.h>
        ret = write(fd, writebuf,50);//50个字节
 

    /*close*/
    ret = close(fd);

————————————————————————————

创建设备节点/dev/设备

应用程序通过设备节点实现与驱动的交互

Cat/proc/devices 查看设备名和设备号

mknod /dev/设备名 c 主设备号 次设备号

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值