我列出了 Ubuntu 17.04 上的进程,注意到以下进程:
root@user-virtual-machine:~# ps xao pid=,ppid=,pgid=,sid=
1603 1 1601 1601
然而进程1601不存在。
root@user-virtual-machine:~# ls /proc/1601
ls: cannot access '/proc/1601': No such file or directory
正如你所看到的 /proc/1603/status 仍然引用 1601。
root@user-virtual-machine:~# cat /proc/1603/status
Name: VGAuthService
Umask: 0000
State: S (sleeping)
Tgid: 1603
Ngid: 0
Pid: 1603
PPid: 1
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 64
Groups:
NStgid: 1603
NSpid: 1603
NSpgid: 1601
NSsid: 1601
值得一提的是,我在主机上(而不是在容器内)。
这怎么可能呢?如何为不存在的进程设置setsid/setpgid?
答案1
是的,这是一个没有领导者的会话,这对于守护进程来说很常见。
Session主要用于实现终端登录会话。
当您从终端启动守护程序时,您希望它与终端断开连接。为了使该守护进程的进程不再将终端作为其控制终端,您需要启动一个新会话。因此,守护进程通常会分叉一个进程(这确保子进程不是进程组领导者,以便父进程可以退出),并调用setsid()
该子进程。
该孩子将成为新会话的领导者,因此不是由终端控制的会话。但是,如果该进程在未传递 O_NOCTTY 标志的情况下打开了另一个终端设备,则会导致该终端成为该会话的控制终端,这对于守护程序来说不是您想要的。为了确保这种情况不会发生,最好再次分叉,然后子进程就不再是会话领导者,并且打开终端设备将不会造成任何危害。
父进程没有理由停留并退出,因此该会话不再有领导者。
因此,守护进程在没有领导者的会话中运行是很常见的。
在这里,在没有领导者的会话中寻找进程,我看到很多守护进程:
$ ps -je | grep -wf <(comm -23 <(ps -eo sid= | sort -u) <(ps -eo pid= | sort -u) | awk '$1{print $1}')
1722 1714 1714 ? 00:00:01 atopacctd
2540 2178 2178 ? 00:00:00 ddclient - slee
2985 2984 2984 ? 00:00:00 dnsmasq
2987 2984 2984 ? 00:00:00 dnsmasq
8428 8427 8427 ? 00:00:00 gnome-keyring-d
8726 8725 8725 ? 00:01:17 pulseaudio
11456 11455 11455 ? 00:00:00 gnome-keyring-d
11649 11648 11648 ? 00:00:00 pulseaudio