プロセスと端末の関係(プロセスとかセッション)

プロセスと端末は関連があるっていう話をはじめてのOSコードリーディング 読書会 (17)で制御端末のときにちょろっとしたのでその補足的に。出てくる用語としては、プロセス、プロセスグループ、セッションリーダー、セッションがあります。これらがどのように関連しているのかと、端末とどう関連するの?ってところですね。

まずセッションですが、これは制御端末と結びついています。制御端末はtty1やpts1などです。例えばxfce環境のTerminalでtmuxを動かしている状況でwコマンドを実行すると以下のようになります。

masami@saga:~$ w
 19:44:54 up  1:31,  2 users,  load average: 0.40, 0.47, 0.54
USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
masami   :0        18:13   ?xdm?   6:02   0.03s /bin/sh /etc/xdg/xfce4/xinitrc -- /etc/X11/xinit/xserverrc
masami   pts/0     18:13    6.00s  0.00s  0.00s tmux

ここでtmuxが/dev/pts0を開いています。この時点では/dev/pts以下に0と1があります。0はtmuxが開いているものです。1は後述します。

masami@saga:~$ ls -la /dev/pts/
total 0
drwxr-xr-x  2 root   root      0 Jul 27 18:13 ./
drwxr-xr-x 18 root   root   3100 Jul 27 18:13 ../
crw--w----  1 masami tty  136, 0 Jul 27 19:46 0
crw--w----  1 masami tty  136, 1 Jul 27 19:46 1
c---------  1 root   root   5, 2 Jul 27 18:13 ptmx

ここで新たにterminalを起動するとwコマンドの結果は以下のようになりbashがpts2を使用していることがわかります。

masami@saga:~$ w
 19:48:16 up  1:34,  3 users,  load average: 0.89, 0.62, 0.58
USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
masami   :0        18:13   ?xdm?   6:31   0.03s /bin/sh /etc/xdg/xfce4/xinitrc -- /etc/X11/xinit/xserverrc
masami   pts/0     18:13    0.00s  0.00s  0.00s tmux
masami   pts/2     19:46    1:22   0.02s  0.02s bash

/dev/ptsにも2が追加されているのが確認できます。

masami@saga:~$ ls -la /dev/pts/
total 0
drwxr-xr-x  2 root   root      0 Jul 27 18:13 ./
drwxr-xr-x 18 root   root   3100 Jul 27 18:13 ../
crw--w----  1 masami tty  136, 0 Jul 27 19:46 0
crw--w----  1 masami tty  136, 1 Jul 27 19:46 1
crw--w----  1 masami tty  136, 2 Jul 27 19:46 2
c---------  1 root   root   5, 2 Jul 27 18:13 ptmx

ここで、pts1は誰が使っているのかということになるのですが、これはtmuxから起動されているbashになります。これを順に見てきましょう。まずはtmuxを確認。

masami@saga:~$ ps -efc | grep [t]mux
masami     760     1 TS   19 18:13 ?        00:00:10 xfce4-terminal -e tmux
masami     841   760 TS   19 18:13 pts/0    00:00:00 tmux
masami     844     1 TS   19 18:13 ?        00:00:05 tmux

xfce4-terminalよりtmuxが起動されます。このプロセスには端末は割当たっていません。次にbashを見てみると、pid 845がログインシェルとして確認できます。そしてこれにpts1が割あたっています。

masami@saga:~$ ps -efc | grep [b]ash
masami     845   844 TS   19 18:13 pts/1    00:00:00 -bash

ここまで出てきたものを確認するとこのように。

masami@saga:~$ ps -jHf 760 841 844 845
UID        PID  PPID  PGID   SID  C STIME TTY      STAT   TIME CMD
masami     844     1   844   844  0 18:13 ?        Ss     0:07 tmux
masami     845   844   845   845  0 18:13 pts/1    Ss     0:01   -bash
masami     760     1   715   715  0 18:13 ?        Sl     0:13 xfce4-terminal -e tmux
masami     841   760   841   841  0 18:13 pts/0    Ss+    0:00   tmux

最後にshell上で自分自身のfdを確認するとこのように割り当てられているのが確認できます。

masami@saga:~$ ls -la /proc/self/fd
total 0
dr-x------ 2 masami masami  0 Jul 27 20:17 ./
dr-xr-xr-x 8 masami masami  0 Jul 27 20:17 ../
lrwx------ 1 masami masami 64 Jul 27 20:17 0 -> /dev/pts/1
lrwx------ 1 masami masami 64 Jul 27 20:17 1 -> /dev/pts/1
lrwx------ 1 masami masami 64 Jul 27 20:17 2 -> /dev/pts/1
lr-x------ 1 masami masami 64 Jul 27 20:17 3 -> /proc/15453/fd/

というわけで、xfce4-terminalによりtmuxが起動されてそこからbashが起動した結果、bashにpts1が割当たり、その上で動く1プロセスもpts1が使わているのが確認できます。 それで、セッションと制御端末の関係に戻りますが、インタラクティブログインの場合、ログインした端末が制御端末(今の場合pts1)、ログインシェル(cmdが-bashのpid 845)がセッションリーダーとなります。
さらにセッショングループという概念もありますが、これはセッションの集まりです。

プロセスはまあそのままの意味で、例えば以下のようにcatが1つプロセスになりますね。

$ cat /etc/passwd

プロセスグループはそのままですがプロセスのグループです。例として以下のようなコードを動かしてみます。

#!/usr/bin/env python
import os

def show_task_info():
    pid = os.getpid()
    sid = os.getsid(pid)
    ppid = os.getppid()
    pgid = os.getpgid(pid)

    print("pid:%d session id - > %d parent -> %d process group -> %d" % (pid, sid, ppid, pgid))
if __name__ == "__main__":
    show_task_info()

上記コードを以下のように実行します。

masami@saga:~$ (./task.py  ; ./task.py) ; ./task.py

出力はこのようになります。

pid:31482 session id - > 845 parent -> 31481 process group -> 31481
pid:31483 session id - > 845 parent -> 31481 process group -> 31481
pid:31484 session id - > 845 parent -> 845 process group -> 31484

この出力でセッションのIDは845でこれは3プロセスすべてで共通です。sid 845のbash上でコマンドを実行しているので当然の結果ですね。次にparentですがこれは()で括ったプロセス達と、;の後のプロセスで変わっています。31481のほうはbashでforkしたプロセスが更に2回forkして./task.pyを実行していると思います。次の括弧の後のプロセスはbashからfork->execして実行されたのでしょう。最後にプロセスグループですが()で囲った箇所が1つのグループとなっていることがわかります。

ざっとですが、プロセス・制御端末・セッションなどの関係を見てみました。

プロセッサを支える技術  ??果てしなくスピードを追求する世界 (WEB+DB PRESS plus)

プロセッサを支える技術  ??果てしなくスピードを追求する世界 (WEB+DB PRESS plus)