OS 3.4 について
Kei kamikawa
yomitanpm # 6
OS という講義の課題
Perl で Shell を実装した話
※ 内部で sh 使わない
Shell でできること?
• フォアグラウンド実行 -> ps -al
• バックグラウンド実行 -> ps -al &
• パイプ -> ps -al ¦ cat -n
• サブシェル -> (ps -al ¦ cat -n)
Shell でできること?
• フォアグラウンド実行 -> ps -al
• バックグラウンド実行 -> ps -al &
• パイプ -> ps -al ¦ cat -n
• サブシェル -> (ps -al ¦ cat -n)
Perl で shell コマンド実行する方法
• system("ps -al")
• `ps -al`
• open を使う
• exec("ps -al")
system("ps -al )
501 42571 729 4006 0 31 0 2466408 15044 - S+ 0 ttys001 0:00.32 /Users/
CodeHex/.plenv/versions/5.20.2/bin/perl5.20.2 /Users/CodeHex
501 42627 42571 6006 0 0 0 0 0 - Z+ 0 ttys001 0:00.00 (sh)
0 42656 42571 4106 0 31 0 2435172 968 - R+ 0 ttys001 0:00.00 ps -al
print `ps -al`
501 42571 729 4006 0 31 0 2466408 15044 - S+ 0 ttys001 0:00.33 /Users/
CodeHex/.plenv/versions/5.20.2/bin/perl5.20.2 /Users/CodeHex
501 42627 42571 6006 0 0 0 0 0 - Z+ 0 ttys001 0:00.00 (sh)
0 42658 42571 4106 0 31 0 2435172 968 - R+ 0 ttys001 0:00.00 ps -al
内部で sh が実行される
sh はいらないね!
なので!
今回は exec を使いました
※ 都合上 open は省略
#!/usr/bin/env perl
use strict;
use warnings;
my @cmd = ("ps", "-al");
if (fork) {
wait;
} else {
exec @cmd;
}
例
exec には list を渡したほうがいいらしい
exec.pl
exec "ps -al"
501 42860 729 4006 0 31 0 2445592 2244 - S+ 0 ttys001 0:00.02 perl k.pl
0 42898 42860 4106 0 31 0 2444388 980 - R+ 0 ttys001 0:00.00 ps -al
_人人人人人人人人_
> sh がいない!! <
 ̄Y^Y^Y^Y^Y^Y^Y ̄
Shell でできること?
• フォアグラウンド実行 -> ps -al
• バックグラウンド実行 -> ps -al &
• パイプ -> ps -al ¦ cat -n
• サブシェル -> (ps -al ¦ cat -n)
#!/usr/bin/env perl
use strict;
use warnings;
my @cmd = ("ps", "-al");
if (!fork) {
exec @cmd;
}
例
exec_bg.pl
Shell でできること?
• フォアグラウンド実行 -> ps -al
• バックグラウンド実行 -> ps -al &
• パイプ -> ps al ¦ cat -n
• サブシェル -> (ps al ¦ cat -n)
ところで
標準ストリーム知ってますか?
標準ストリーム
• STDIN (Standard input) <= 標準入力
• STDOUT (Standard output) <= 標準出力
• STDERR (Standard error) <= 標準エラー出力
例えば
ps al ¦ cat -n
ps al ¦ cat -n
STDOUT
or
STDERR
STDIN
結果を渡す
※あくまでイメージです
STDIN
or
Not
STDOUT
or
STDERR
➀
➁ ➂
➃
#!/usr/bin/env perl
use strict;
use warnings;
my @cmd1 = ("ps", "al");
my @cmd2 = ("cat", "-n");
pipe READ1, WRITE1;
pipe READ2, WRITE2;
if (fork) {
close READ1;
close WRITE2;
wait;
open STDIN, ">&", READ2;
exec @cmd2;
} else {
close READ2;
close WRITE1;
open STDOUT, ">&", WRITE2;
exec @cmd1;
}
例
pipe.pl
複数パイプは?
案. パイプの配列を作る
例えば
ps -al ¦ cat -n ¦ cowsay
ps -al ¦ cat -n ¦ cowsay
STDIN
or
Not
STDOUT
or
STDERR
STDIN
STDOUT
or
STDERR
STDIN
STDOUT
or
STDERR
STDIN
or
Not
STDOUT
or
STDERR
STDIN
STDOUT
or
STDERR
STDIN
STDOUT
or
STDERR
こういう並びのパイプの配列を用
意すればできる…!?
コードビュー(10秒)
multi_pipe.pl
Shell でできること?
• フォアグラウンド実行 -> ps -al
• バックグラウンド実行 -> ps -al &
• パイプ -> ps al ¦ cat -n
• サブシェル -> (ps al ¦ cat -n)
サブシェルって?
shell が shell を起動
PPIDPID
親プロセス 729 が 子プロセス 48015 を起動している
これを再現
コードビュー(10秒)
sub_perl.pl
ご静聴ありがとうございました
😄

Yomitanpm 6