阅读:1383回复:9
请教内核中的信号灯的问题(高手请进)????!!
如题,俺要做一个驱动,采用DMA方式(plx9054)与PCI卡通讯,现在遇到这样一个问题,即在用户层同时并发1024个进程,而每个进程请求的都是大数据量的运算,我如何实现在驱动中的互斥呢?
我的想法是这样的,即每个进程的每一次数据运算请求都通过ioctl的调用,率先探测当前板卡的DMA通道是否空闲,如果不空闲,则该请求被投入内核的一个FIFO对列中睡眠,直到空闲被唤醒。 问题是: 1.我如果要判断是否空闲,必须判断我自己的设备结构中的一个变量的值,如 mydev->dma0_idle,可是我如何保证我在判断这个值的时候,这个值不会被修改,比如,我正在判断的时候,某个进程的运算结束,最后一次DMA的中断被触发,这时候我肯定要在中断处理程序中(tasklet)将这个 mydev->dma0_idle 重新置位空闲,而此时另外一个进程的请求很有可能正在判断这个值是什么,我如何控制这种情况? 2.上面我说的情况,我听说可以通过内核提供的 semaphore或spinlock来做,可是前者据说不能用于中断环境,我不知道是什么 意识,如果我上面那种情况下用semaphore,不知道算不算中断环境?而后者,据说影响效率,且容易死锁,而且据说用在SMP系统的比较多,所以归根到底还是问题一,我该怎么办???!!! 3.如果我说的要求能使用semaphore,那么听说他可以自己排队等候 那是不是说我不需要自己在内核重新定义一个链表了,只需要用semaphore提供的排队就可以了 呵呵呵呵,问得比较乱,可能理解就有问题,恳请高手体谅初学者,耐心看完,盼复!!!!多谢!!! 另注:千万别光说一句“自己看书!”就拉倒这样的话,俺不是懒人,俺看了很多帖子和资料也没想通,才问得,DX们多少给点提示也好,可能俺悟性太差了吧!! 再次感谢,能回答这个问题的DX |
|
沙发#
发布于:2004-04-20 16:18
非常关注你的话题,我使用semaphore 信号量,运行没有问题,但是好像在处理一些异常时候,有问题。
比如,我应用层一个死循环来测试板卡,如果中断这个程序,可能导致控制台死机,我不得不切换控制台来重新进行测试。 你呢,目前有什么好办法?? |
|
|
板凳#
发布于:2004-04-20 18:03
非常关注你的话题,我使用semaphore 信号量,运行没有问题,但是好像在处理一些异常时候,有问题。 你说的这个问题我怀疑是不是由于你使用了down 而不是down_interruptible()造成的,改成后者试试 |
|
地板#
发布于:2004-04-20 19:19
哎,还是没人理我,我提议下我自己的想法,高手给点建议总可以了吧?
由于我的驱动有可能向SMP系统拓展,并且要与BH或TASKLET打交道,因此我肯定不会用semaphore了 我的想法如下(程序框架来源于我的概要设计): ioctl() { /* I think bh or tasklet can interrupt the ioctl ,so I use spin_lock_bh . But I think spin_lock_bh can not close hard irq .Hard irq do not modify dma0_idle,it just let tasklet or bh do it ,so I think spin_lock_bh is enough */ spin_lock_bh(); if (mydev->dma0_idle) return; /* 1 means dma 0 channel can be used */ spin_unlock_bh(); /* must be unlock before wait*/ wait_event_interruptible(mydev->res_wait,mydev->dma0_idle); return; } bh() { /* I think hard irq will interrupt bh or tasklet ,so I use spin_lock_irqsave */ spin_lock_irqsave(); mydev->dma0_idle = 1; wake_up_interruptible(mydev->res_wait); /* I think it can be used before unlock */ spin_unlock_irqrestore(); } 请DX们注意我上面“I think....”的部分,我认为比较easy,没有翻译过来,直接从我的概要设计里copy过来了,DX们看看我这些地方有什么死锁或无效锁(即无法达到我想要的目的)的潜在问题吗??? 拜托!!急!! |
|
地下室#
发布于:2004-04-20 19:26
更正一个地方,我自己发现设计的有问题了,不过不是根本问题,所以还请DX们继续指点
ioctl中作判断的地方,应该如下: if (mydev->dma0_idle) { /* 1 means dma 0 channel can be used */ mydev->dma0_idle = 0; spin_unlock_bh(); return; } |
|
5楼#
发布于:2004-04-20 23:03
用spin_lock()自已看......源代码.
|
|
6楼#
发布于:2004-04-21 10:10
用spin_lock()自已看......源代码. 我的理解用spin_lock是不行的吧? 应该是spin_unlock_bh 和 spin_lock_irqsave 吧 |
|
7楼#
发布于:2004-04-21 20:15
一年多没用我也记不清了,但是是用spin_lock_irqsave()没错,反正你照着现成的驱动里用就行了.只不过要注意的是,如果因为设计失误引起spin_lock被死锁,那么你的整个系统前台会被完全锁住,从效果上来说与死机没有区别.切记切记.
再一个就是编译的问题,单CPU的spin_lock与SMP的目标代码是完全不同的,所以决不能共用同一个驱动. |
|
8楼#
发布于:2004-04-21 20:24
所谓\"中断环境\",也就是回调过程(call back),linux设计了两种过程,一种是由上到下调用,一种是由下到上,这两种过程通常又叫做\"上半部\"与\"下半部\".上半部用于排队,发送队列,然后休眠等待,而唤醒由下半部即回调过程完成.这就意味着,下半部是从中断程序调用过来的,不能使用任何排斥中断的操作.回调过程可以看作是资源独占过程.
知道了这一点,相信哪里要用什么类型的互斥量就很清楚了吧? |
|
9楼#
发布于:2004-04-22 09:43
多谢多谢!!!
我会尽快作试验来测试各种情况,最后选定一种至少用起来是稳定的方法 |
|