PerlでSigAction.c

TCP/IP Socket in cをPerlで振り返るシリーズの第5弾です。

少し昔にモテモテだったらしいLAMPエンジニアも廃れて、最近ではフルスタックエンジニアという万能型N型がモテモテらしい。

I型とかT型とか色々ありますけど、たとえば超人的(変人?)なI型の人って、その辺の一般的なT型と比較すると、N型に見えると思うんよね。
I型は古いとか言われるけど、そういう事ではなくて中途半端なとこで満足するなって事だと思うんだな。
何でもIを目指せばTにもNにもWにもなるはず。
最後にIは勝つって言いますし。

まぁ、そんな感じでTCP/IP Socket in Cは第5章に入りました。

ソケットオプションの項目ですが、PerlではC言語と違ってサイズの指定が不要なので以下のようになるようです。

use Socket qw(:all);

setsockopt(SOCKET, LEVEL, optName, optbal)
getsockopt(SOCKET, LEVEL, optName)

qwっていうのは今回初めて見るものだ。
指定もできるようだけど、のちのちのブロードキャストで再び出てくるだろうから、今はこれだけで終了しとくよ。

続いてシグナルで、プログラムはSigActionです。

シグナルの理解がだいぶ足りてなかったので、EchoServerに比べて随分と苦労しました。
C言語でも理解が足りておらず、もちろんそれを継承するのでPerlでも良く分かりません。

POSIXモジュールを使用すれば、POSIXで定義された関数を使用することができます。
ここでハンドラ関数ってなんじゃの?と調べ漁ってみる。

そのハンドラが対応すべき処理要求が発生するとプログラムの流れを中断して
ハンドラが呼び出され、要求された処理を実行する。
ハンドラはプログラム中で関数やサブルーチンなどの形で実装され、メモリ上に展開されるが
通常のプログラムの流れには組み込まれず、普段は待機している。

むむむむー、関数とサブルーチンとどう違うんだ。
関数やサブルーチンもメイン関数で呼ばなけりゃ、メモリ上に展開されるが待機してる事と同義じゃないか!!

と怒りながら、もう少し調べてみると

シグナルハンドラの実装
シグナルハンドラとは、シグナルをきっかけとして実行されるサブルーチンのことです。
シグナルとはOSがプロセスに送る合図です。

なるほど。
わたしってほんとバカ。

気を取り直して、とりあえず参考サイトをもとにしてSigIntを使ったプログラムを作ってみました。

# sigaction.c のつもり
# sigaction 使ってないけど・・・

#!/use/bin/perl

use strict;
use warnings;
use POSIX ();

sub handle_mon;

$SIG{'INT'} = 'Handle_mon';

while(1){}

exit(0);

sub Handle_mon
{
        print "Interrupt Received. Exiting Program.\n";
        exit 1;
}

実行結果

# perl sig.pl                                                  [/root/perl]
^CInterrupt Received. Exiting Program.

これでも動くんだけど、SigActionを使ってないから納得できない。

だが、これがまたなかなかうまくいかない!
キー!っとなってまた過程をメモしていなかったので、いきなり答えになります

orz

ソース

# sigaction.c のつもり

#!/use/bin/perl

use strict;
use warnings;
use POSIX ();
use POSIX qw(:signal_h);

sub handler();

print "うに\n";

my $sigset = POSIX::SigSet->new(SIGINT);

print "鉄火巻き\n";
my $sigaction = POSIX::SigAction->new( \&handler, $sigset,  &POSIX::SA_NOCLDSTOP  ) or die "failed\n";

print "ぶり\n";
#&handler = InterruptSignalHandler();

POSIX::sigaction(SIGINT, $sigaction);
print "いくら\n";

while(1){}

exit(0);

sub handler()
{
        print "Interrupt Received. Exiting Program.\n";
        exit 1;
}

デバッグ用のお寿司は残してあります。

実行結果

# perl sigaction.pl                                                                      [/root/perl]
うに
鉄火巻き
ぶり
いくら
^CInterrupt Received. Exiting Program.cha

いくら=whileで止まって、SIGINTが送られてhandler()が実行されます。

そして、Perlといえばネスト(入れ子)だよねっていうイメージがあるので、ちょこっとネストしました。

ソース

# sigaction.c のつもり

#!/use/bin/perl

use strict;
use warnings;
use POSIX ();
use POSIX qw(:signal_h);

sub handler();

print "鉄火巻き\n";
my $sigaction = POSIX::SigAction->new( \&handler, POSIX::SIGINT, &POSIX::SA_NOCLDSTOP  ) or die "failed\n";

print "ぶり\n";
#&handler = InterruptSignalHandler();

POSIX::sigaction(SIGINT, $sigaction);
print "いくら\n";

while(1){}

exit(0);

sub handler()
{
        print "Interrupt Received. Exiting Program.\n";
        exit 1;
}

実行結果は同じなので省略します。

こんな感じです。

Perlでも楽しいんだけど、C言語の方がやってて楽しいのは何故だろうか

参考サイト

Perldoc.jp

参考文献

TCP/IPソケットプログラミングC言語編
共著:Michael J.Donahoo/Kenneth L. calvert
訳:小高知宏

 

Similar Posts:


Leave a Reply

Your email address will not be published. Required fields are marked *