IO机制vs下半部机制vs并发控制机制_第1页
IO机制vs下半部机制vs并发控制机制_第2页
IO机制vs下半部机制vs并发控制机制_第3页
IO机制vs下半部机制vs并发控制机制_第4页
IO机制vs下半部机制vs并发控制机制_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

IO机制vs下半部机制vs并发控制机制Jet.chenJet.chen.g@目录预备知识三种机制的比较下半部机制并发控制机制汇总驱动IO机制汇总FAQ预备知识1.三种线程:内核线程、轻量级进程、用户线程内核线程:kthread_create()轻量级进程:clone()用户线程:Pthread_create()2.一种进程:用户进程linux普通应用:API:fork/vfork/clone/Linux中,每个XX都有一个task_struct,所以线程和进程可以使用同一调度器调度。因为Linux中进程的概念已经被抽象成了计算状态加资源的集合,这些资源在进程间可以共享。

为何要区分?使用资源和同步效率,调度开销等都不一样。知识预备-进程上下文和中断上下文概念描述什么时候发生进程上下文主要是异常处理程序和内核线程。内核之所以进入进程上下文是因为进程自身的一些工作需要在内核中做。例如,系统调用是为当前进程服务的,异常通常是处理进程导致的错误状态等。所以在进程上下文中引用current是有意义的。进程调度;系统调用;中断上下文是因为中断信号而导致的中断处理或软中断。而中断信号的发生是随机的,中断处理程序及软中断并不能事先预测发生中断时当前运行的是哪个进程,所以在中断上下文中引用current是可以的,但没有意义。事实上,对于A进程希望等待的中断信号,可能在B进程执行期间发生。例如,A进程启动写磁盘操作,A进程睡眠后现在时B进程在运行,当磁盘写完后磁盘中断信号打断的是B进程,在中断处理时会唤醒A进程。

发生中断;

为什么在中断上下文中不能休眠?原因在于中断上下文不是一个进程上下文,其没有一个专门用来描述CPU寄存器等信息的数据结构,所以无法被调度器调度。如果将中断上下文也设计成进程上下文,那么调度器就可以对其进行调度,如果在开中断的情况下,其自然就可以睡眠了。但是,如果这样设计,那么中断处理的效率将会降低。中断(硬中断、软中断)处理都是些耗时不是很长,对实时性要求很高,执行频度较高的应用,所以,如果采用一个专门的后台daemon对其处理,显然并不合适。三种机制的比较机制描述种类实现下半部机制

由下到上的

通知机制;软中断,工作队列,tasklet,内核定时器等;同步/异步IO机制

是由上到下(或者驱动程序自发)的

IO通信机制。分为阻塞IO(异步)与非阻塞IO(同步)

等待队列,poll,epoll,Completions机制等并发控制机制提供并发控制机制,对共享资源进行保护。spinlock,mutex,信号量,中断屏蔽、顺序锁(seqlock)、RCU(Read-Copy-Update)等在编程中

往往三者互相使用:

比如

hwm_sensor的驱动:用到(内核定时器+工作队列+mutex取决于

项目设计的需要。)Mtklogdump:就用到poll+等待队列下半部机制机制是否在进程上下文是否在中断上下文可否睡眠是否需要内核线程性能CPU的支持特性是否需要调度应用场合软中断

yesYesNo可有可无,取决于调用时机高1)一个类型的软中断可以执行在多个CPU;2)并发运行在多个CPU上(即使同一类型的也可以)。所以软中断必须设计为可重入的函数(允许多个CPU同时操作),因此也需要使用自旋锁来保护其数据结构。YES考虑因素:多CPU;不可睡眠,不可阻塞;软中断是在编译期间静态分配;系统开销相对小;设计难度高;适合执行频率高和连续性执行要求高的情况,性能较高;应用:目前只有两个子系直接使用软中断:网络和SCSI。

例如在网络子系统中,注册了如下两个softirq及其处理函数:open_softirq(NET_TX_SOFTIRQ,net_tx_action);--注册softirqopen_softirq(NET_RX_SOFTIRQ,net_rx_action);--触发softirq

taskletyesYESNO可有可无,取决于调用时机中1)一个类型的tasklet只能执行在单个CPU;不能并行,只能串行执行。

2)多个不同类型的tasklet可以并行在多个CPU上。

