この記事はRustその2 Advent Calendar 2017 17日目の記事です。
本記事ではUnix系システムプログラミングを行うのに便利なnix crate
について簡単にご紹介できればと思います。
nix crateとは
nix crate
はいわゆるラッパーです。
RustにはC言語の型を定義したlibc crate
があり、このcrate
を利用すればfork
、execv
、clone
などのC言語でおなじみの関数を扱えます。
しかしこのlibc crate
の関数の多くはunsafe
となっており、コンパイル時に安全であることを保証できないコードを書けるようになる為、取り扱いには注意が必要となってしまいます。
nix crate
はこのlibc crate
のunsafe
な部分をラップしたunsafe
でないAPIを提供しているので、libc crate
の機能をより安全に利用できます。
使用例
nix crate
を使用してclone
を実行する例は下記のようになります。
まずCargo.toml
に依存関係を記述します。
[dependencies]
nix = "0.9.0"
次にソース上でnix crate
を利用することを宣言し、clone
が実装されているsched
モジュールをインポートします。
(下記ではsched
モジュールの中身をすべてインポートしています。)
extern crate nix;
use nix::sched::*;
後は、インポートしたsched
モジュールを利用してclone
を実行する記述を書くだけです。
(プロセスの情報を出力させるのにpentry crate
を利用しています。)
extern crate nix;
extern crate pentry;
use nix::sched::*;
// プロセス情報出力処理
fn print_process_info() {
if let Ok(ps) = pentry::current() {
println!("{:?}", ps);
}
}
// cloneしたプロセスで実行する処理
fn child() -> isize {
// プロセス情報出力
print_process_info();
// 成功時は0を返す
0
}
fn main() {
// プロセス情報出力
print_process_info();
// stackのサイズ
const STACK_SIZE: usize = 1024 * 1024;
let ref mut stack: [u8; STACK_SIZE] = [0; STACK_SIZE];
// cloneで実行する処理
let cb = Box::new(|| child());
// clone時に指定するフラグ(今回はフラグは指定しない)
let clone_flags = CloneFlags::empty();
// clone
let p = clone(cb, stack, clone_flags, None);
let p = match p {
Ok(p) => p,
Err(err) => panic!(err),
}
}
Process { pid: 2163, ppid: 1992, name: "clone", path: Some("/home/ubuntu/Rust/sample/target/debug/sample") }
Process { pid: 2180, ppid: 2163, name: "clone", path: Some("/home/ubuntu/Rust/sample/target/debug/sample") }
実行すると環境により出力結果は異なりますが、clone
した子プロセスの親プロセスIDppid
が、親のプロセスIDpid
となっているはずです。
まとめ
nix crate
を利用してlibc crate
の関数を利用することができました。
unsafe
でない分nix crate
を利用するとより安全になるのかと思います。