由spin_lock_bh想到的一些事
近日有人问我为什么在PREROUTING这个NF HOOK点的function里需要使用spin_lock_bh/unlock_bh而不是spin_lock/unlock来保护临界区。
面对这个问题,有点懵,说到spin_lock族,有很多系列接口:
- spin_lock/spin_unlock
- spin_lock_bh/spin_unlock_bh
- spin_lock_irq/spin_unlock_irq
- spin_lock_irqsave/spin_unlock_irqrestore
- …
之所以有这么多,说白了就是为了 防止关闭了抢占的临界区被同一个CPU的高优先级序列打断而重入时造成死锁。
但还是要给出一个具体的case才能让人信服,而不仅仅是理论上如此。
其实只需要给出一个进程上下文调用PREROUTING function的case即可:
- 进程上下文C1在PREROUTING function中调用spin_lock(Lx)进入临界区。
- 尚未出临界区,C1所运行CPU被中断,随即调度softirq执行net_rx_action。
- 在软中断上下文C2中进入PREROUTING function,调用spin_lock(Lx)企图进入临界区。
- 由于C1已经获取spinlock Lx,C2开始自旋,等待C1释放Lx。
- 由于C1被C2抢占,而C2已经自旋,因此妥妥死锁!
但问题是,在什么情况下,进程上下文能到PREROUTING呢??
记得2015年大概也是这个时候,写过一篇文章:
https://blog.csdn.net/dog250/article/details/48770481
该文章中的case是进程上下文中执行数据包接收的场景,数据包接收的过程中肯定是穿过PREROUTING点的。
我来摘抄一下该文章相关的描述:
一个连接本机的TCP数据包最终到达了loopback的xmit发送函数,其中简单的调度了本CPU上的一个软中断处理,然后会在下一次中断结束后调度其执行,这有很大几率是在当前发送进程的上下文中进行的,也就是说,发送进程在其上下文中进行了发送操作,而此时软中断借用了其上下文触发了接收操作,…
但是,有问题啊,什么叫 "这有很大几率是在当前发送进程的上下文中进行的" 我感觉这不严谨,所以今天我要深入探究一下这个问题:
- 为什么loopback网卡的发送和接收逻辑在同一个进程上下文中进行?
为此,需要在本地通过loopback进行ping通信的时候,打印出stack:
#!/usr/local/bin/stap -gfunction dump()
%{dump_stack();
%}probe kernel.function("icmp_rcv")
{dump();//print_backtrace(); // 这个不知为何不好使..
}
以下是一次ping后的结果:
[34197.319729] [<ffffffff8159a145>] ? icmp_rcv+0x5/0x380
[34197.319732] [<ffffffff81561b84>] ? ip_local_deliver_finish+0xb4/0x1f0
[34197.319735] [<ffffffff81561e69>] ip_local_deliver+0x59/0xd0
[34197.319738] [<ffffffff81561ad0>] ? ip_rcv_finish+0x350/0x350
[34197.319741] [<ffffffff815617fd>] ip_rcv_finish+0x7d/0x350
[34197.319744] [<ffffffff81562196>] ip_rcv+0x2b6/0x410
[34197.319747] [<ffffffff81561780>] ? inet_del_offload+0x40/0x40
[34197.319752] [<ffffffff815267b2>] __netif_receive_skb_core+0x582/0x7d0
[34197.319755] [<ffffffff81526a18>] __netif_receive_skb+0x18/0x60
[34197.319757] [<ffffffff815276ee>] process_backlog+0xae/0x180
[34197.319760] [<ffffffff81526ed2>] net_rx_action+0x152/0x240
[34197.319765] [<ffffffff8107e02f>] __do_softirq+0xef/0x280
[34197.319768] [<ffffffff81646b1c>] call_softirq+0x1c/0x30
[34197.319769] <EOI> [<ffffffff81017155>] do_softirq+0x65/0xa0
[34197.319777] [<ffffffff8107d924>] local_bh_enable+0x94/0xa0
[34197.319780] [<ffffffff81566a00>] ip_finish_output+0x1f0/0x7d0
[34197.319783] [<ffffffff81567cff>] ip_output+0x6f/0xe0
[34197.319786] [<ffffffff81566810>] ? ip_fragment+0x8b0/0x8b0
[34197.319789] [<ffffffff81565971>] ip_local_out_sk+0x31/0x40
[34197.319791] [<ffffffff81568746>] ip_send_skb+0x16/0x50
[34197.319793] [<ffffffff815687b3>] ip_push_pending_frames+0x33/0x40
[34197.319797] [<ffffffff81590fbe>] raw_sendmsg+0x59e/0x620
[34197.319802] [<ffffffff810af1a9>] ? ttwu_do_wakeup+0x19/0xd0
[34197.319805] [<ffffffff8159f604>] inet_sendmsg+0x64/0xb0
[34197.319811] [<ffffffff8150cc90>] sock_sendmsg+0xb0/0xf0
[34197.319814] [<ffffffff8150d201>] SYSC_sendto+0x121/0x1c0
[34197.319817] [<ffffffff8150e221>] ? __sys_recvmsg+0x51/0x90
[34197.319820] [<ffffffff8150dc8e>] SyS_sendto+0xe/0x10
[34197.319823] [<ffffffff81645189>] system_call_fastpath+0x16/0x1b
哈哈,真相大白了!我在2015年的分析是错误的:
发送进程在其上下文中进行了发送操作,而此时软中断借用了其上下文触发了接收操作,…
根本就不是什么 "借用了其上下文" ,而是实实在在就是在该上下文中主动调用的net_rx_action啊!
其调用逻辑如下:
ip_output_finishrcu_read_lock_bh...dev_queue_xmitloopback_xmitnetif_rxenqueue_to_backlog # 这里将skb入队列raise_softirq_irqoff(NET_RX_SOFTIRQ)...............rcu_read_unlock_bh # unlock操作触发进程上下文中处理接收操作local_bh_enabledo_softirq__do_softirqnet_rx_action # 这里对队列中的skb进行处理...ip_rcv_finishicmp_rcv..................
ip_output_finish return
OK,现在,这就是一个非常清晰的进程上下文执行数据包接收逻辑的case,也就是说:
- 既然软中断函数net_rx_action可能会在进程上下文中执行,为了防止死锁,其中的临界区一定要用_bh版本的spinlock保护!
类似rcu_read_unlock_bh这种在unlock过程中做很多事情的操作,内核中还有很多:
- spin_unlock可能会触发schedule进而发生task切换。
- spin_unlock_bh可能会触发do_softirq进而执行软中断例程。
- release_sock可能会执行sk_backlog_rcv进而处理收包。
- …
这是一种 补偿 效应,既然lock操作到unlock操作之间禁止了一些行为,那么在unlock时就要尽可能地去补偿这些不得不延后的行为,尽量让它们马上执行。这个设计还是比较巧妙的。
另外,还有一个典型的进程上下文执行数据包接收逻辑的case,即TUN/TAP网卡从进程上下文调用tun_get_user,然后直接调用netif_rx_ni来收包的case。
我们再来看看这个loopback网卡发送和接收数据包奇怪且有意思的流程:
- 发送逻辑尚未返回,接收逻辑先返回。
这意味着什么?不得而知,但如果碰到一些本机连本机过程中莫名其妙的问题,可以从此入手来排查。
由spin_lock_bh想到的一些事相关推荐
- 《那些年啊,那些事——一个程序员的奋斗史》——88
谁也不知道武总脑袋里面会想些什么.这天早上段伏枥还在发愁如何改进这4.3'机器的电源管理的时候,武总突然让自己到会议室开会. 段伏枥还没坐下来的时候,武总推过来一台机器,说:"你看看,这机器 ...
- 男人应该做的50件事(1-16)
序 言:男人,走过,路过,不错过 王星凡 连载:男人一生要做的50件事 出版社:哈尔滨出版社 作者:王星凡 人的一生,从推开生命之门那一刻开始,于是,你走进生命的殿堂,像一个好奇的旅客,每一件新奇的事 ...
- java 搞笑的事情_一件搞笑的事作文(精选10篇)
一件搞笑的事作文(精选10篇) 生活中的事像天空中的繁星一样多,搞笑的事情也是有的.下面是小编准备的一件搞笑的事作文(精选10篇),欢迎阅读. 一件搞笑的事作文1 从小到大,在我的生活中发生过许多可笑 ...
- 番茄工作法总结-第一章:一次只做一件事
在25分钟之内,专心做某一件事,然后短暂休息, 休息之后,再将其他事与正在做的事对比一下,选择更重要的 开始之前 要想做到专注,就要坚决抛开各种杂念 例举人脑思维研究成果,揭示番茄工作法原理 使用番茄 ...
- 非211计算机保研的那些事
1一次偶然的机会知道保研 2搜集上届保研情况心底一凉 3开始进行保研的准备多方打听 4一次次的联系老师的过程处处碰壁 5看起来高大上的夏令营能不能去 6暑期里的生活心里不安 7新学期的开始各种矛盾 8 ...
- 最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用50
广告客户 吴言之前也研究过互联网广告业务模式,具体来讲可以分为六大模式:门户网站广告模式.搜索引擎广告模式.社会化网站广告模式.视频网站广告模式.植入式广告模式.广告联盟模式. 对于门户网站广告模式来 ...
- 如何评价LoRa这项应用于低功率长距离场景的物联网传输技术?
大家好,我是无际单片机编程徐工. 我2010年毕业就开始做无线相关的工作,那个时候用的是ASK无线通讯,收发模块都是我们自己做的. 那今年,给我最深刻的就是没完没了地调试无线模块的参数,测试无线通讯距 ...
- CentOS6.5更改ssh端口问题
今天更改ssh端口时,发现更改后重启sshd服务不生效,经过测试sshd端口更改为1024以下的端口不生效,更改为1024及以上的端口则可以生效. 这就奇怪了,只要端口不冲突,ssh端口理论上是可以修 ...
- CLion报错解决:allocating an object of abstract class type--unimplemented pure virtual method
在用CLion写代码时遇到了这个报错: allocating an object of abstract class type '...' unimplemented pure virtual met ...
- 清华大学计算机王君,对不起,我曾希望你成为“我”!(特级教师王君)
王君 [导读:这是特级教师王君写给儿子的反思信.老师家长,在教育孩子的路上,你是否总是希望孩子成长为你想要的模样?你是否曾因为孩子不够"优秀"而焦虑不安?你是否曾经因为太过急功近利 ...
最新文章
- ORB-SLAM3中的3d-2d匹配
- hdu 4722(记忆化搜索)
- Science:人类在实验室创建了微型“大脑”,含祖先基因的那种
- VarGFaceNet
- DOS命令编译JAVA程序
- big5码在线转换_【开源】基于 SpringBoot 的 web kettle 在线采集平台
- 数据分析训练营还有这些内容(Spark)
- BTC 重现“自由落体”式暴跌,原来是受这几个因素影响?
- 客户端和服务器之间的信息结构,客户端和服务器之间的信息结构
- [网络结构]DenseNet网络结构
- wpf listview 大数据界面刷新
- 安装UWB定位系统设备需要注意什么?
- php怎么画五星红旗,php基于GD库画五星红旗的方法,phpgd库五星红旗
- 5G NR的新特征—超低时延
- 智慧养老平台推广文案列
- 新增诊所19804家 | 私营诊所要如何主动?才能被患者选择
- 使用PHP获取网站Favicon的方法
- 全量备份,差量备份,增量备份的异同
- oracle创建Triggers
- 8-设计模式之行为型模式二(状态模式、观察者模式、中介者模式)
热门文章
- 机器学习初探(手写数字识别)matlab读取数据集
- Redis常见配置文件详解
- 如何使用python将二维数组去重呢?
- 优化mysql数据库性能的十个参数
- TOMCAT报错解决
- 搞大啦!精灵云与全球最大孵化器PNP带你一起飞
- 学习OpenCV——SVM 手写数字检测
- Html表格lt;tablegt;还是须要加入一些标签进行优化,能够加入标题lt;captiongt;和摘要lt;table summarygt;...
- ocp007 题库解析(1-15)
- libsvm 实现多分类原理