字符设备驱动2(添加应用程序来调用驱动)

应用程序是通过主次设备号来寻找对应的在内核中维护的file_operations结构体,从而操作相应的设备。
驱动设备文件的创建:
设备号=主设备号+次设备号,主设备号表示种类,次设备号表示第几个。默认次设备号是0,使用ls -l可以查看该设备的主次设备号.
mknod来创建主次设备号mknod dev/xxx c 主设备号 次设备号(C表示字符设备)

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


#define FILE    "/dev/test"         // 刚才mknod创建的设备文件名


int main(void)
{
    int fd = -1;

    fd = open(FILE, O_RDWR);
    if (fd < 0)
    {
        printf("open %s error.\n", FILE);
        return -1;
    }
    printf("open %s success..\n", FILE);

    // 读写文件


    // 关闭文件
    close(fd);

    return 0;
}

改程序是应用程序代码,在insmod 安装驱动后,再通过mknod创建设备文件,创建设备的主次设备号要与驱动中register_chardev()注册的主次设备号一致。这样在应用中使用open和close函数就可以调用驱动着设置的file_operations里面的对应的函数。

为了实现读写操作,需要应用和驱动之间传递数据,应用和驱动所在的地址空间不一样,不能直接相互访问,可以用以下两个函数
copy_from_user 从用户空间到内核空间
copy_to_user 从内核空间到用户空间
函数如果成功返回0,不成功返回未成功复制的字节数。
在file_operations中添加读写操作

// 自定义一个file_operations结构体变量,并且去填充
static const struct file_operations test_fops = {
    .owner      = THIS_MODULE,              // 惯例,直接写即可

    .open       = test_chrdev_open,         // 将来应用open打开这个设备时实际调用的
    .release    = test_chrdev_release,      // 就是这个.open对应的函数
    .write      = test_chrdev_write,
    .read       = test_chrdev_read,
};

读写的函数为

// 写函数的本质就是将应用层传递过来的数据先复制到内核中,然后将之以正确的方式写入硬件完成操作。
static ssize_t test_chrdev_write(struct file *file, const char __user *ubuf,
    size_t count, loff_t *ppos)
{
    int ret = -1;

    printk(KERN_INFO "test_chrdev_write\n");

    // 使用该函数将应用层传过来的ubuf中的内容拷贝到驱动空间中的一个buf中
    //memcpy(kbuf, ubuf);       // 不行,因为2个不在一个地址空间中
    ret = copy_from_user(kbuf, ubuf, count);
    if (ret)
    {
        printk(KERN_ERR "copy_from_user fail\n");
        return -EINVAL;
    }
    printk(KERN_INFO "copy_from_user success..\n");

    // 真正的驱动中,数据从应用层复制到驱动中后,我们就要根据这个数据
    // 去写硬件完成硬件的操作。所以这下面就应该是操作硬件的代码


    return 0;
}
ssize_t test_chrdev_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
{
    int ret = -1;

    printk(KERN_INFO "test_chrdev_read\n");

    ret = copy_to_user(ubuf, kbuf, count);
    if (ret)
    {
        printk(KERN_ERR "copy_to_user fail\n");
        return -EINVAL;
    }
    printk(KERN_INFO "copy_to_user success..\n");


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值