Rk3568驱动开发_完善字符驱动_4

1.代码

驱动代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>


#define CHREDEVBASE_MAJOR 200  // 主设备号
#define CHRDEVNAME  "chrdevbase"  // 名字

static char kernaldata[20] = {"kerndata"};

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 ssize_t chrdevbase_read(struct file* filp, __user char* buf, size_t count, 
                                loff_t* ppos){
    int ret = 0;

    // 应用程序不能直接访问内核,必须借助其他函数
    ret = copy_to_user(buf, kernaldata, count); // 将内核数据copy到用户
    if(ret < 0){
        printk("copy to user error\r\n");
        return -1;
    }                             
    //printk("hrdevbase_read\r\n");
    return 0;                
}

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

    ret = copy_from_user(kernaldata, buf, count);
    if(ret < 0){
        printk("copy from user error\r\n");
        return -1;
    }
    printk("write msg is %s\r\n", kernaldata);
    return 0;
}


// 字符设备操作集合
static struct file_operations chrdevbase_fops={
    .owner = THIS_MODULE,       // 属于这个驱动模块
    .open = chrdevbase_open,
    .release = chrdevbase_release,
    .read = chrdevbase_read,
    .write = chrdevbase_write,
};



static int __init chrdevbase_init(void){   

    int ret = 0;

    printk("chrdevbase_init\r\n");
    // 注册字符设备
    ret = register_chrdev(CHREDEVBASE_MAJOR, CHRDEVNAME, &chrdevbase_fops);
    
    if(ret < 0){
        printk("chrdevbase init failed\r\n");
        unregister_chrdev(CHREDEVBASE_MAJOR, CHRDEVNAME);
    }

    return 0;
}

static void __exit chrdevbase_exit(void){
    printk("chrdevbase_exit\r\n");
}

// 核心修正点:添加以下声明
MODULE_LICENSE("GPL");          // 必须声明许可证(例如GPL)
MODULE_AUTHOR("Narnat");      // 可选:作者信息
MODULE_DESCRIPTION("chrdevbase"); // 可选:模块描述

// 模块入口与出口
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);

app代码:

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

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

    int ret = 0;
    int fd;
    char readbuf[10], writebuf[50];
    static char userdata[] = {"helloa"};

    if(argc != 3){
      printf("ERROR USAGE!\r\n");
      return -1;
    }
    
    char* filename;
    filename = argv[1];

    fd = open(filename, O_RDWR);

    if(fd < 0){
      printf("cant open file %s\r\n", filename);
      return -1;
    }

    if(atoi(argv[2]) == 1){ // 读
        ret =  read(fd, readbuf, sizeof(readbuf));
        if(ret < 0){
          printf("read file %s failed\r\n", filename);
          return -1;
        }else{
          printf("RERAD DATA: %s\r\n", readbuf);
        }
    }

 
    if(atoi(argv[2]) == 2){ // 读

        memcpy(writebuf, userdata, sizeof(userdata));
        ret = write(fd, writebuf, sizeof(userdata));
        if(ret < 0){
          printf("write file %s failed!\r\n", filename);
        }
    }

    close(fd);

    return 0;
}

2.实验现象:

在这里插入图片描述

3.总结分析:

用户层在调用open函数打开设备节点后,应用层上的write和read函数调用的是我们自己实现的驱动函数,同理在linux操作系统上调用write和read函数去操作txt文件的时候调用的是系统实现的函数

需要注意的是:

应用层没办法直接读取或写入数据到内核里,所以要借助接口函数copy_to_user、copy_from_user函数去做

app层往内核写数据要注意安全严谨,容易发生缓冲区溢出

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值