unlock_ioctl函数
它是驱动程序中fops结构体的一个与应用层通讯的函数指针之一。使用Ioctl可以向驱动程序发送控制信号,而不必向之前我们写的程序一样通过read,write函数进行读写指针中的命令。
在驱动fops结构体的函数指针定义为。 filp是对应的设备文件,cmd 是应用程序发送过来的命令信息,arg 是应用程序发送过来的参数
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
其中cmd,通过查看别人定义的cmd,如下。__IOR是读IO ; __IOW是写IO;__IORW是写IO; 类型有很多。在ARM架构下cmd是14位的数据,由四个字段组成---幻数,序数,传输方向,数据大小。
#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
在应用层中接口为
int ioctl(int d, int request, ...);
一、驱动程序
在驱动程序中定义IO的命令,在驱动中也要定义同样的指令进行传输。
本次实验测试三个指令:
打开定时器,关闭定时器,以及修改定时器的值。
因此在定时器处理函数中要求不可以设置绕回函数。
#define TIMER_CLOSE _IO(0xEF, 1)
#define TIMER_OPEN _IO(0xEF, 2)
#define TIMER_SET_PERIOD _IOW(0xEF , 3 , int)
/*
Timer中断处理函数
*/
static void timer_handler(unsigned long dummy){
static int i = 0;
struct timer_dev *dev = (struct timer_dev*)dummy;
printk("i = %d \r\n" , i++);
}
long timer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
int value = 0;
int ret = 0;
struct timer_dev *dev = (struct timer_dev *)filp->private_data;
switch(cmd){
case TIMER_CLOSE:
del_timer(&dev->timerdev);
break;
case TIMER_OPEN:
mod_timer(&dev->timerdev , jiffies + msecs_to_jiffies(dev->timeperiod));
break;
case TIMER_SET_PERIOD:
ret = copy_from_user(&value , (int *)arg , sizeof(int));
if(ret < 0){
return -EFAULT;
}
dev->timeperiod = value;
mod_timer(&dev->timerdev , jiffies + msecs_to_jiffies(dev->timeperiod));
break;
}
return 0;
}
static const struct file_operations timer_fops = {
.owner = THIS_MODULE,
.open = timer_open,
.release = timer_release,
.read = timer_read,
.write = timer_write,
.unlocked_ioctl = timer_ioctl,
};
/* 5.初始化定时器 */
init_timer(&timer.timerdev);
timer.timeperiod = 1000;
timer.timerdev.expires = jiffies + msecs_to_jiffies(timer.timeperiod); //定时1s
timer.timerdev.function = timer_handler;
timer.timerdev.data = (unsigned long)&timer;
add_timer(&timer.timerdev); //添加到系统
二、应用测试程序
#define TIMER_CLOSE _IO(0xEF, 1)
#define TIMER_OPEN _IO(0xEF, 2)
#define TIMER_SET_PERIOD _IOW(0xEF , 3 , int)
int main(int argc, char *argv[])
{
int timer_fd = 0 ,led_fd = 0, ret = 0 ;
//int tmp = atoi(argv[1]);
char read_buff[1] , write_buff[1];
unsigned int cmd;
unsigned int arg;
unsigned char str[100];
timer_fd = open("/dev/timer" , O_RDWR);
if(timer_fd < 0){
printf("打开KEY设备结点失败\n");
return -1;
}
while(1){
printf("Input Cmd!\r\n");
ret = scanf("%d" ,&cmd );
if(ret != 1){
fgets(str , sizeof(str) , stdin);
}
if(cmd == 1)
ioctl(timer_fd , TIMER_CLOSE , &arg);
else if (cmd == 2)
ioctl(timer_fd , TIMER_OPEN , &arg);
else if (cmd == 3){
printf("Please set timer period\r\n");
ret = scanf("%d" , &arg);
if(ret != 1){
fgets(str , sizeof(str) , stdin);
}
ioctl(timer_fd , TIMER_SET_PERIOD , &arg);
}
}
close(timer_fd);
return 0;
}
\