linux 使用 ioctl 参数
在看 scull 驱动的 ioctl 代码之前, 我们需要涉及的另一点是如何使用这个额外的参数. 如果它是一个整数, 就容易: 它可以直接使用. 如果它是一个指针, 但是, 必须小心些.
当用一个指针引用用户空间, 我们必须确保用户地址是有效的. 试图存取一个没验证过的 用户提供的指针可能导致不正确的行为, 一个内核 oops, 系统崩溃, 或者安全问题. 它 是驱动的责任来对每个它使用的用户空间地址进行正确的检查, 并且返回一个错误如果它 是无效的.
在第 3 章, 我们看了 copy_from_user 和 copy_to_user 函数, 它们可用来安全地移动 数据到和从用户空间. 这些函数也可用在 ioctl 方法中, 但是 ioctl 调用常常包含小数 据项, 可通过其他方法更有效地操作. 开始, 地址校验(不传送数据)由函数 access_ok 实现, 它定义在 <asm/uaccess.h>:
int access_ok(int type, const void *addr, unsigned long size);
第一个参数应当是 VERIFY_READ 或者 VERIFY_WRITE, 依据这个要进行的动作是否是读用 户空间内存区或者写它. addr 参数持有一个用户空间地址, size 是一个字节量. 例如, 如果 ioctl 需要从用户空间读一个整数, size 是 sizeof(int). 如果你需要读和写给定 地址, 使用 VERIFY_WRITE, 因为它是 VERIRY_READ 的超集.
不象大部分的内核函数, access_ok 返回一个布尔值: 1 是成功(存取没问题)和 0 是失 败(存取有问题). 如果它返回假, 驱动应当返回 -EFAULT 给调用者.
关于 access_ok 有多个有趣的东西要注意. 首先, 它不做校验内存存取的完整工作; 它只 检查看这个内存引用是在这个进程有合理权限的内存范围中. 特别地, access_ok 确保这 个地址不指向内核空间内存. 第 2, 大部分驱动代码不需要真正调用 access_ok. 后面描 述的内存存取函数为你负责这个. 但是, 我们来演示它的使用, 以便你可见到它如何完成.
scull 源码利用了 ioclt 号中的位段来检查参数, 在 switch 之前: int err = 0, tmp;
int retval = 0;
/*
* extract the type
and number bitfields, and don't decode
* wrong cmds:
return ENOTTY (inappropriate ioctl) before access_ok()
*/
if (_IOC_TYPE(cmd) != SCULL_IOC_MAGIC)
return -ENOTTY;
if (_IOC_NR(cmd) > SCULL_IOC_MAXNR)
return -ENOTTY;
/*
* the direction is
a bitmask, and VERIFY_WRITE catches R/W
* transfers. `Type'
is user-oriented, while
* access_ok is
kernel-oriented, so the concept of "read" and
* "write"
is reversed
*/
if (_IOC_DIR(cmd) & _IOC_READ)
err =
!access_ok(VERIFY_WRITE, (void user *)arg, _IOC_SIZE(cmd)); else if
(_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void user *)arg, _IOC_SIZE(cmd));
if (err)
return -EFAULT;
在调用
access_ok 之后, 驱动可安全地进行真正的传输. 加上 copy_from_user 和 copy_to_user_ 函数, 程序员可利用一组为被最多使用的数据大小(1,
2, 4, 和 8 字节) 而优化过的函数. 这些函数在下面列表中描述, 它们定义在 <asm/uaccess.h>:
put_user(datum, ptr)
put_user(datum,
ptr)
这些宏定义写 datum 到用户空间; 它们相对快, 并且应当被调用来代替
copy_to_user 无论何时要传送单个值时. 这些宏已被编写来允许传递任何类型的 指针到 put_user, 只要它是一个用户空间地址. 传送的数据大小依赖 prt 参数的 类型, 并且在编译时使用 sizeof 和 typeof 等编译器内建宏确定. 结果是, 如果 prt 是一个 char 指针, 传送一个字节, 以及对于 2, 4, 和 可能的 8 字节.
put_user
检查来确保这个进程能够写入给定的内存地址. 它在成功时返回 0, 并 且在错误时返回 -EFAULT. put_user 进行更少的检查(它不调用
access_ok), 但是仍然能够失败如果被指向的内存对用户是不可写的. 因此, put_user 应当 只用在内存区已经用 access_ok 检查过的时候.
作为一个通用的规则,
当你实现一个 read 方法时, 调用 put_user 来节省几个 周期, 或者当你拷贝几个项时, 因此, 在第一次数据传送之前调用 access_ok 一
次, 如同上面 ioctl 所示.
get_user(local, ptr)
get_user(local,
ptr)
这些宏定义用来从用户空间接收单个数据.
它们象 put_user 和 put_user, 但 是在相反方向传递数据. 获取的值存储于本地变量 local; 返回值指出这个操作是 否成功. 再次, get_user 应当只用在已经使用 access_ok 校验过的地址.
如果做一个尝试来使用一个列出的函数来传送一个不适合特定大小的值,
结果常常是一个 来自编译器的奇怪消息, 例如"coversion to non-scalar type requested". 在这些情况
中, 必须使用 copy_to_user 或者 copy_from_user.
linux 使用 ioctl 参数的更多相关文章
- linux mount命令参数及用法详解
linux mount命令参数及用法详解 非原创,主要来自 http://www.360doc.com/content/13/0608/14/12600778_291501907.shtml. htt ...
- 【转】linux expr命令参数及用法详解
在抓包过程中,查看某个设定时间内,数据上下行多少,用命令expr 计算! --------------------------------------------------------------- ...
- linux dmesg命令参数及用法详解(linux显示开机信息命令)
linux dmesg命令参数及用法详解(linux显示开机信息命令) http://blog.csdn.net/zhongyhc/article/details/8909905 功能说明:显示开机信 ...
- linux sed命令参数及用法详解
linux sed命令参数及用法详解 http://blog.csdn.net/namecyf/article/details/7336308 1. Sed简介 sed 是一种在线编辑器,它一次处理一 ...
- Linux mail 命令参数
linux mail 命令参数: 使用mail发邮件时,必须先将sendmail服务启动. mail –s “邮件主题” –c”抄送地址” –b “密送地址” -- -f 发送人邮件地址 –F 发件人 ...
- Linux VM子系统参数调整
Timesten数据库下的Linux page子系统参数调整 如果Timesten(TT)采用了Durablecommits或是share memory segment被lock的话,那么linux ...
- linux内核启动参数
Linux内核启动参数 Console Options 参数 说明 选项 内核配置/文件 console=Options 用于说明输出设备 tt ...
- linux dd命令参数及用法详解---用指定大小的块拷贝一个文件(也可整盘备份)
linux dd命令参数及用法详解---用指定大小的块拷贝一个文件 日期:2010-06-14 点击:3830 来源: 未知 分享至: linux dd命令使用详解 dd 的主要 ...
- nginx的linux服务器内核参数调整【转】
概述 由于默认的linux内核参数考虑的是最通用场景,这明显不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,让Nginx可以拥有更高的性能: 在优化内核时,可以做的事情很 ...
随机推荐
- 大数据技术之HBase
第1章 HBase简介 1.1 什么是HBase HBase的原型是Google的BigTable论文,受到了该论文思想的启发,目前作为Hadoop的子项目来开发维护,用于支持结构化的数据存储. 官方 ...
- ajax请求与form表单提交共存的时候status为canceled
chrome浏览器调试,发现,status竟然是canceled状态 网上总论: 1.在URL变更后,会对当前正在执行的ajax进求进行中止操作.中止后该请求的状态码将为canceled 2.在使用到 ...
- SDUT-3361_迷宫探索
数据结构实验之图论四:迷宫探索 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 有一个地下迷宫,它的通道都是直的,而通道 ...
- Java中清空session的方法
session.removeAttribute("sessionname")是清除SESSION里的某个属性. session.invalidate()是让SESSION失效. 或 ...
- sql —— having
在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与聚合函数一起使用.HAVING 子句可以让我们筛选分组后的各组数据. 原表: 我们可以对上面数据根据性别这个字段进行分组查询,分别 ...
- poj 1085 Triangle War (状压+记忆化搜索)
Triangle War Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2685 Accepted: 1061 Desc ...
- form表单提交,后台怎么获取select的值?后台直接获取即可,和input方式一样。
form表单提交,后台怎么获取select的值? 后台直接获取即可,和后台获取input的值方式一样. form提交后,后台直接根据select的name获取即可,即getPara("XXX ...
- @loj - 2174@ 「FJOI2016」神秘数
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一个可重复数字集合 S 的神秘数定义为最小的不能被 S 的子集的 ...
- Android中后台线程如何与UI线程交互
我想关于这个话题已经有很多前辈讨论过了.今天算是一次学习总结吧. 在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须 ...
- 洛谷 2158 [SDOI2008]仪仗队
Description 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是 ...