在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 幻数相关推荐

  1. linux下i2c设备驱动程序,Linux I2C 设备驱动

    I2C 设备驱动要使用 i2c_driver 和 i2c_client 数据结构并填充其中的成员函数.i2c_client 一般被包含在设备的私有信息结构体yyy_data 中,而 i2c_drive ...

  2. linux iic 设备驱动,linux IIC设备驱动.doc

    linux IIC设备驱动 //---------------IIC的linux驱动------------------#include #include #include #include #inc ...

  3. linux nand 驱动,Linux NAND FLASH驱动分析(一)

    最近一直在忙着工作上的事情,好久都没有更新博客了,发现最近思想是比较混乱的.学任何东西都坚持不下去,既然选择驱动开发这条路就要坚持下去. 之前分析了Linux块设备驱动,是以内存块来模拟的虚拟块设备. ...

  4. tl-wn821n无线网卡驱动 linux,tl-wn821n win10驱动

    TL-WN821N是TP-link推出的一款无线USB网卡,采用11N无线技术,无线速率最高达到300Mbps,适用于台式PC机等设备进行wifi无线连接,不过现在很多台式机都没有安装光驱了,导致无法 ...

  5. Linux绘图函数与驱动,Linux中与驱动相关的ioctl函数

    一:    ioctl函数的作用 ioctl用于向设备发控制和配置命令 ,有些命令也需要读写一些数据,但这些数据是不能用read/write读写的,称为Out-of-band数据.也就是说,read/ ...

  6. [linux驱动]linux块设备学习笔记(二)

    1,gendisk结构体 在linux内核中,使用gendisk结构体来表示一个实际的磁盘设备的抽象,结构体定义如下所示: [cpp] view plaincopy struct gendisk { ...

  7. linux 怎样查看设备信息,Linux查看设备信息命令

    系统 #查看内核/操作系统/CPU信息 uname -a #查看操作系统版本 head -n 1 /etc/issue #查看CPU信息 cat /proc/cpuinfo #查看计算机名 hostn ...

  8. linux tty设备号,linux tty设备

    /dev/console是什么 如果系统中存在多个tty设备,想象一下,这时内核启动的log应该打印在哪里,这时内核会从tty中选择一个最合适的作为console,当然内核启动参数中也可以明确的去指定 ...

  9. Linux中不同MTD设备分区,Linux MTD设备总结

    1 flash如何分区? 见内核配置与编译 系统启动后,在dev目录下,/dev/mtd0,1,2等代表char型设备,mtd0代表flash的第一分区,依次类推:/dev/mtdblock0,1,2 ...

最新文章

  1. BERT+CRF的损失函数的研究
  2. Calc3: Vector Fields
  3. java面向对象基础复习
  4. THINKPHP3.2+PHP5.3 配置MEMCACHE
  5. 事件总线知多少(2)
  6. 冒泡排序c java c,冒泡排序,c语言冒泡排序法代码
  7. php的慢查询,慢查询是什么
  8. win7系统下装ubuntu系统
  9. 830计算机软件综合大纲,2019年中国地质大学830计算机软件综合考试大纲.pdf
  10. 使用多种算法挖掘Alexa域名数据
  11. Windows设备场景函数 - GetDC Ex
  12. stm32f4定时器时钟频率/选择
  13. Android电池信息的获取
  14. keil 对于 ERROR: FILE DOES NOT EXIST错误的解决办法
  15. RecyclerView的使用(二):添加头部和尾部
  16. misra c编码规范个人整理总结/misra c 2012中文版-个人总结-【方便查询】
  17. mysql查找语句报错_MYSQL报错注入-WEB资讯专栏-DMOZ中文网站分类目录-免费收录各类优秀网站的中文网站目录....
  18. SqlServer geometry 转 geography
  19. 商品价格变化监控记录方法
  20. android ble蓝牙接收不到数据_Android BLE蓝牙开发-读写数据 获取UUID

热门文章

  1. Ae效果控件快速参考:抠像
  2. 零基础如何入门嵌入式领域
  3. 7个技巧帮助你进行更有吸引力的脉动/脉搏调查
  4. Java AQS的实现原理(大部分同步类都依赖AQS实现)
  5. 如何用计算机将图片整成手绘画,【新手教程】如何将手绘作品转变成电子档,并让其更像“作品”?...
  6. 雷迪9000使用说明_雷迪RD8100PXL操作说明
  7. 为什么任何数的0次方都是1
  8. IMU让无人机控制变得更轻松
  9. 香河哪有学计算机编程,香河计算机程序设计员职业资格证书
  10. TC358774XBG/TC358775XBG替代方案|CS5518替代TC358774XBG/TC358775XBG设计DSI转LVSD设计资料