今までこんな関数扱ったことない…
linuxでのC言語案件で触ったファイルに知らない固有関数がたくさん…忘備録としてまとめた記事になります。
ソースコードの流れ
main関数の先頭で
fork ⇒ exit() ⇒ setsid()
が実行されていました、なんだこれは…。
結論から言うと、これは処理をバックグラウンドで回すためのデーモン化を行っています。
fork()
プロセスを分割(=fork直下のコードのコピーが生成)します。
分割前を親、分割後を子と表現し、マルチタスクとして動作。
親と子はforkを呼んだ時の戻り値(プロセスID)で判断でき、0の場合は子、0より大きい場合は親、0未満の場合はエラーとなります。
なので、コードはこんな感じ。
int id = fork();
if(id == 0){
//do something child
} else if(id > 0){
//do something parent
exit(0); //後述
} else {
//error
}
このid変数をif文で分けて処理を別個に設けることが可能。
exit(0)
プロセスを終了する。引数が0の場合正常終了、0以外だったら異常終了を意味している。
fork()項で述べたように、プロセスIDで親子を判断でき、親プロセスでexit()させることが多い。
つまり、forkして親をexitした時点で子プロセスしか残ってない。
この時点では何のためにやってるのかさっぱり分からない…。
setsid()
プロセスが親プロセスでない場合、新たなセッションを作成する。
これは子プロセスが独立した処理になるということを意味している。
ところで、セッションとは何だろうか。
プログラムの構造を理解する
プロセスとはプログラムの実行単位を言う。
そして、forkで分けたプロセスは元になっているのを親、コピーしてできた方を子と言った。
exitで親プロセスを終了して、子プロセスだけ残っている。
で、こうしたプロセスは全てセッションという大枠の中で行われている。
セッション自体は、ユーザーがターミナルからログインし、シェルを実行するときに形成される。
セッションがユーザーが実行するすべてのプロセスをグループ化し、リソース管理やターミナル制御を行っている。
setsidは、このセッション内にいる子プロセスを独立した新たなセッションとして作ることを行っている。
新たなセッションのプロセスはバッググラウンドで処理が実行され、これをデーモンプロセスという。
つまり、fork、(親の)exit、setsidのセットはデーモン化ということになる。
デーモン化の利点
デーモンプロセスがセッションリーダーとして新しいセッションを作成することによって、以下の利点がある。
- ターミナルからの切断: セッションリーダーとなったデーモンプロセスは、親セッション(ターミナルなど)から切り離されるため、ターミナルの状態の変更や制御信号がデーモンに影響を与えることがありません。
- ファイルディスクリプタの独立性: セッションリーダーによって作成されたセッション内では、ファイルディスクリプタが新しい制御端末に関連付けられないため、デーモンプロセスがファイルディスクリプタを開いたり閉じたりするときに予期せぬ動作が発生しなくなります。
- プロセスグループとセッションIDの独立性: セッションリーダーによって新しいセッションが作成されるため、プロセスグループIDとセッションIDが切り離され、デーモンプロセスが他のプロセスやセッションと独立して識別されることが可能になります。
デーモンプロセスが実行される環境では、通常fork()
を使用して新しいプロセスを生成し、setsid()
を呼び出して新しいセッションを作成します。このようにしてデーモンプロセスはセッションリーダーとなり、上記の特性を持つバックグラウンドプロセスとなります。
まとめ
fork、(親の)exit、setsidのセットはデーモン化ということ。
コメント