免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3878 | 回复: 12
打印 上一主题 下一主题

周日回来加班,小声问个关于workqueue问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-02-19 09:14 |只看该作者 |倒序浏览
       linux驱动里面使用create_singlethread_workqueue建立了一个单线程workqueue, 然后在中断处理函数中使用queue_work函数把任务放到workqueue中处理,但任务出来的速度比较慢,而中断的速度比较快,想问下这样长时间下会不会引起workqueue的 溢出或者是简单丢掉下任务?
      然后我看ULK中说flush_workqueue函数会等待工作队列中所以挂起的任务执行完成,但我的实践是调用flush后很快就返回了,好像没有去执行挂起的处理,是不是让workqueue丢掉了呢?

论坛徽章:
0
2 [报告]
发表于 2012-02-19 12:20 |只看该作者
linux驱动里面使用create_singlethread_workqueue建立了一个单线程workqueue, 然后在中断处理函数中使用queue_work函数把任务放到workqueue中处理,但任务出来的速度比较慢,而中断的速度比较快,想问下这样长时间下会不会引起workqueue的 溢出或者是简单丢掉下任务?
      然后我看ULK中说flush_workqueue函数会等待工作队列中所以挂起的任务执行完成,但我的实践是调用flush后很快就返回了,好像没有去执行挂起的处理,是不是让workqueue丢掉了呢?

=============================================================

问题的关键在于,你是否会在中断处理函数中提交不同的struct work_struct对象,换句话说是否你在每次中断到来时要执行不同的操作,如果是,work_struct本身有链表机制,极端情形下导致内存分配失败是可能的。但是现实中,很少会在每次中断,比如网卡显示有数据到达时,提交不同的工作节点。如果你的中断处理函数中提交相同工作结点的话,《深入Linux设备驱动程序内核机制》 6.2.5节“提交工作节点queue_work"的叙述是:"(queue_work_on)函数首先检测work->data的WORK_STRUCT_PENDING位有没有被置1,置1的话意味着此前该work已被提交还没有处理,内核禁止驱动程序在一个工作结点还没处理完就再次提交该结点",所以即便中断发生了10次,但是工作结点可能只提交了一个。  简言之,work_queue应该按照要处理的不同任务提交不同节点,而代表相同任务的工作节点只应该出现一次。flush_workqueue使用COMPLETION机制确保所有在该函数调用前提交的节点都会被执行完毕,但是之后提交的节点它就管不着了。

评分

参与人数 1可用积分 +4 收起 理由
瀚海书香 + 4 讲解很到位!

查看全部评分

论坛徽章:
0
3 [报告]
发表于 2012-02-20 09:46 |只看该作者
谢谢,我提交的是相同的work节点,那就是说当工作队列处理不过来的时候丢弃了很多。

论坛徽章:
0
4 [报告]
发表于 2012-02-20 11:10 |只看该作者
楼上的其实也不用担心丢掉的工作节点,因为假设网卡自己数据没丢,你只要提交了一个节点,当被调度执行时还是会给DMA到系统内存中的。这个跟softirq机制差不多:同一件事提交一次就够了。
另外感谢版主加分,呵呵。

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
5 [报告]
发表于 2012-02-20 12:37 |只看该作者
本帖最后由 linuxfellow 于 2012-02-20 12:41 编辑

回复 2# MagicBoy2010
这样举个例子会更清楚:

如果3个中断源(S1,S2,S3)共用一个中断信号: INTn
S1 对应的中断下半部为 tasklet1
S2 对应的中断下半部为  tasklet2
S3 对应的中断下半部为  tasklet2
同一个中断信号其下半部有可能重叠:如中断源 S1/S2通过中断INTn能重叠提交他们的下半部。
但中断源S2/S3其下半部就不可同时提交。在实际实现时最好秉承哪里的问题哪里解决的原则,不完全寄希望于系统,在执行完tasklet2之前屏蔽掉S2/S3,这样interrupt reentry就不会发生,有利于系统的性能提高。


   

论坛徽章:
0
6 [报告]
发表于 2012-02-20 13:10 |只看该作者
这样举个例子会更清楚:

如果3个中断源(S1,S2,S3)共用一个中断信号: INTn
S1 对应的中断下半部为 tasklet1
S2 对应的中断下半部为  tasklet2
S3 对应的中断下半部为  tasklet2
同一个中断信号其下半部有可能重叠:如中断源 S1/S2通过中断INTn能重叠提交他们的下半部。
但中断源S2/S3其下半部就不可同时提交。在实际实现时最好秉承哪里的问题哪里解决的原则,不完全寄希望于系统,在执行完tasklet2之前屏蔽掉S2/S3,这样interrupt reentry就不会发生,有利于系统的性能提高。
============================================================

不错,很好的例子。最后一点,tasklet(softirq的一种)在执行时属于中断上下文, in_interrupt(), 所以tasklet在执行时,不会有reentry的问题。

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
7 [报告]
发表于 2012-02-20 13:24 |只看该作者
回复 6# MagicBoy2010
是的, softirq不会reentry. 我的本意是:在tasklet2执行完之前,INTn不要再被S2/S3触发,s2/s3中断的前半部也不应该发生。因为即使触发了,其下半部也会被忽略,白白增加系统中断负担。
   

论坛徽章:
0
8 [报告]
发表于 2012-02-20 13:38 |只看该作者
本帖最后由 MagicBoy2010 于 2012-02-20 13:40 编辑

是的, softirq不会reentry. 我的本意是:在tasklet2执行完之前,INTn不要再被S2/S3触发,s2/s3中断的前半部也不应该发生。因为即使触发了,其下半部也会被忽略,白白增加系统中断负担。
==================================================================
事实上在整个tasklet执行过程中,内核都是将外部中断打开的,所以tasklet执行时,是允许外部中断进来的。你的说法恰好违反了softirq的本意,因为s2/s3的前半部分极大的可能是会重新提交一个tasklet,虽然这次的中断不会导致reentry正在执行的tasklet,但是tasklet在执行时会重新检查有无新的tasklet正在被加入(pending), 具体代码框架:

__do_softirq(void)
{
    ...
restart:
     ...
     do{
     ..
     }while(pending);
   
    pending = local_softirq_pending(); //重新检查有无新的softirq pending...
    if(pending && --max_restart)
       goto restart;

论坛徽章:
0
9 [报告]
发表于 2012-02-20 13:52 |只看该作者
除非出于保护系统共享资源的需要,系统应该尽可能地开放响应外部中断的能力,否则会带来很多问题。这也是为什么Linux内核有hardirq和softirq的主要原因。

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
10 [报告]
发表于 2012-02-21 08:04 |只看该作者
本帖最后由 linuxfellow 于 2012-02-21 08:05 编辑

回复 9# MagicBoy2010
只屏蔽S2/S3中断源,其他中断都开放;如果S2/S3再次发生中断, 只能执行前半部没有任何意义。屏蔽S2/S3对其他中断没有任何影响。


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP