0> 目标:
通过虚拟led设备实验,学习用户态ioctl()与驱动unlocked_ioctl( )之间的关系,忽略中间流程。
ioctl:io
control
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1> 用户空间:
int ioctl(int fd, int cmd, ...);
@fd:文件描述符
@cmd:命令,只是个数字,看成是用户态与客户态的暗号,内核建议了这个暗号的组织。
@...
: 这只写一个参数或不写,...的妙处:可以传任何类型的参数,学会这招。
2> kernel:
long unlocked_ioctl (struct file *filep, unsigned int cmd, unsigned long arg);
@filep:
@cmd: 等于用户态cmd。
@arg:等于用户态<...>传的值, 可看出用户态<...>只能写一个参数。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
补充:看看内核怎么设计暗号的:
创建命令:
点击(此处)折叠或打开
-
"/linux-3.5/include/asm-generic/ioctl.h"
-
-
#define _IOC_NRBITS 8
-
-
#define _IOC_TYPEBITS 8
-
-
# define _IOC_SIZEBITS 14
-
-
# define _IOC_DIRBITS 2
-
-
-
#define _IOC_NRSHIFT 0
-
-
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) //8
-
-
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) // 16
-
-
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) //30
-
-
-
#define _IOC(dir, type, nr, size) \
-
-
(((dir) << _IOC_DIRSHIFT) | \ 30
-
-
((type) << _IOC_TYPESHIFT) | \ 8
-
-
((nr) << _IOC_NRSHIFT) | \ 0
-
- ((size) << _IOC_SIZESHIFT)) 16
direction【31:30】 |
size【29:16】 |
Type[15:8] |
Number[7:0] |
数据传输方向2 |
数据大小14 |
幻数8 |
顺序编号8 |
……………………………………………………………………………………………………
# define _IOC_NONE 0U //无传输方向
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
解析密令:
#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
//((1<<8)-1) = 0x ff = 0b 1111_1111 赞一个,这招不能不学!!
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
//(cmd >> 0)& 0xff 就是number的值,
大牛:
http://www.cnblogs.com/geneil/archive/2011/12/04/2275372.html
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
实例源码:
app.txt
ioctl.txt
ledioctl.txt
Makefile.txt