【Linux 驱动开发】1-正点原子 第五十章 Linux 内核定时器实验的一些疑问
疑问1: 宏定义中的 _IO 和 0xEF 有什么用?
1 #define CLOSE_CMD (_IO(0XEF, 0x1)) /* 关闭定时器 */ 2 #define OPEN_CMD (_IO(0XEF, 0x2)) /* 打开定时器 */ 3 #define SETPERIOD_CMD (_IO(0XEF, 0x3)) /* 设置定时器周期命令 */
疑问2:timer 设备结构体中定义的 spinlock_t lock; /* 定义自旋锁 */ 有什么用?
疑问3: return -EINVAL; 中的-EINVAL是什么意思?
疑问4:在 xxx_open 中的,将timerdev 赋值给 filp->private_data 有什么用?timerdev 不是全局变量吗?
static int timer_open(struct inode *inode, struct file *filp) { int ret = 0; filp->private_data = &timerdev; /* 设置私有数据 */ timerdev.timeperiod = 1000; /* 默认周期为1s */ ret = led_init(); /* 初始化LED IO */ if (ret < 0) { return ret; } return 0; }
疑问5:为什么 fops 结构体中,成员是 unlocked_ioctl 而不是 ioctl 呢?
1 static struct file_operations timer_fops = { 2 .owner = THIS_MODULE, 3 .open = timer_open, 4 .unlocked_ioctl = timer_unlocked_ioctl, 5 };
疑问6:(本人尝试写的代码)目的是在定时器处理函数中实现 LED 翻转,请分析其逻辑错误
提示:stat 应该定义为 static int stat = 0;
疑问7:为什么一定要用 xxx_ioctl() ,为什么不用原来的 xxx_write() 呢?
疑问8:Makefile 中已经定义 ARCH 和 CROSS_COMPILE ,为什么直接使用 make 命令会出错,使用 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 才能正确地 make 出来?
疑问9:我的 Buffer I/O error on dev mmcblk0, logical block 0, async page read 问题 至今仍然没有解决,开启linux系统浪费需要大量的时间在这上面。
回答疑问7:ioctl 与 write 的不同:
参考文章1
参考文章2
行为上:
ioctl是iocontrol的缩写,就是IO控制。
简单来说,如果你在写驱动程序时候,碰到一些IO操作,在逻辑上不能归类到read,不能归类到write,那就可以认为是ioctl的部分。其操作大多与IC的控制寄存器有关。
比如:串口的波特率、串口的流控方法(xon/xoff、DTR/DSR、RTS/CTS)等等,一般不
用来传递“主要的”数据,一般用put_user/get_user传递单个数据,不用copy_from_user与copy_to_user*
read和write应该是写入和读出数据的,应该是作为单纯的数据交换的方式来处理。而ioctl则是控制read和write一些选项的。比如:你做了一个通用的读写IO端口的驱动模块。read和write是从端口读写数据的,但是更改读写的端口,这个操作应该如何处理呢?显然用ioctl来实现比较合理。比如你的read和write是可以阻塞的,或者不能阻塞的,或者对设备文件的读写是可以并发的,或者是不可以并发的,这些都可以写成可以用ioctl来配置的情况。后面为了可以用ioctl来实现模块不同的IO特点。
从函数参数上来讲,两者不同:
ioctl的一般参数格式就是命令字(常量)+命令参数的方式。
read和write的参数格式都是数据缓冲区+数据目的地指针+长度。
static ssize_t xxx_write (struct file *flip, const char __user * buf, size_t cnt, loff_t *offt)