YES考虑因素:单CPU;不可睡眠,不可阻塞;动态分配;系统开销相对小;设计难度小;适合执行频率低,连续性要求低的情况下;性能中;应用:TP,键盘,鼠标。大部分设备驱动都使用它。下半部机制工作队列YESNOYESYES低1)每个工作队列(仅限于MT)都会在每一个cpu上创建一个内核线程。2)一个工作队列可以在不同CPU上同时运行。YES考虑因素:多CPU;可睡眠,可阻塞;动态创建;系统开销大;设计难度小;适合执行频率低,连续性要求低的情况下;需要考虑使用进程上下文的情况(信号,消息,内存申请等);性能低;应用:LED灯光控制;

内核定时器noyesNOno较低同

软中断,实际上是一个软中断种类:TIMER_SOFTIRQ

yes考虑因素:需要在某段时间内执行的情况下使用;只执行一次;应用:软件定时器在设备驱动程序中被大量应用以检测设备的状态。

触屏中断检测防抖动功能;init_timer()Add_timer();Mod_timer();….

并发控制机制汇总From网络并发控制机制汇总补充:1.顺序锁(seqlock),RCU,也称为

多核情况下,linux的无锁编程算法)2.各种锁,互斥量的实现基础都是依靠原子操作完成。

semaphore又是在spinlock基础上实现。3.Mutex比较semaphoreLinux驱动IO机制汇总序列概念描述通知方式"实现方式应用层次应用实例1阻塞:是指进程在执行设备操作时,若不能获得资源,则挂起进程直到满足可操作的条件后再进行操作。注意:被挂起的进程会进入休眠状态,它将被从调度器的运行队列移走。可以由其他程序来唤醒被阻塞的队列。Wait_event(&waiter)等待队列内核充电线程内;lcd刷屏;…..2异步通知:由设备通知进程可以访问,实现异步的IO。有点类似阻塞IO。适当的时候驱动程序调用kill_fasync()函数,使用信号SIGIO通知应用程序,设备准备就绪,可以执行IO操作了。file_operations结构体中实现:Fasync_struct结构体内核+应用配合ccci;Audiodriver;3非阻塞IO:当进程在不能进行设备操作时,并不挂起,它或者放弃,或者不停的查询,直到可以进行操作为止。应用自己决定什么时候放弃;POLL,Epoll,select,内核+应用层;应用层;Mtklog;Logdump应用;4异步IO(AIO):也叫做异步I/O(AIO),用户程序可以通过向内核发出I/O请求命令,不用等带I/O事件真正发生,可以继续做另外的事情,等I/O操作完成,通知方式:内核会通过函数回调或者信号机制通知用户进程。这样很大程度提高了系统吞吐量。

1)Vs非阻塞IO:非阻塞IO中,如果设备资源不可用,则驱动程序返回EAGAIN,应用程序需要在适当的时候进行重试,直到资源可用,IO请求成功执行。而使用异步IO时,如果设备资源不可用,IO请求会排队等待处理,驱动程序返回EIOCBQUEUED,应用程序不需要进行重试。

2)VS异步通知共同点:这两种机制都有这样一共通点:都可以在驱动层使用信号来通知应用层的程序做相应的I/O操作。在AIO中,可以使用信号和回调函数是实现内核空间对用户空间应用程序通知的两种机制。

差异点:与异步通知相比较,异步通知强调的是设备就绪后,驱动程序主动通知应用程序。强调的是应用程序处于被动的一面。AIO强调的多次操作后查询结果。概念本身有交叠的地方。可以使用信号和回调函数是实现内核空间对用户空间应用程序通知file_operations结构体中实现:

aio_read()aio_write()等等

加上GNUC库支持内核+应用配合mtk的xlogFAQ1。linux内核打印"BUG:schedulingwhileatomic"和"bad:schedulingfromtheidlethread"错误的时候,通常是在中断处理函数中调用了可以休眠的函数,如semaphore,mutex,sleep之类的可休眠的函数,而linux内核要求在中断处理的时候,不允许系统高度,不允许抢占,要等到中断处理完成才能做其他事情。因此,要充分考虑中断处理的时间,一定不能太久Internalerror:Oops-BUG:0[#1]PREEMPTSMPARM原因就是mutextlock时间太长,导致的。例如:[154.941700]-([154.942751]-(0)[43:kworker/u:1][<c03c8e5c>](aee_wdt_irq_info+0x0/0x154)from[<c03c9070>](aee_wdt_fiq_info+0xc0/0xd0)[154.944090]-(0)[43:kworker/u:1]r9:c08f5fc0r8:00000096r7:00000000r6:00000000r4:00000000[154.945139]-(0)[43:kworker/u:1][<c0653688>](mutex_lock_nested+0x0/0x568)from[<c044d940>](synaptics_rmi4_i2c_read+0x60/0x290)[154.946582]-(0)[43:kworker/u:1][<c044e5bc>](synaptics_rmi4_sensor_wake+0x0/0x98)from[<c044e890>](synaptics_rmi4_resume+0x30/0xe0)[154.949603]-(0)[43:kworker/u:1]r6:00000000r5:c080365cr4:c092af20[154.950390]-(0)[43:kworker/u:1][<c044e860>](synaptics_rmi4_resume+0x0/0xe0)from[<c00b76d8>](late_resume+0x184/0x1b8)[154.951740]-(0)[43:kworker/u:1]r7:0000000br6:c0982198r5:c09ddec0r4:c092af20/u:1][<c00b7554>](late_resume+0x0/0x1b8)from[<c006af38>](process_one_work+0x1bc/0x58c)[154.953969]-(0)[43:kworker/u:1][<c006ad7c>](process_one_work+0x0/0x58c)from[<c006b494>](worker_thread+0x18c/0x3d8)[跟踪到这里:mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex));触发内核异常//oldsize=4096nowchangeto2048

gprDMABuf_va=(u8*)dma_alloc_coherent(NULL,4096,&gprDMABuf_pa,GFP_KERNEL);

if(!gprDMABuf_va){printk("[Error]AllocateDMAI2CBufferfailed!\n");

}发现这个rmi4_io_ctrl_mutex的数值

前后不一致,说明或者传入有问题,或者取数据时候有问题。首先私有数据rmi4_data与dev的绑定:FAQstaticintsynaptics_rmi4_set_input_dev(structsynaptics_rmi4_data*rmi4_data){intretval;inttemp;rmi4_data->input_dev=input_allocate_device();……………..input_set_drvdata(rmi4_data->input_dev,rmi4_data);是一个input设备类型}

staticintsynaptics_rmi4_resume(structdevice*dev){intretval;structsynaptics_rmi4_exp_fhandler*exp_fhandler;//structsynaptics_rmi4_data*rmi4_data=dev_get_drvdata(dev);----不能这样取数据修改为://modifedbyjetinhuaqin,fordataerror.exeple:mutexdataerror,willcausesystemdeadlockstructinput_dev*input_raw=to_input_dev(dev);structsynaptics_rmi4_data*rmi4_data=input_get_drvdata(input_raw);4.工作队列中能否使用等待队列???FAQstaticintsynaptics_rmi4_set_input_dev(structsynaptics_rmi4_data*rmi4_data){intretval;inttemp;rmi4_data->input_dev=input_allocate_device();……………..input_set_drvdata(rmi4_data->input_dev,rmi4_data);是一个input设备类型}

staticintsynaptics_rmi4_resume(structdevice*dev){intretval;structsynaptics_rmi4_exp_fhandler*exp_fhandler;//structsynaptics_rmi4_data*rmi4_data=dev_get_drvdata(dev);----不能这样取数据修改为://modifedbyjetinhuaqin,fordataerror.exeple:mutexdataerror,willcausesystemdeadlockstructinput_dev*input_raw=to_input_dev(dev);structsynaptics_rmi4_data*rmi4_data=input_get_drvdata(input_raw);4.工作队列中能否使用等待队列???FAQstaticvoid

hwmsen_work_func(structwork_struct*work){。。。。。。。。。。。。。#ifdefHQ_SENSORif((isCameraActive==1)&&((idx==ID_MOTION)||(idx==ID_LIGHT)||(idx==ID_PROXIMITY)||(idx==ID_FACE_DETECT))){HWM_ERR("donotreaddatafromsensor(%d)\n",idx);HWM_ERR("cameraisACTIVE,setthethreadintoWAITstatus\n");wait_event_interruptible(hi164_wq,(hi164_wq_flag==KAL_FALSE));//restarthi164toothermode5.软中断回调里面之后加mutexordeley等

会报出异常:比如内核定时器里面使用mutex。::软中断跑在swapper线程的内核栈空间:【c08bf890:c00119c4】]Backtrace:[52.113934](0)[0:swapper/0][<c00119c4>]save_stack_trace_tsk+0x0/0x98[52.113946](0)[0:swapper/0][<c03c7fc4>]aee_get_traces+0x60/0xc0[52.113957](0)[0:swapper/0][<c03c80b8>]aee_kernel_warning_api+0x94/0xe0[52.113970](0)[0:swapper

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论