免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: duanjigang

发个简单(易用)的内存池 [复制链接]

论坛徽章:
0
发表于 2010-01-12 10:14 |显示全部楼层
原帖由 Godbach 于 2010-1-12 10:07 发表


呵呵,白金兄这个问题还没有解决啊。

是呀,一直很迷茫,小伟能不能帮我解释一下

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2010-01-12 10:39 |显示全部楼层
原帖由 platinum 于 2010-1-12 10:14 发表

是呀,一直很迷茫,小伟能不能帮我解释一下

很惭愧的说,我也不是很清楚。前段时间还特意为这个问题翻了一下LKD2等相关的书籍。只看到了底半和顶半的区别及应用的场合,感觉看的还是不很明白

论坛徽章:
0
发表于 2010-01-12 13:27 |显示全部楼层
原帖由 platinum 于 2010-1-12 09:49 发表
借这个贴子问一下
段兄为何使用 spin_lock 而不是 spin_lock_bh,什么情况下应该加 _bh 什么时候应该不加呢?

在LDD上翻出来看了看:
spin_lock_bh disables software interrupts
before taking the lock, but leaves hardware interrupts enabled
.
spin_lock_bh通常用在进程中,用来禁止抢断和禁止软中断,所以个人感觉这就跟试用场景有关了
如果你的代码lock和unlock之间访问的资源不会被一个中断处理访问的话,应该就不需要考虑禁止软中断了吧。
那样就直接试用spin_lock,如果代码片段很可能在中断处理中执行或者与中断处理的程序访问同一资源,
就应该调用spin_lock_irq或者spin_lock_bh吧
我的理解大概是这样,再看看别的文章

[ 本帖最后由 duanjigang 于 2010-1-12 13:30 编辑 ]

论坛徽章:
0
发表于 2010-01-12 13:32 |显示全部楼层
原帖由 platinum 于 2010-1-12 10:14 发表

是呀,一直很迷茫,小伟能不能帮我解释一下

对了,你的应用场景是什么??这些API的区别是什么我没仔细研究过,就用过read_lock,write_lock
还有就是这个spin_lock,也没怎么求甚解,借这个机会,大家正好讨论下

论坛徽章:
0
发表于 2010-01-12 13:44 |显示全部楼层
我的应用场景很简单,写基于 netfilter 的 hook 模块,通过 netlink 与 userspace 交互
在内核态工作时,有三个地方需要用到 lock 机制
1、收取 netlink 信令并插入链表
2、hook 中处理数据包时查找链表
3、timer 中 destroy 函数中有删除链表的操作
为了安全起见,我都是用的是 _bh,不知道是不是没必要,段兄这块是怎么做的?

至于 rwlock、spinlock,我一般都是用 spinlock,只有在很多读,很少写的时候才使用 rwlock
但是我看文章说在极大读,极小写的时候可以改用 RCU 锁,但 RCU 的应用场景很复杂,很多种情形,很多种用法,一头雾水……

另一个问题,对于一个 spin_lock 变量,能否在不同地方使用不同的锁
比如

fun1()
{
    spin_lock(&lock);
    do_something();
    spin_unlock(&lock);
}

fun2()
{
    spin_lock_bh(&lock);
    do_something();
    spin_unlock_bh(&lock);
}
同一个锁,一个地方有 _bh,另一个没有?是不是这也和应用场景有关,看是否需要对 local 进行 disable ?

[ 本帖最后由 platinum 于 2010-1-12 13:51 编辑 ]

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2010-01-12 13:46 |显示全部楼层
我们也有类似的应用。前两种都用了_bh

论坛徽章:
0
发表于 2010-01-12 15:29 |显示全部楼层
原帖由 platinum 于 2010-1-12 13:44 发表
我的应用场景很简单,写基于 netfilter 的 hook 模块,通过 netlink 与 userspace 交互
在内核态工作时,有三个地方需要用到 lock 机制
1、收取 netlink 信令并插入链表
2、hook 中处理数据包时查找链表
3、 ...

