|
关于linux外部中断,定时器,等对队列的问题
[复制链接]
我写了一个linux的中断驱动,驱动功能是利用DECLARE_WAIT_QUEUE_HEAD()申请了等对队列。在read()函数中用wait_event_interruptible()使程序等待外部中断的到来,中断处理函数的主要功能是用wake_up_interruptible()使程序继续运行下去。但是在测试程序中我使用了信号SIGALRM,以及setitimer()设置了一个定时器,目的是为了每隔一段时间利用定时器的中断处理函数向一个文件中写入一个固定变量的值。在我用实验板测试的时候发现每当到达设定时间后,处理完定时器中断处理函数,之后会自动使驱动使用的等待队列被唤醒,虽然这时候我没有引起外部中断。
还是把代码贴一下吧,可能我讲的不够详细。
/*中断驱动程序*/
/*read()函数*/
static ssize_t my_read(struct file *filp, char * buf, size_t count, loff_t *f_pos)
{
static int value;
wait_event_interruptible(key_wait, ready == 1);
if(count != sizeof(key_value))
return -EINVAL;
value = key_value;
copy_to_user(buf, &value, sizeof(value));
ready = 0;
return sizeof(value);
}
/*中断处理函数*/
static DECLARE_WAIT_QUEUE_HEAD(key_wait);
static void key_irq_handle(int irq, void *dev_id, struct pt_regs *reg)
{
struct key_info *key;
key = key1;
key_value = key->key_num;
ready = 1;
wake_up_interruptible(&key_wait);
}
/*这里的key_info是一个自己定义的结构体,用于返回一些信息*/
static struct key_info
{
int irq_num;
unsigned int gpio_port;
int key_num;
} key1[1] =
{
{ IRQ_EINT4, GPIO_F4, 1 },
};
/*测试程序*/
main()
{
……………………
/*设定闹钟*/
act.sa_handler = savefile;
sigemptyset(&act.sa_mask);
act.sa_flags |= SA_RESTART;
if (sigaction(SIGALRM, &act, &oact) < 0)
{
perror("sigaction\n");
exit(1);
}
savetime.it_value.tv_sec = 5;
savetime.it_value.tv_usec = 0;
savetime.it_interval.tv_sec = 5;
savetime.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &savetime, &ovalue);
for(i = 0; i < 20; i++)
{
/*我希望当我没有提供外部中断的时候,程序会停在这里,定时器返回后程序也会停在这里,但是结果是read()返回值是1,也就是说等待队列被唤醒,驱动中read()函数继续运行了,在这里跳入了else中,输出了一些信息,但是这些信息是我希望在提供外部中断信号之后才显示的*/
result = read(fd2, &key_value, sizeof(key_value)) == sizeof(key_value);
usleep(700000); //按键防抖
if (!result)
{
if (errno == EINVAL)
{
printf("Wrong size!\n");
break;
}
}
else
{
/*打印一些信息*/
}
}
}
/*定时器中断处理函数*/
int savefile()
{
struct rainfall raindata1 = {2009, 7, 11, 2, 12,23,0};/*自己定义的结构体,在存储时使用,主要内容是当前时间,和一个变量值*/
get_sys_time(&raindata1);/*因为要存储当前系统时间,所以使用了该函数*/
file_write("/tmp/sd/rainfall.dat", raindata1);/*自己编写的简单的文件存储程序*/
return 1;
}
遇见这个问题之后,查了很多东西,我有几种想法,但是好像用来解决问题都没有用,说出来希望大家帮我分析分析是否正确。
第一,看了《Unix环境高级编程》里面的第10章,里面有提到信号会中断系统调用,是不是和这个问题有关系。由于被信号中断而重新启动了该系统调用,如果是这样的话,但是为什么程序会继续运行下去。
第二,看了《linux kernel development》相关内容,对于等待队列和工作队列不太明白,不知道两个是不是同一个概念。如果是一个概念,书中说内核态有一个默认的工作队列,而且我没有新建另外一个,那么驱动中read()和定时器中断处理函数是不是都挂在了同一个等待队列上,在定时器到时后激活等待队列,等待队列处理完队列上所有工作后才返回,所以才造成这个现象。
我是第一次发帖,我也是刚开始接触嵌入式和linux的新手,问题和想法还比较低级,不过希望有人可以帮我解答,或者想想办法,谢谢!
|
|