infoMore than 1 year has passed since last update.
Command::spawnのデザイン(unix)
Last updated at Posted at 2018-08-12
1 / 17
まえがき
- std::processはポータブルな実装だがにここではunix着目する
プロセス起動
- 新しいプロセスを立ち上げてプログラムを実行する
- サブプロセスと言ったりもする
プロセス
- プログラムを実行している主体
- いろいろ状態をもってる
prcess::Command
- プロセス起動を行うためのAPI
- 実装はポータブル(Posix/Windows)
- UNIXでいうfork-execを行う
- シェルを経由する専用APIは用意しない
- newやargの引数に
sh -c
を渡せばできる
イメージ
let output = Command::new("sh")
.arg("-c")
.arg("echo hello")
.output()
.expect("failed to execute process");
デザイン
-
Command::new
時点ではプロセスを生成しない
-
spawn
などを呼ぶまでの間にやりたいことを設定
- 引数の追加(
arg/args
)
- リダイレクト(
stdin/stdout/stderr
)
- 環境変数の追加/クリア(
env_clear
)
- カレントディレクトリ(
current_dir
)
デザイン
- waitするかどうかはAPIによって変わる
- spawnはwaitしないので親が明示的に行う
- outputやstatusは当然行う
spawn
- ジェネリックなプロセス起動API
-
std::process::Child
を返す
- 子プロセスのPIDをもつ
- waitをメソッドにもつ
spawnの内部実装
- 条件が合えば
posix_spawn
を使う
- そうでない場合
fork
と exec
を使う
posix_spawn
- fork-execまで一気にやってくれるAPI
- 現時点でいくつかのプラットフォームで使える(ただしそれぞれいくつか制約条件はある)
- Linux/Glibc2.24+, MacOS , FreeBSD
posix_spawnを使う意図
- メモリを複製しない実装が使われることが多い
- Linuxなら
clone(CLONE_VM/E_VFORK)
注:コメント欄で指摘いただきました
- Linux: clone(CLONE_VM|CLONE_VFORK)
- MacOS/FreeBSDなら
vfork
- fork-exec間に差し込めない処理もある
-
current_dir
など使ったらforkを使う
before_exec
- UNIXなシステムのみ存在
- fork-exec間で行いたい処理をフック可能
- 他ではPythonの
preexec_fn
などがある
- リダイレクトや環境変数以外にもやりたいことはある
- リソース管理 (例: core dump)
- fdのclose処理を書きたいかも
before_execは問題ないのか
- 任意の処理が記述できてしまう
- fork-exec間はasync-signal-safeな関数のみ使うべき
- 危険性はドキュメントで注意喚起している
FDの挙動
- 他の言語のように3番以降のFDをcloseするAPIを提供していない
- Rustのstd自体はCLOEXEC前提
- Cのライブラリ関数は保証がない
過去の議論
spawnのまとめ
- プロセス起動のプリミティブなAPI
- fork+属性設定+exec
-
before_exec
で振る舞いを自由に記述できる
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme
What you can do with signing up