实验现象
使用Alinux官方提供的驱动和应用程序代码,petalinux工程基于自身需要进行了一定的修改(主要是SD卡根文件系统)。在把petalinux工程编译后打包的boot.scr、BOOT.BIN、image.ub放入FAT分区,把驱动程序与应用程序放在NFS共享路径中,运行后的结果如下:
在运行应用程序后,按下按键,直接就release,退出了进程,并在最后打印了I/O possible。
问题分析与解决
从I/O possible入手,经过查询,其表示设备现在处于可以进行I/O操作的状态。这通常是由驱动程序或硬件状态改变触发的,比如设备完成了一个先前的操作,或者设备的电源/连接状态已经稳定。也确实是在我们按下按键以后才出现的,合理推断,系统捕捉到了按键的输入,但由于驱动或应用程序的问题,导致了这个结果。
Alinx教程这一章讲的是异步IO,在其中强调,对信号的处理有三种方式:忽略,系统默认的处理与用户自定义的方式,而对于第二种,几乎都是终止进程或者暂停进程。从这个角度继续切入找一下驱动与应用程序有关信号的部分。
在驱动中的定时回调函数中,给应用层发送了信号,代码如下:
void timer_function(struct timer_list *timer)
{
alinx_char.key_state = 1;
if(alinx_char.fasync_p)
{
kill_fasync(&alinx_char.fasync_p, SIGIO, POLL_IN);
}
}
特别注意的是,驱动给应用层发送的是SIGIO信号。
再看看应用程序,设计内容如下:
signal(SIGUSR2, sigio_signal_func);
fcntl(fd_key, F_SETOWN, getpid());
flag = fcntl(fd_key, F_GETFL);
fcntl(fd_key, F_SETFL, flag | FASYNC);
第一行,应用层把信号的回调函数sigio_signal_func绑定给了SIGUSR2信号,用户信号。
那问题也就显而易见了,驱动与应用所使用的信号不是一个信号!所以只需要把驱动的信号改为SIGUSR2或者把应用程序的信号改为SIGIO就行了。
我这里改的是应用层,最后的结果如下:
此时已经可以按照预期的设计,根据按键翻转PS端LED。