なるほどUnixプロセス ― Rubyで学ぶUnixの基礎
https://gyazo.com/58677e76fa0810a3803810b815713d36
目次
第1章 はじめに
winampなつ
第2章 本書の手引き
ユーザーランド
プログラムが実行される場
システムコールを使わなくてもプログラムは書ける
四則演算とか文字列操作とか
カーネル
ハードウェアとの間にいる
プログラムはカーネルを直接操作できない
システムコール経由で行う必要がある
逆にいうと、システムコールを使えば、ハードウェアと相互作用ができる
ドキュメントの見つけ方
man コマンド
ユーザーコマンド(1)
find(1) とか
システムコール(2)
getpid(2) とか
サブルーチン(3)
malloc(3) とか
デバイス(4)
プロセス
code:ruby
$ ruby -e "p Time.now"
2022-05-16 13:29:16.559249 +0900
そうだね
あらゆるコードはプロセスの上で実行される
↑のrubyのプログラムも、DBも裏で動いているアプリケーションも
第3章 プロセスにはIDがある
pid
プロセス固有のId
code:ruby
$ irb
irb(main):001:0> p Process.pid
34389
=> 34389
なるほどね
Process.pid は getpid(2) を呼ぶ
code:sh
$ ps -p 34632
PID TTY TIME CMD
34632 ttys008 0:00.34 irb
ログとか眺めると、pidが出力されていたりするのよ
第4章 プロセスには親がいる
プロセスには親となるプロセスがいる
ppid
code:ruby
irb(main):002:0> Process.ppid
=> 68638
ほーん
code:sh
$ ps -p 68638
PID TTY TIME CMD
68638 ttys008 0:04.68 -fish
fish から irb 起動しているのでそれはそうかも
getppid(2) を呼び出してるんだってね
第5章 プロセスにはファイルディスクリプタがある
ファイルディスクリプタ
Unixは「全てがふぁいる」
リソースとも呼べる
プロセスからリソースを開くとファイルディスクリプタが割り当てられる
IO#fileno がそれ
code:ruby
irb(main):004:0> f = File.open('404.html')
irb(main):005:0> f.fileno
=> 9
ほーん
ファイルディスクリプタは連番
閉じたらその番号は再利用される
開かれたリソースに対して「オープンファイルディスクリプタ」なんてよばれることもある
標準ストリーム
予約されたファイルディスクリプただ!
STDIN
STDOUT
STDERR
リダイレクトの時の 2 > /dev/null とかの番号これじゃん〜
第6章 プロセスにはリソースの制限がある
ものには限度がある
code:ruby
p Process.getrlimit(:NOFILE)
ソフトリミットとハードリミットがある
そのプロセスが触る限界とハードの限界
ハードリミットは実質INFINITY
code:ruby
irb(main):001:0> Process.setrlimit(:NOFILE, 4096)
=> nil
irb(main):003:0> Process.getrlimit(:NOFILE)
ソフトリミットの制限に達したら Errno::EMFILE 例外がとぶ
Errnoの例外シリーズはunixの例外なんだね
リソースシリーズ
NPROC プロセスユーザーが作成できるプロセス数
FSIZE プロセスが作成できるファイルサイズの数
STACK プロセススタック
ulimit ってユーザーの作成できるリソースをあれこれしてるんやね
第7章 プロセスには環境がある
環境変数の話
プロセスは親プロセスから環境変数を引き継ぐ
Ruby には Hash のように環境変数を取れる ENV が存在する
けどHASHではない
code:ruby
irb(main):005:0> ENV.class
=> Object
これさー、つまるところインスタンスに特異メソッドはやしまくりってこと?
ARGFはARGF.classのインスタンスなんですよねえ
第8章 プロセスには引数がある
ARGV よくある
C++ だと ARGV と ARGC にわかれてるよね
Ruby で ARGVの解析するなら optparse 使おうね
第9章 プロセスには名前がある
$PROGRAM_NAME がプロセスの名前
普通に代入できて、変更すると実際のプロセス名にも反映される
rubyはこれが唯一のプロセス名を変える方法
code:ruby
irb(main):008:0> $PROGRAM_NAME
=> "irb"
irb(main):009:0> $PROGRAM_NAME = "IIIIIIIIIIIIIIIIRB"
=> "IIIIIIIIIIIIIIIIRB"
code:console
$ ps | grep IIIIII
85402 ttys007 0:05.31 IIIIIIIIIIIIIIIIRB
86093 ttys009 0:00.00 grep --color=auto IIIIII
第10章 プロセスには終了コードがある
終了するとなんらかの 0-255 のコードを返す
正常終了は0
エラーなら < 1
プログラミング言語の true, false と逆になるので混乱しがち
Kernel#exit でスクリプトが終わる。一緒に終了コードもおくれる
at_exit で定義したブロック内のコードが終了時に実行される
Kernel#exit! はデフォルト終了コード1で終える
at_exit で定義したブロック内のコードは実行されない
Kernel#abort も終了コード1
メッセージを引数に取れて、 STDERRに流せる
例外がcatchされずにエントリーポイントを突き抜けたときもプロセスが終了される
at_exit は実行される
STDERR にメッセージとバックトレースが流れる
普段みてるのはこれなのねえ
第11章 プロセスは子プロセスを作れる
fork(2)だ。これは聴いたことがありますよ。
プロセスから新しいプロセスを生成できる
親プロセスと子プロセス
子プロセスは親プロセスで使われているメモリのコピーやファイルディスクリプタを引き継ぐ
ファイルやソケットを共有できる
fork メソッドは子プロセス側ではnilを返す
親プロセスでは生成した子プロセスの pid を返す
500MBのメモリ〜フォーク爆弾
前に書いてることと矛盾してね。効率的なのか、爆弾なのか
ブロックを渡すとブロックの中は子プロセスで実行される
code:ruby
irb(main):001:1* fork do
irb(main):002:1* puts {Process.pid}
irb(main):003:0> end
=> 91339
irb(main):004:0> Process.pid
=> 91323
第12章 孤児プロセス
親は死んでも子を道連れにしない
code:ruby
irb(main):005:1* fork do
irb(main):006:1* sleep 4
irb(main):007:1* puts "aaaaaaaaaaaa"
irb(main):008:0> end
=> 91368
irb(main):009:0> exit
17:25:02 ⎈ minikube ~ 4.16
$ aaaaaaaaaaaa
ほんとだ
孤児を管理する方法はあるのか
デーモンプロセス
Unixシグナルを用いたプロセスとの通信
第13章 プロセスは優しい
コピーオンライト
第14章 プロセスは待てる
第15章 ゾンビプロセス
第16章 プロセスはシグナルを受信できる
第17章 プロセスは通信できる
第18章 デーモンプロセス
バックブラウン度で動作するプロセスのことをデーモンプロセスという
daemon
カーネルは起動時に ppid 0, pid 1 の init プロセスを作る
第19章 端末プロセスを作る
第20章 おわりに
付録1 Resqueのプロセス管理
付録2 Unicornのワーカープロセスの管理
付録3 preforkサーバ
付録4 Spyglass
あとがき