13.3 什么是D-Bus

13.3.1 runC请求D-Bus

容器运行时的runC命令,是libcontainer的一个简单的封装。这个工具可以用来管理单个容器,比如创建容器和删除容器。在上一节的最后,我们却发现runC不能完成创建容器的任务。我们可以把对应的进程“杀”掉,然后在命令行用同样的命令启动容器,同时用strace追踪整个过程,如图13-9所示。

图13-9 使用追踪机制分析runC

分析发现,runC停在了向带有org.free字段的dbus socket写数据的地方。那什么是D-Bus呢?在Linux中,D-Bus是一种进程间进行通信的机制。

13.3.2 原因并不在D-Bus

在Linux中,D-Bus是进程间互相通信的总线机制,如图13-10所示。

图13-10 D-Bus在进程通信中的作用

我们可以使用busctl命令列出系统现有的所有bus。如图13-11所示,在问题发生的时候,我们看到问题节点bus name编号非常大。所以我们倾向于认为,是dbus某些相关的数据结构(比如name)的耗尽引起了这个问题。

图13-11 D-Bus通信连接

D-Bus机制的实现,依赖于一个叫作dbus daemon的组件。如果真的是dbus相关数据结构耗尽,那么重启这个daemon应该可以解决这个问题。但不幸的是,问题并没有这么简单。重启dbus daemon之后,问题依然存在。

在上面strace追踪runC的截图中,runC停在向带有org.free字段的bus写数据的地方。在busctl输出的bus列表里,显然带有这个字段的bus,都在被Systemd使用。这时,我们用Systemctl daemon-reexec来重启Systemd,问题消失了。所以我们可以判断出大体方向:问题可能和Systemd有关。