linux3.0字符设备驱动,linux字符设备驱动的 ioctl 幻数
在Linux字符设备驱动入门(一)中,我们实现了字符设备的简单读写字符功能,接下来我们要在这个基础上加入ioctl功能。首先,我们先来看看3.0内核下../include/linux/fs.h中file_operations结构体的定义:
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
};
红色字体已经标出在kernel 3.0中已经完全删除了struct file_operations 中的ioctl 函数指针,剩下unlocked_ioctl和compat_ioctl,取而代之的是unlocked_ioctl,主要改进就是不再需要上大内核锁 (调用之前不再先调用lock_kernel()然后再unlock_kernel())。
所以,在hellow.c中,我们在file_operations中加入成员函数hello_ioctl(红色字体部分):
/* file operations for hello device */
static struct file_operations hello_ops = {
.owner = THIS_MODULE,
.unlocked_ioctl = hello_ioctl,
.open = hello_open,
.read = hello_read,
.write = hello_write,
.release = hello_release,
};
hello_ioctl()的定义如下:
static int hello_ioctl( struct file *file,
unsigned int cmd, unsigned long arg)
{ int temp = 0;
switch(cmd)
{
case HELLO_CMD1:
{
temp = 1;
if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;
break;
}
case HELLO_CMD2:
{
temp = 2;
if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;
break;
}
}
printk( KERN_NOTICE"ioctl CMD%d done!\n",temp);
return 0;
}
这里强调一下cmd的定义:
#define HELLO_MAGIC 'k'
#define HELLO_CMD1 _IO(HELLO_MAGIC,0x1a)
#define HELLO_CMD2 _IO(HELLO_MAGIC,0x1b)
其中'k'为幻数,要按照Linux内核的约定方法为驱动程序选择ioctl编号,应该首先看看include/asm/ioctl.h和Documentation/ioctl-number.txt这两个文件,下面是ioctl.h的部分内容,也是比较重要的:
_IO(type, nr)
用于构造无参数的命令编号;
_IOR(type, nr, datatype)
用于构造从驱动程序中读取数据的命令编号;
_IOW(type, nr, datatype)
用于写入数据的命令;
_IOWR(type, nr, datatype)
用于双向传输。注意千万不能重复定义。
注意对幻数的编号千万不能重复定义,如ioctl-number.txt已经说明‘k'的编号已经被占用的范围为:
'k' 00-0F linux/spi/spidev.h conflict!
'k' 00-05 video/kyro.h conflict!
所以我们在这里分别编号为0x1a和0x1b,到这里,我们已经完成了对ioctl功能的编写,接下来就是在测试程序中利用系统调用来测试它。
=============================================================
ioctl测试程序
=============================================================
#include
#include
#include
#include
#include
#include
#include
#include
#define HELLO_MAGIC 'k' //当然我们也可以定义一个相应的头文件,把ioctl的cmd放进里面,然后再include进 来
#define HELLO_CMD1 _IO(HELLO_MAGIC,0x1a)
#define HELLO_CMD2 _IO(HELLO_MAGIC,0x1b)
int main(void)
{
int ioctl_rdata;
int fd, ret;
fd = open ( "/dev/hellow" , O_RDWR);
if ( fd == -1 )
{
perror("open");
exit(0);
}
ret = ioctl( fd, HELLO_CMD2,&ioctl_rdata);
if ( ret == -1)
{
perror("ioctl");
exit(0);
}
printf("ioctl_rdata= %d \n",ioctl_rdata);
close(fd);
return 0;
}
=============================================================
运行结果
=============================================================
root@Ubuntu:~/share/hellow# insmod hellow.ko
root@Ubuntu:~/share/hellow# mknod /dev/hellow c 251 0
root@Ubuntu:~/share/hellow# ./a.out
ioctl_rdata= 2
root@Ubuntu:~/share/hellow# dmesg | tail
[ 2431.126532] hello init. major:251, minor:0
[ 2453.326022] Hello device open!
[ 2453.326047] ioctl CMD2 done! [ 2453.326487] Hello device close!
linux3.0字符设备驱动,linux字符设备驱动的 ioctl 幻数相关推荐
- linux下i2c设备驱动程序,Linux I2C 设备驱动
I2C 设备驱动要使用 i2c_driver 和 i2c_client 数据结构并填充其中的成员函数.i2c_client 一般被包含在设备的私有信息结构体yyy_data 中,而 i2c_drive ...
- linux iic 设备驱动,linux IIC设备驱动.doc
linux IIC设备驱动 //---------------IIC的linux驱动------------------#include #include #include #include #inc ...
- linux nand 驱动,Linux NAND FLASH驱动分析(一)
最近一直在忙着工作上的事情,好久都没有更新博客了,发现最近思想是比较混乱的.学任何东西都坚持不下去,既然选择驱动开发这条路就要坚持下去. 之前分析了Linux块设备驱动,是以内存块来模拟的虚拟块设备. ...
- tl-wn821n无线网卡驱动 linux,tl-wn821n win10驱动
TL-WN821N是TP-link推出的一款无线USB网卡,采用11N无线技术,无线速率最高达到300Mbps,适用于台式PC机等设备进行wifi无线连接,不过现在很多台式机都没有安装光驱了,导致无法 ...
- Linux绘图函数与驱动,Linux中与驱动相关的ioctl函数
一: ioctl函数的作用 ioctl用于向设备发控制和配置命令 ,有些命令也需要读写一些数据,但这些数据是不能用read/write读写的,称为Out-of-band数据.也就是说,read/ ...
- [linux驱动]linux块设备学习笔记(二)
1,gendisk结构体 在linux内核中,使用gendisk结构体来表示一个实际的磁盘设备的抽象,结构体定义如下所示: [cpp] view plaincopy struct gendisk { ...
- linux 怎样查看设备信息,Linux查看设备信息命令
系统 #查看内核/操作系统/CPU信息 uname -a #查看操作系统版本 head -n 1 /etc/issue #查看CPU信息 cat /proc/cpuinfo #查看计算机名 hostn ...
- linux tty设备号,linux tty设备
/dev/console是什么 如果系统中存在多个tty设备,想象一下,这时内核启动的log应该打印在哪里,这时内核会从tty中选择一个最合适的作为console,当然内核启动参数中也可以明确的去指定 ...
- Linux中不同MTD设备分区,Linux MTD设备总结
1 flash如何分区? 见内核配置与编译 系统启动后,在dev目录下,/dev/mtd0,1,2等代表char型设备,mtd0代表flash的第一分区,依次类推:/dev/mtdblock0,1,2 ...
最新文章
- BERT+CRF的损失函数的研究
- Calc3: Vector Fields
- java面向对象基础复习
- THINKPHP3.2+PHP5.3 配置MEMCACHE
- 事件总线知多少(2)
- 冒泡排序c java c,冒泡排序,c语言冒泡排序法代码
- php的慢查询,慢查询是什么
- win7系统下装ubuntu系统
- 830计算机软件综合大纲,2019年中国地质大学830计算机软件综合考试大纲.pdf
- 使用多种算法挖掘Alexa域名数据
- Windows设备场景函数 - GetDC Ex
- stm32f4定时器时钟频率/选择
- Android电池信息的获取
- keil 对于 ERROR: FILE DOES NOT EXIST错误的解决办法
- RecyclerView的使用(二):添加头部和尾部
- misra c编码规范个人整理总结/misra c 2012中文版-个人总结-【方便查询】
- mysql查找语句报错_MYSQL报错注入-WEB资讯专栏-DMOZ中文网站分类目录-免费收录各类优秀网站的中文网站目录....
- SqlServer geometry 转 geography
- 商品价格变化监控记录方法
- android ble蓝牙接收不到数据_Android BLE蓝牙开发-读写数据 获取UUID
热门文章
- Ae效果控件快速参考:抠像
- 零基础如何入门嵌入式领域
- 7个技巧帮助你进行更有吸引力的脉动/脉搏调查
- Java AQS的实现原理(大部分同步类都依赖AQS实现)
- 如何用计算机将图片整成手绘画,【新手教程】如何将手绘作品转变成电子档,并让其更像“作品”?...
- 雷迪9000使用说明_雷迪RD8100PXL操作说明
- 为什么任何数的0次方都是1
- IMU让无人机控制变得更轻松
- 香河哪有学计算机编程,香河计算机程序设计员职业资格证书
- TC358774XBG/TC358775XBG替代方案|CS5518替代TC358774XBG/TC358775XBG设计DSI转LVSD设计资料