我有一个谜:我的 6GB 交换区用于做什么?我的内核版本是4.15.9-300.fc27.x86_64
.
这是在发生一些崩溃之后发生的。 dmesg
显示我在 gnome-shell 进程(属于 gdm)和后来的一些 firefox 进程(Chrome_~dThread,在 libxul.so 中)中出现了段错误。 coredumpctl -r
显示我当前的启动没有其他崩溃。
1.free
和df -t tmpfs
# free -h
total used free shared buff/cache available
Mem: 7.7G 1.2G 290M 5.4G 6.1G 761M
Swap: 7.8G 6.0G 1.8G
# swapoff -a
swapoff: /dev/dm-1: swapoff failed: Cannot allocate memory
# df -h -t tmpfs
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.9G 17M 3.9G 1% /dev/shm
tmpfs 3.9G 1.9M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
tmpfs 3.9G 40K 3.9G 1% /tmp
tmpfs 786M 20K 786M 1% /run/user/1000
我还手动检查了每个进程的挂载命名空间,是否有任何额外的 tmpfs。没有其他挂载的 tmpfs(或者它们是相同的 - 所以只有 17M,并且有不到 10 个不同的挂载命名空间)。
2.ipcs
# ipcs --human
------ Message Queues --------
key msqid owner perms size messages
------ Shared Memory Segments --------
key shmid owner perms size nattch status
0x00000000 20643840 alan-sysop 600 512K 2 dest
0x00000000 22970369 alan-sysop 600 36K 2 dest
0x00000000 20774914 alan-sysop 600 512K 2 dest
0x00000000 20905987 alan-sysop 600 3.7M 2 dest
0x00000000 23461892 alan-sysop 600 2M 2 dest
0x00000000 20873221 alan-sysop 600 3.7M 2 dest
0x00000000 22511622 alan-sysop 600 2M 2 dest
0x00000000 28278791 alan-sysop 600 60K 2 dest
0x00000000 23003144 alan-sysop 600 36K 2 dest
0x00000000 27394057 alan-sysop 600 60K 2 dest
0x00000000 29622282 alan-sysop 600 156K 2 dest
0x00000000 27426828 alan-sysop 600 60K 2 dest
0x00000000 28246029 alan-sysop 600 60K 2 dest
0x00000000 29655054 alan-sysop 600 156K 2 dest
0x00000000 29687823 alan-sysop 600 512K 2 dest
------ Semaphore Arrays --------
key semid owner perms nsems
0x002fa327 98304 root 600 2
3. 进程内存
这每个进程交换使用脚本说进程内存只占交换区的 54MB:
PID=1 swapped 2292 KB (systemd)
PID=605 swapped 4564 KB (systemd-udevd)
PID=791 swapped 324 KB (auditd)
PID=793 swapped 148 KB (audispd)
PID=797 swapped 232 KB (sedispatch)
PID=816 swapped 120 KB (mcelog)
PID=824 swapped 1544 KB (ModemManager)
PID=826 swapped 152 KB (rngd)
PID=827 swapped 300 KB (avahi-daemon)
PID=829 swapped 1688 KB (abrtd)
PID=830 swapped 836 KB (systemd-logind)
PID=831 swapped 432 KB (dbus-daemon)
PID=843 swapped 368 KB (chronyd)
PID=848 swapped 312 KB (avahi-daemon)
PID=854 swapped 476 KB (gssproxy)
PID=871 swapped 1140 KB (abrt-dump-journ)
PID=872 swapped 1280 KB (abrt-dump-journ)
PID=873 swapped 1236 KB (abrt-dump-journ)
PID=874 swapped 14196 KB (firewalld)
PID=911 swapped 592 KB (mbim-proxy)
PID=926 swapped 1356 KB (NetworkManager)
PID=943 swapped 17936 KB (libvirtd)
PID=953 swapped 200 KB (atd)
PID=955 swapped 560 KB (crond)
PID=1267 swapped 284 KB (dnsmasq)
PID=1268 swapped 316 KB (dnsmasq)
PID=10397 swapped 160 KB (gpg-agent)
PID=14862 swapped 552 KB (systemd-journal)
PID=18131 swapped 28 KB (login)
PID=18145 swapped 384 KB (bash)
Overall swap used: 54008 KB
到目前为止,我假设没有疏忽的程序
umount -l
在完整的 tmpfs 上使用。我还没有尝试为任何打开这样一个隐藏的 tmpfs 的人抓取 /proc/*/fd 。我想我也假设没有人建造了一个巨人
memfd
并将其打开......哈哈为什么我什至会怀疑这样的事情......呜咽。
附加到进程的 memfd 名称对我来说似乎是无辜的:
# ls -l /proc/*/fd/* 2>/dev/null|grep /memfd:
lrwx------. 1 alan-sysop alan-sysop 64 Mar 18 22:52 /proc/20889/fd/37 -> /memfd:xshmfence (deleted)
lrwx------. 1 alan-sysop alan-sysop 64 Mar 18 22:52 /proc/20889/fd/53 -> /memfd:xshmfence (deleted)
lrwx------. 1 alan-sysop alan-sysop 64 Mar 18 22:52 /proc/20889/fd/54 -> /memfd:xshmfence (deleted)
lrwx------. 1 alan-sysop alan-sysop 64 Mar 18 22:52 /proc/20889/fd/55 -> /memfd:xshmfence (deleted)
lrwx------. 1 alan-sysop alan-sysop 64 Mar 18 22:52 /proc/20889/fd/57 -> /memfd:xshmfence (deleted)
lrwx------. 1 alan-sysop alan-sysop 64 Mar 18 22:52 /proc/20889/fd/60 -> /memfd:xshmfence (deleted)
lrwx------. 1 alan-sysop alan-sysop 64 Mar 18 22:52 /proc/21004/fd/6 -> /memfd:pulseaudio (deleted)
这些 memfd 看起来很无辜,因为: Process 20889 是我当前的进程Xorg
,它比 6GB 的交换空间更晚。同样,进程21004确实是我的pulseaudio进程,并且该进程的创建时间晚于6GB交换空间的建立。
理论上,我担心的那些也可能处于不确定状态,附加到 unix 套接字消息并且从未阅读过。
编辑1
停止后systemd-logind
(本机 Xorg 会通过死亡来响应)并重新启动 Xorg,我看到整个 6GB 交换区被清除。
请注意,我忘记了我需要重新开始登录。尽管lennart告诉我logind不应该通过总线激活,但logind立即重新启动。这是来自journalctl -b
,即系统日志,其间没有删除任何消息:
Mar 18 23:14:12 alan-laptop systemd[1]: Stopped Login Service.
Mar 18 23:14:12 alan-laptop dbus-daemon[831]: [system] Activating via systemd: service name='org.freedesktop.login1' unit='dbus-org.freedesktop.login1
Mar 18 23:14:12 alan-laptop systemd[1]: Starting Login Service...
这与登录然后经历了几次崩溃的循环有关。这是这个版本的 logind 所期望的(修复它的 PR 已合并到上游,按照我的问题报告)。
因此,这并不能完全隔离个别原因,我真的应该在杀死 fds logind 之前检查它所持有的内容。
问题
我在上述检查中是否遗漏了任何可能的交换用户? (非破坏性的,在 EDIT1 之前)。
有没有更好的方法来获取我上面列出的任何可能用户的使用情况报告?也就是说,要么有一个替代方案可以纠正一些我没有注意到的错误?或者当这种情况再次发生时更容易运行并快速得到结果的东西?
有没有人有一个很好的脚本来检查打开“隐藏”tmpfs(与 分离的 tmpfs umount -l
)的 fds?
有没有人有一个好方法来检查 memfds 的内存使用情况?
有没有办法检查未读的 unix 套接字消息中是否存在大量 memfd? (这些天才在实现 memfd 时是否考虑过这一点,因为 memfd 是明确用于传递 unix 套接字的?)
编辑2:我的猜测是否正确,图形设备(DRM)的文件描述符可以保存对可交换内存的引用? Notelogind
保存此类文件描述符。
答案1
编辑1停止 systemd-logind(本机 Xorg 通过死亡来响应)并重新启动 Xorg 后,我看到整个 6GB 交换空间被清除。
第二次之后,我可以确认这是systemd-logind中的一个错误。 logind
记得关闭它所保存的 DRM fd 的副本,但无法关闭 PID1 中保存的副本(用于支持“无缝”重新启动登录):
$ sudo lsof /dev/dri/card0 | grep systemd
[sudo] password for alan-sysop:
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
Output information may be incomplete.
systemd 1 root 16u CHR 226,0 0t0 14690 /dev/dri/card0
systemd 1 root 87u CHR 226,0 0t0 14690 /dev/dri/card0
systemd 1 root 101u CHR 226,0 0t0 14690 /dev/dri/card0
systemd 1 root 106u CHR 226,0 0t0 14690 /dev/dri/card0
systemd 1 root 110u CHR 226,0 0t0 14690 /dev/dri/card0
systemd-l 860 root 21u CHR 226,0 0t0 14690 /dev/dri/card0
systemd-l 860 root 25u CHR 226,0 0t0 14690 /dev/dri/card0
这感觉很像一个已知的错误,这应该已经在 systemd v238 中修复了。
事实上,每次我登录和退出 GNOME 时,logind 似乎都会以这种方式泄漏 DRM fd。据推测,只有当显示服务器不正常关闭时,此错误才会变得明显,因此它们没有机会取消分配附加到其 DRM fd 的缓冲区。
编辑2:我的猜测是否正确,图形设备(DRM)的文件描述符可以保存对可交换内存的引用?请注意,logind 保存此类文件描述符。
答:是的。
菲尔普
SHMEM 文件节点用作可交换缓冲区对象的后备存储。
--https://www.kernel.org/doc/html/v4.15/gpu/drm-mm.html
据我了解,这里的“SHMEM 文件节点”与 tmpfs 文件/memfd 的工作完全相同。上面的引述是关于“GEM 缓冲对象”...
mmap 系统调用不能直接用于映射 GEM 对象,因为它们没有自己的文件句柄。当前共存两种替代方法将 GEM 对象映射到用户空间...第二种方法在 DRM 文件句柄上使用 mmap 系统调用。
--https://01.org/linuxgraphics/gfx-docs/drm/drm-memory-management.html#id-1.3.4.6.6.8
结论:有人真的应该仔细检查登录中的当前代码,因为它与文件句柄的关闭有关:)。
附录:如何尝试排除 memfds
有没有人有一个好方法来检查 memfds 的内存使用情况?
stat --dereference
memfds 的内存使用情况可以使用或du -D
中的魔术符号链接来读取/proc/$PID
。要么是fd/$FD
文件描述符,要么是 - 你忘记了 -map_files/...
内存映射对象。
我对此没有很好的便利,但您至少可以搜索最大的单个 FD 或映射文件。 (下面的示例不是额外的证据;它是在 6GB 交换使用量消失后拍摄的)。
$ sudo du -aLh /proc/*/map_files/ /proc/*/fd/ | sort -h | tail -n 10
du: cannot access '/proc/self/fd/3': No such file or directory
du: cannot access '/proc/thread-self/fd/3': No such file or directory
108M /proc/10397/map_files/7f1e141b4000-7f1e1ad84000
111M /proc/14862/map_files/
112M /proc/10397/map_files/
113M /proc/18324/map_files/7efdda2fb000-7efddaafb000
121M /proc/18324/map_files/7efdea2fb000-7efdeaafb000
129M /proc/18324/map_files/7efdc82fb000-7efdc8afb000
129M /proc/18324/map_files/7efdd42fb000-7efdd4afb000
129M /proc/18324/map_files/7efde52fb000-7efde5afb000
221M /proc/26350/map_files/
3.9G /proc/18324/map_files/
$ ps -x -q 18324
PID TTY STAT TIME COMMAND
18324 pts/1 S+ 0:00 journalctl -b -f
$ ps -x -q 26350
PID TTY STAT TIME COMMAND
26350 ? Sl 4:35 /usr/lib64/firefox/firefox
$ sudo ls -l /proc/18324/map_files/7efde52fb000-7efde5afb000
lr--------. 1 root root 64 Mar 19 00:32 /proc/18324/map_files/7efde52fb000-7efde5afb000
-> /var/log/journal/f211872a957d411a9315fd911006ef03/user-1001@c3f024d4b01f4531b9b69e0876e42af8-00000000002e2acf-00055bbea4d9059d.journal