系统调度不过来(重力感应sensor)

来源:互联网 发布:洞主的手工皂淘宝店 编辑:程序博客网 时间:2024/04/30 13:29
 

项目中设计的重力感应驱动调整好之后,装了一款自己喜欢的卡丁车游戏,krazycartracing(konami),使用过后发生突然不能转向了。打印log后发现,手指点触摸屏过多就会出现系统调度不过来,log无法打印。手指点屏幕暂停键后,log一下子打印出来。

为了验证问题,此前在系统级写了一个死线程,每3s打印一个log,当进入游戏界面后,手机点触屏过多后,死线程log也无法打印出来,确认是系统无法调度的问题。

针对该现象,从代码优化上着手,分析可能原因应该出在工作队列上或者是上报事件过多引起的。上报事件相关联的有触屏事件和重力三维事件,这里触屏事件是感应手的中断,应该在合理范围内,检查了下重力三维事件,调低后影响了游戏灵敏度,而且仍然无法解决目前的问题。

重点分析工作事件,重力感应的代码里面使用了shedule_work()函数,该函数主要是将工作加入到系统共享的默认工作队列中,对于这类经常上报的数据为了避免冲突尽量建立单独的工作队列。

通过采用queue_work(p_queue,&my_work)方法后,效果依然不佳,于是检查了触摸屏的代码,触摸屏的代码写的比较复杂,采用的中断方式是request_thread_irq方式,该方式创建的内核进程有较高的优先级,工作在该线程中进行中断处理。中断处理线程拥有较高的优先级,应该比我所建立的工作队列要高,难道是这里出了问题,通过触摸屏代码的分析,在触摸屏处采用了新的中断申请方式并按照重力感应的单独工作队列方式进行处理,编译下载后,新的驱动方式非常出色的完成了游戏任务。

最终问题应该出在触摸屏处理方式上,触屏的大量中断操作,加上本身游戏运行画面中大量专用内核,导致重力感应的工作队列调度不过来,产生了系统假死的现象。

结论:设备驱动程序中经常需要上报数据的设备尽量采用单独创建工作队列的方式进行处理,另外,对于一些偶尔才需要向队列提交的任务可以采用更简单、有效的方法:使用内核提供的共享默认工作队列。

单独创建工作队列的方法:

1声明工作处理函数和一个指向工作队列的指针

void my_func();

struct workqueue_struct *p_queue;

2创建自己的工作队列和工作结构体变量

p_queue=create_workqueue("my_queue"); //创建一个名为my_queue的工作队列并把工作队列的入口地址赋给声明的指针

struct work_struct my_work;

INIT_WORK(&my_work , my_func , &data); //

3将工作添加入自己创建的工作队列等待执行

queue_work(p_queue,&my_work);

4删除自己的工作队列

destroy_workqueue(p_queue); //一般是在close函数中删除

原创粉丝点击