linux驱动开发--copy_to_user 、copy_from_user函数实现内核空间数据与用户空间数据的相互访问
如果该操作为空,将使得read系统调用返回负EINVAL失败,正常返回实际读取的字节数
ssize_t (*read)(struct file *filp, char __user *buf, size_t count, lofft *f_pos);
filp:待操作的设备文件file结构体指针
buf:待写入所读取数据的用户空间缓冲区指针
count:待读取数据字节数
f_pos:待读取数据文件位置,读取完成后根据实际读取字节数重新定位
返回:成功实际读取的字节数,失败返回负值
设备写操作
如果该操作为空,将使得write系统调用返回负EINVAL失败,正常返回实际写入的字节数
ssize_t (*write)(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
filp:待操作的设备文件file结构体指针
buf:待写入所读取数据的用户空间缓冲区指针
count:待读取数据字节数
f_pos:待读取数据文件位置,写入完成后根据实际写入字节数重新定位
返回:成功实际写入的字节数,失败返回负值
内核为驱动程序提供在内核空间和用户空间传递数据的方法
定义在arch/arm/include/asm/uaccess.h中
用户空间-- 内核空间
copy_from_user函数
unsigned long copy_from_user(void *to, const void *from, unsigned long n);
to:目标地址(内核空间)
from:源地址(用户空间)
n:将要拷贝数据的字节数
返回:成功返回0,失败返回没有拷贝成功的数据字节数
get_user宏
int get_user(data, ptr);
data:可以是字节、半字、字、双字类型的内核变量
ptr:用户空间内存指针
返回:成功返回0,失败返回非0
-----------------------------------------------------------------------------------------------
内核空间-- 用户空间
copy_to_user函数
unsigned long copy_to_user(void *to, const void *from, unsigned long n)
to:目标地址(用户空间)
from:源地址(内核空间)
n:将要拷贝数据的字节数
返回:成功返回0,失败返回没有拷贝成功的数据字节数
put_user宏:
int put_user(data, prt)
data:可以是字节、半字、字、双字类型的内核变量
ptr:用户空间内存指针
返回:成功返回0, 失败返回非0
/** *Copyright (c) 2013.TianYuan *All rights reserved. *文件名称: char_device_driver08.c *文件标识: copy_to_user 、copy_from_user函数的使用 *当前版本:1.0 *作者:wuyq *取代版本:xxx *原作者:xxx *完成日期:2013-11-28 #include linux/init.h #include linux/module.h #include linux/fs.h #include linux/cdev.h #include linux/device.h #include linux/slab.h #include asm/uaccess.h
pcdevp = container_of(inode- i_cdev, struct cdd_cdev, cdev); printk("led = %d\n", pcdevp- led); filp- private_data = pcdevp; return 0; int cdd_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) int ret = 0; struct cdd_cdev *cdevp = filp- private_data; printk("enter cdd_read!\n"); ret = copy_to_user(buf, cdevp- kbuf, count); printk("kernel kbuf content:%s\n", cdevp- kbuf); return ret; int cdd_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) int ret = 0; struct cdd_cdev *cdevp = filp- private_data; printk("enter cdd_write!\n"); ret = copy_from_user(cdevp- kbuf, buf, count); return ret; int cdd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) printk("enter cdd_ioctl!\n"); return 0; int cdd_release(struct inode *inode, struct file *filp) printk("enter cdd_release!\n"); return 0; struct file_operations cdd_fops = { .owner = THIS_MODULE, .open = cdd_open, .read = cdd_read, .write = cdd_write, .ioctl = cdd_ioctl, .release = cdd_release, int __init cdd_init(void) int ret = 0; int i = 0; if(cdd_major){ dev = MKDEV(CDD_MAJOR, CDD_MINOR);//生成设备号 //注册设备号;1、要注册的起始设备号2、连续注册的设备号个数3、名字 ret = register_chrdev_region(dev, CDD_COUNT, "cdd_demo"); }else{ // 动态分配设备号 ret = alloc_chrdev_region( dev, cdd_minor, CDD_COUNT, "cdd_demo02"); if(ret 0){ printk("register_chrdev_region failed!\n"); goto failure_register_chrdev; //获取主设备号 cdd_major = MAJOR(dev); printk("cdd_major = %d\n", cdd_major); cdd_cdevp = kzalloc(sizeof(struct cdd_cdev)*CDD_COUNT, GFP_KERNEL); if(IS_ERR(cdd_cdevp)){ printk("kzalloc failed!\n"); goto failure_kzalloc; /*创建设备类*/ dev_class = class_create(THIS_MODULE, "cdd_class"); if(IS_ERR(dev_class)){ printk("class_create failed!\n"); goto failure_dev_class; for(i=0; i CDD_COUNT; i++){ /*初始化cdev*/ cdev_init( (cdd_cdevp[i].cdev), cdd_fops); /*添加cdev到内核*/ cdev_add( (cdd_cdevp[i].cdev), dev+i, 1); /* “/dev/xxx” */ device_create(dev_class, NULL, dev+i, NULL, "cdd%d", i); cdd_cdevp[i].led = i; return 0; failure_dev_class: kfree(cdd_cdevp); failure_kzalloc: unregister_chrdev_region(dev, CDD_COUNT); failure_register_chrdev: return ret; void __exit cdd_exit(void) /*逆序消除*/ int i = 0; for(; i CDD_COUNT; i++){ device_destroy(dev_class, dev+i); cdev_del( (cdd_cdevp[i].cdev)); //cdev_del( ((cdd_cdevp+i)- cdev)); class_destroy(dev_class); kfree(cdd_cdevp); unregister_chrdev_region(dev, CDD_COUNT); module_init(cdd_init); module_exit(cdd_exit);
/** *Copyright (c) 2013.TianYuan *All rights reserved. *文件名称: char_device_driver08_test.c *文件标识: 测试程序:测试内核空间的copy_to_user、copy_frome_user * 执行:先./char_device_driver08_test 再cat /dev/cdd0 cat /dev/cdd5观察两者的区别 *当前版本:1.0 *作者:wuyq *取代版本:xxx *原作者:xxx *完成日期:2013-11-28 #include stdio.h #include fcntl.h #include stdlib.h /*手工创建设备节点文件 mknod /dev/cdd c 248 0 int fd = 0; char rbuf[100]; char wbuf[100] = "nihao!\n";
Linux下访问DNS服务 要访问DNS服务,就必须先知道DNS服务器的IP地址。Linux 使用/etc/resolv.conf文件来存放DNS服务器的IP地址。机器ernest-laptop上,该文件的内容如下:
练习将maven项目打成war包放在linux服务器中,进行访问 第一次使用云服务器,练习将maven项目打成war包放在linux服务器中,进行访问。 这是阿里云的投稿活动,经过自己的尝试对阿里云服务器使用更加熟悉,阿里云使用方便,对学生也十分良心~让我学到了一些服务器的知识,祝阿里云团队蒸蒸日上~
相关文章
- linux刻录iso到u盘
- linux驱动开发--字符设备:内核等待队列
- linux驱动开发--内核链表
- linux驱动开发--内核空间中内存的申请与释放
- [Linux]linux如何把文件切成多块
- [linux]Linux下的log
- Linux下生成patch和打patch
- 【刷题】面筋-Linux 系统中“|”管道的作用是什么
- 【学习总结】快速上手Linux玩转典型应用-第6章-linux常用命令讲解
- linux(centos8):使用cgroups做资源限制
- linux中解压rar文件
- 【Linux基础】linux下的stdin,stdout和stderr理解
- 【学习总结】快速上手Linux玩转典型应用-第6章-linux常用命令讲解
- 十个不错的 Linux 网络监视工具
- Linux uname指令
- linux驱动开发重点关注内容--摘自《嵌入式Linux驱动模板精讲与项目实践》
- L78.linux命令每日一练 -- 第11章 Linux系统管理命令 -- iostat和iotop
- L64.linux命令每日一练 -- 第十章 Linux网络管理命令 -- ifconfig和ifup
- L43.linux命令每日一练 -- 第七章 Linux用户管理及用户信息查询命令 -- chage和chpasswd
- 嵌入式linux开发,Linux下访问PHY芯片寄存器
- 查看linux系统配置 查询Linux配置
- 02 从头开始atac项目 ubuntu20 install r4.2 Linux系统环境配置 服务器版本的rstudio r install in linux /ubuntu/centos
- kali linux 升级内核 安装内核头文件 安装nvidia驱动
- 编译win10的WSL2内核(windows subsystem linux)
- 【linux设备模型】之platform设备驱动
- 【Linux驱动开发100问】如何编译Linux内核?
- 【Linux驱动开发100问】什么是Linux内核?
- Linux 如何迅速分析定位CPU性能瓶颈