linux驱动:(6)应用层和内核层数据传输

目录

当对设备节点进行read

假如没有实现相对应的函数

应用层和数据层传数据

copy_from_user例子

copy_to_user例子


linux一切皆文件

文件对应的操作有打开,关闭,读取

设备节点对应的操作有打开,关闭,读取

当对设备节点进行read

例如当对设备节点进行open时,会调用这个驱动里的文件操作集结构体里的open成员

int (*open) (struct inode *,struct file *);

现在将第五章的misc代码文件操作集中的read实现

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
 
int misc_open(struct inode * inode,struct file * file)
{
    printk("hello misc_open\n");
    return 0;
}

struct const file_operation misc_fops = {
    .owner = THIS_MODULE,
    .open = misc_open
};
struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,//动态分配
    .name ="hellomisc",//设备节点名字
    .fops =&misc_fops 
};
 
static int misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0)
    {
        printk("misc registe is error\n");
        return -1;
    }
    printk("misc registe is success\n");
    return 0;
}
 
static void misc_exit(void)
{
    misc_deregister(&misc_dev);
    printk("misc goodbye");
}
 
module_init(misc_init);
module_exit(misc_exit);
 
MODULE_LICENSE("GPL");

将其编译成模块然后加载,并新建一个.c打开设备节点来测试

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

int main(int argc, char * argv)
{
    int fd;
    fd = open("/dev/hellomisc",O_RDWR);
    if (fd<0)
    {
        perror("open error\n");
        return fd;
    }
    close(fd);
    return 0;
}

用交叉编译放到板子上,运行就会输出 hello misc_open

其他的也是这么实现

假如没有实现相对应的函数

假如没有实现相对应的函数,但又对设备节点做出对应的函数操作,就不会有任何反应

应用层和数据层传数据

应用层和数据层不能直接传数据,有两个函数可以实现,只能在驱动中使用,定义在源码目录中的include/asm-generic/uaccess.h里

static inline long copy_from_user(void *to,const void _user *from, unsigned long n)
static inline long copy_to_user(void _user *to,const void *from, unsigned long n)
  • copy_from_user:应用层到内核层
  • copy_to_user:内核层到应用层

参数:

  • to:传到哪里去
  • from:数据从哪里来
  • n:数据大小

copy_from_user例子

修改上面misc驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
 
int misc_open(struct inode * inode,struct file * file)
{
    printk("hello misc_open\n");
    return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = "heheh";
    if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
    {
        printk("copy_to_user error\n");
        return -1;
    }
    return 0;
}
struct const file_operation misc_fops = {
    .owner = THIS_MODULE,
    .open = misc_open,
    .read = misc_read
};
struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,//动态分配
    .name ="hellomisc",//设备节点名字
    .fops =&misc_fops 
};
 
static int misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0)
    {
        printk("misc registe is error\n");
        return -1;
    }
    printk("misc registe is success\n");
    return 0;
}
 
static void misc_exit(void)
{
    misc_deregister(&misc_dev);
    printk("misc goodbye");
}
 
module_init(misc_init);
module_exit(misc_exit);
 
MODULE_LICENSE("GPL");

修改测试.c

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

int main(int argc, char * argv)
{
    int fd;
    char buf[64] = {0};
    fd = open("/dev/hellomisc",O_RDWR);
    if (fd<0)
    {
        perror("open error\n");
        return fd;
    }
    read(fd,buf,sizeof(buf));
    printf("buf is %s\n",buf);
    close(fd);
    return 0;
}

进行交叉编译和重新加载模块,运行后会打印出buf is heheh

copy_to_user例子

和上面操作一样,修改驱动代码和测试.c

驱动文件

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
 
int misc_open(struct inode * inode,struct file * file)
{
    printk("hello misc_open\n");
    return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = "heheh";
    if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
    {
        printk("copy_to_user error\n");
        return -1;
    }
    return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{
    char kbuf[64] = {0};
    if( copy_from_user(kbuf,ubuf,size)!=0)
    {
        printk("copy_from_user error\n");
        return -1;
    }
    printk("kbuf is %s\n",kbuf);
    return 0;
}
struct const file_operation misc_fops = {
    .owner = THIS_MODULE,
    .open = misc_open,
    .write= misc_write,
    .read = misc_read
};
struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,//动态分配
    .name ="hellomisc",//设备节点名字
    .fops =&misc_fops 
};
 
static int misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0)
    {
        printk("misc registe is error\n");
        return -1;
    }
    printk("misc registe is success\n");
    return 0;
}
 
static void misc_exit(void)
{
    misc_deregister(&misc_dev);
    printk("misc goodbye");
}
 
module_init(misc_init);
module_exit(misc_exit);
 
MODULE_LICENSE("GPL");

测试.c

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

int main(int argc, char * argv)
{
    int fd;
    char buf[64] = "heheh";
    fd = open("/dev/hellomisc",O_RDWR);
    if (fd<0)
    {
        perror("open error\n");
        return fd;
    }
    write(fd,buf,sizeof(buf));
    close(fd);
    return 0;
}

进行交叉编译和重新加载模块,运行后会打印出kbuf is heheh

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值