netfilter的hook点是在softirq的上下文中,参考以下文章,我觉得你的用法至少是足够了,而没有欠缺,如果要采取更确切的
锁操作api, 觉得netlink和timer中的锁操作应该参考下文再分析下(还是结合场景

     至于同一个spin_lock,个人觉得应该可以支持不同的操作,禁softirq或者不禁softirq都行,关键是你要保证lock和unlock的
操作类型是匹配的,也就是说bh_lock了,就要bh_unlock.当然,最好试验下,感觉不顶事。

     白金兄有没有在netlink通讯中遇到用户态Sendmsg时阻塞的情况,有的话,大致是哪些原因???我做一个东西,偶尔会有
这种情况出现,一旦阻塞,再send就一直阻塞,除非重新加载模块,不知道是不是锁使用不当导致的。。。

  看了这文章,我一身冷汗,得赶紧查查我的代码去。
获得自旋锁和释放自旋锁有好几个版本,因此让读者知道在什么样的情况下使用什么版本的获得和释放锁的宏是非常必要的。

如果被保护的共享资源只在进程上下文访问和软中断上下文访问,那么当在进程上下文访问共享资源时,可能被软中断打断,从而可能进入软中断上下文来对被保护的共享资源访问,因此对于这种情况,对共享资源的访问必须使用spin_lock_bh和spin_unlock_bh来保护。当然使用spin_lock_irq和spin_unlock_irq以及spin_lock_irqsave和spin_unlock_irqrestore也可以,它们失效了本地硬中断,失效硬中断隐式地也失效了软中断。但是使用spin_lock_bh和spin_unlock_bh是最恰当的,它比其他两个快。

如果被保护的共享资源只在进程上下文和tasklet或timer上下文访问,那么应该使用与上面情况相同的获得和释放锁的宏,因为tasklet和timer是用软中断实现的。

如果被保护的共享资源只在一个tasklet或timer上下文访问,那么不需要任何自旋锁保护,因为同一个tasklet或timer只能在一个CPU上运行,即使是在SMP环境下也是如此。实际上tasklet在调用tasklet_schedule标记其需要被调度时已经把该tasklet绑定到当前CPU,因此同一个tasklet决不可能同时在其他CPU上运行。timer也是在其被使用add_timer添加到timer队列中时已经被帮定到当前CPU,所以同一个timer绝不可能运行在其他CPU上。当然同一个tasklet有两个实例同时运行在同一个CPU就更不可能了。

如果被保护的共享资源只在两个或多个tasklet或timer上下文访问,那么对共享资源的访问仅需要用spin_lock和spin_unlock来保护,不必使用_bh版本,因为当tasklet或timer运行时,不可能有其他tasklet或timer在当前CPU上运行。如果被保护的共享资源只在一个软中断(tasklet和timer除外)上下文访问,那么这个共享资源需要用spin_lock和spin_unlock来保护,因为同样的软中断可以同时在不同的CPU上运行。

如果被保护的共享资源在两个或多个软中断上下文访问,那么这个共享资源当然更需要用spin_lock和spin_unlock来保护,不同的软中断能够同时在不同的CPU上运行。

如果被保护的共享资源在软中断(包括tasklet和timer)或进程上下文和硬中断上下文访问,那么在软中断或进程上下文访问期间,可能被硬中断打断,从而进入硬中断上下文对共享资源进行访问,因此,在进程或软中断上下文需要使用spin_lock_irq和spin_unlock_irq来保护对共享资源的访问。而在中断处理句柄中使用什么版本,需依情况而定,如果只有一个中断处理句柄访问该共享资源,那么在中断处理句柄中仅需要spin_lock和spin_unlock来保护对共享资源的访问就可以了。因为在执行中断处理句柄期间,不可能被同一CPU上的软中断或进程打断。但是如果有不同的中断处理句柄访问该共享资源,那么需要在中断处理句柄中使用spin_lock_irq和spin_unlock_irq来保护对共享资源的访问。

在使用spin_lock_irq和spin_unlock_irq的情况下,完全可以用spin_lock_irqsave和spin_unlock_irqrestore取代,那具体应该使用哪一个也需要依情况而定,如果可以确信在对共享资源访问前中断是使能的,那么使用spin_lock_irq更好一些,因为它比spin_lock_irqsave要快一些,但是如果你不能确定是否中断使能,那么使用spin_lock_irqsave和spin_unlock_irqrestore更好,因为它将恢复访问共享资源前的中断标志而不是直接使能中断。当然,有些情况下需要在访问共享资源时必须中断失效,而访问完后必须中断使能,这样的情形使用spin_lock_irq和spin_unlock_irq最好。

需要特别提醒读者,spin_lock用于阻止在不同CPU上的执行单元对共享资源的同时访问以及不同进程上下文互相抢占导致的对共享资源的非同步访问,而中断失效和软中断失效却是为了阻止在同一CPU上软中断或中断对共享资源的非同步访问。

论坛徽章:
0
发表于 2010-01-12 15:31 |显示全部楼层
又找到两篇好文章啊
Linux 内核的同步机制,第 1 部分
http://www.ibm.com/developerworks/cn/linux/l-synch/part1/
Linux 内核的同步机制,第 2 部分
http://www.ibm.com/developerworks/cn/linux/l-synch/part2/

论坛徽章:
0
发表于 2010-01-12 16:11 |显示全部楼层
原帖由 duanjigang 于 2010-1-12 15:31 发表
又找到两篇好文章啊
Linux 内核的同步机制,第 1 部分
http://www.ibm.com/developerworks/cn/linux/l-synch/part1/
Linux 内核的同步机制,第 2 部分
http://www.ibm.com/developerworks/cn/lin ...

看你们的讨论受益匪浅
http://www.ibm.com/developerworks/cn/linux/上的文章向来经典   去拜读下

论坛徽章:
0
发表于 2010-01-12 16:30 |显示全部楼层

回复 #1 duanjigang 的帖子

在init_mem_list函数里的第一次分配的话 ,是不是应该要添加一行代码:
  if(!plist->list)
        {
            plist->list = p;
            plist->list->next = p;//添加代码。否则在第二次循环时候的p->next指针为空,与第一次分配的不能形成链表
            plist->ptr = p;
            continue;
        }
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP