Linux驱动学习—ioctl接口

Linux驱动学习—ioctl接口本文详细解释了 unlock ioctl 与 ioctl 在 Linux2 6 36 内核中的区别 介绍了它们的相似性和不同之处 包括 unlock ioctl 的优势以及其在命令规则 合成宏和分解宏方面的应用

大家好,欢迎来到IT知识分享网。

1、unlock_ioctl和ioctl有什么区别?

kernel 2.6.36 中已经完全删除了struct file_operations 中的ioctl 函数指针,取而代之的是unlocked_ioctl 。ioctl是老的内核版本中的驱动API,unlock_ioctl是当下常用的驱动API。unlocked_ioctl 实际上取代了用了很久的ioctl,主要的改进就是不再需要上大内核锁(BKL) (调用之前不再先调用lock_kernel()然后再unlock_kernel())。

2、unlock_ioctl和read/write函数有什么相同点和不同点

相同点:都可以往内核里面写数据。

不同点:read函数只能完成读的功能,write只能完成写的功能。读取大数据的时候效率高。ioctrl既可以读也可以写。读取大数据的时候效率不高。

Linux驱动学习—ioctl接口

3、unlock_ioctl接口命令规则

第一个分区:0-7位,命令的编号,范围是0-255。

第二个分区:8-15位,命令的幻数。

注意:第一个分区个第二个分布主要作用是用来区分命令的。

第三个分区:16-29位表示传递的数据大小。

第四个分区:30-31位代表读写的方向。

00:表示用户程序和驱动程序没有数据传递。 10:表示用户程序从驱动里面读数据。 01:表示用户程序向驱动里面写数据。 11:表示先写数据到驱动里面,然后在从驱动里面把数据读出来。

这四个分区的示例图如下:

img

Linux驱动学习—ioctl接口

4、命令的合成宏与分解宏

4.1 合成宏

在include\uapi\asm-generic\ioctl.h

#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) 注释如下: _IO(type,nr)用来定义没有数据传递的命令 _IOR(type,nr,size)用来定义从驱动中读取数据的命令 IOW(type,nr,size)用来定义从驱动中写入数据的命令 _IOWR(type,nr,size)用来定义输一局交换类型的命令,先写入数据,在读取数据这类命令。 参数: type:表示命令的组成的魔数,也就是8-15位。 nr:表示命令组成的编号,也就是0-7位。 size:表示命令组成的参数传递大小,注意这里不是传递数字,而是传递数据类型,如要传递4字节,就可以写成int.

4.2 分解宏

#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) #define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) #define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) #define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) 注释如下: _IOC_DIR(nr)是分解命令的方向,也就是上面说30-31位的值。 _IOC_TYPE(nr)分解命令的魔数,也就是上面说的8-15位的值。 _IOC_NR(nr)分解命令的编号,也就是上面说的0-7位。 _IOC_SIZE(nr)分解命令的复制数据大小,也就是上面说的16-29位。 参数说明: nr:要分解的命令

5、实验:在应用层使用命令合成宏和命令分解宏

值得注意的是,内核中使用的合成宏和分解宏与应用层使用的是一样的。其实可以用户和内核空间共用的头文件,里面是ioctl命令的构成和头文件。但本实例在应用层演示其使用,所以就不定义共用的头文件了。

#incldue <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> ​ #define CMD_TEST0 _IO("L",0) #define CMD_TEST1 _IO("A",1) #define CMD_TEST2 _IOW("L",2,int) #define CMD_TEST3 _IOR("L",3,int) ​ int main(int argc, char *argv[]) { printf("30-31 is %d\n",_IOC_DIR(CMD_TEST0)); printf("30-31 is %d\n",_IOC_DIR(CMD_TEST3)); printf("8-15 is %d\n",_IOC_TYPE(CMD_TEST0)); printf("8-15 is %d\n",_IOC_TYPE(CMD_TEST1)); printf("0-7 is %d\n",_IOC_NR(CMD_TEST2)); }

Linux驱动学习—ioctl接口

6、实验:驱动层和应用层使用ioctl

6.1 驱动层代码

#include <linux/init.h> #include <linux/module.h>//最基本的文件,支持动态添加和卸载模块 #include <linux/miscdevice.h>//注册杂项设备头文件 #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> ​ #define CMD_TEST0 _IO("L",0) #define CMD_TEST1 _IO("A",1) #define CMD_TEST2 _IOW("L",2,int) #define CMD_TEST3 _IOW("L",3,int) #define CMD_TEST4 _IOR("L",4,int) ​ ssize_t 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; } ​ ssize_t misc_wirie(struct file *file,char __user *ubuf, size_t size, loff_t *loff_t) { char kbuf[64] = {0}; if(copy_form_user(kbuf, ubuf, strlen(kbuf)) != 0) { printk("copy_form_user error\n"); return -1; } printk("kbuf is %s\n",kbuf); return 0; } ​ int misc_open(struct inode *inode, struct file *file) { printk("misc_open \n"); return 0; } ​ int misc_release(struct inode *inode, struct file *file) { printk("misc_release \n"); return 0; } ​ long misc_ioctl(struct file *file, unsigned int cmd, unsigned long value) { int val = 0; switch(cmd) { case CMD_TEST2: printk("LEN ON!\n"); printk("value is %d!!\n",value); break; case CMD_TEST3: printk("LEN OFF!\n"); printk("value is %d!!\n",value); break; case CMD_TEST4: val = 12; if(copy_to_user((int *)value, &val, sizeof(val)) != 0) { printk("copy_to_user error\n");           return -1;             } break; } } struct file_operations misc_fops={ .owner = THIS_MODULE,//owner 指针指向的就是你的模块 .open = misc_open, .release = misc_release, .read = misc_read, .write = misc_write, .unlocked_ioctrl = misc_ioctl }; struct miscdevice misc_dev={ .minor=MISC_DYNAMIC_MINOR,//MISC_DYNAMIC_MINOR动态分配次设备号 .name = "hello_misc", .fops = &misc_fops, }; ​ static int misc_init(void) { int ret; ret = misc_register(&misc_dev); if(ret < 0) { printk("misc register is error \n"); return ret; } printk("misc register is succeed \n"); return 0; } ​ static void misc_exit(void) { misc_deregister(&misc_dev); printk("misc_exit \n"); } ​ module_init(misc_init); module_exit(misc_exit); MODULE_LICENSE("GPL");

6.2应用层ioctl函数

和open read write函数同理,当在应用层代码中调用ioctl接口的时候,其实调用的内核file_operations的unlocked_ioctl结构体成员。

#include <sys/ioctl.h> int ioctl(int fd, int cmd, ...) ; 参数1:设备描述符 参数2:指令,如某一个命令对应驱动层的某一个功能 参数3:可变参数,跟命令有关,传递进入驱动层的参数或者是接收数据的缓存 返回值:成功:返回 0,失败:返回 -1,并设置全局变量 errorno 值

6.3应用层代码

#incldue <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> ​ #define CMD_TEST0 _IO("L",0) #define CMD_TEST1 _IO("A",1) #define CMD_TEST2 _IOW("L",2,int) #define CMD_TEST3 _IOW("L",3,int) #define CMD_TEST4 _IOR("L",4,int) ​ int main(int argc, char *argv[]) { int fd; fd = open("/dev/hello_misc",O_RDWR); if (fd < 0) { perror("open error"); return fd; } while (1) { ioctl(fd,CMD_TEST2,0); sleep(2); ioctl(fd,CMD_TEST3,1); sleep(2); } return 0; }

Linux驱动学习—ioctl接口

6.4 修改应用层代码,使得用到宏IOR

#incldue <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> ​ #define CMD_TEST0 _IO("L",0) #define CMD_TEST1 _IO("A",1) #define CMD_TEST2 _IOW("L",2,int) #define CMD_TEST3 _IOW("L",3,int) #define CMD_TEST4 _IOR("L",4,int) ​ int main(int argc, char *argv[]) { int fd; fd = open("/dev/hello_misc",O_RDWR); if (fd < 0) { perror("open error"); return fd; } while (1) { ioctl(fd,CMD_TEST4,&value); printf("value is %d\n",value); sleep(2); } return 0; }

Linux驱动学习—ioctl接口

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/153121.html

(0)
上一篇 2025-03-05 21:00
下一篇 2025-03-05 21:05

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信