前言: perl和C語言都提供了消息隊列的機制,而且這兩種語言中的消息隊列可以相互兼容. 當涉及到系統架構時, 可以用C語言實現核心計算模塊,用Perl實現業務邏輯層, 而這兩層間可以通過消息隊列來實現不同語言的進程間的通信. 本文先用兩個示例程序講解Perl對消息隊列的實現。 再一個示例程序講解Perl與C之間使用消息隊列進行進程間的通信. 一. 使用IPC::SysV和IPC::Msg模塊訪問Unix消息隊列 例一, 單個進程中實現消息隊列的訪問(Perl實現) File: msg_single_process.pl 1. #!/usr/bin/perl 2. use strict; 3. use warnings; 4. use IPC::SysV qw(IPC_PRIVATE S_IRWXU S_IRWXG S_IRWXO IPC_CREAT IPC_NOWAIT); 5. use IPC::Msg; 6. my($key, $msg, $msgid, $msgtype, $buf); 7. $key = IPC::SysV::ftok(".",'1'); 8. $msg = new IPC::Msg($key, 0666 | IPC_CREAT) or die "create message queue: $!"; 9. $msgtype = 1; 10.$msgid = $msg->id(); 11.print "MSG_ID: ",$msgid,"\n"; 12.$msg->snd($msgtype, "test", IPC_NOWAIT) or die "send message failed: $!"; 13.$msg->rcv($buf, 1024) or die "receive message failed: $!"; 14.print "BUFFER: ",$buf,"\n"; 15.$msg->remove(); 代碼解釋: 4.使用IPC::SysV模塊, qw(IPC_PRIVATE S_IRWXU S_IRWXG S_IRWXO IPC_CREAT IPC_NOWAIT) 等同於("IPC_PRIVATE S_IRWXU S_IRWXG S_IRWXO IPC_CREAT IPC_NOWAIT"), 表示本程序將從該模塊引入若干符號, 在後續的代碼裡面需要要指定模塊名就可以使用這些符號; 5.使用IPC::Msg模塊(消息隊列); 6.定義私有變量; 7.用ftok通過文件名獲得一個key_t值,這裡使用是當前目錄. 類似C語言中的ftok函數,這個文件必須實際存在; 8.獲得Msg對象。類似msgget函數; 9.指定消息類型; 10.獲得消息隊列的標識符; 12.發送消息。類似msgsnd函數; 13.接收消息。類似msgrcv函數; 15.刪除消息隊列; 更多的信息,可以參考IPC::Msg模塊定義: http://search.cpan.org/~mhx/IPC-SysV-2.03/lib/IPC/Msg.pm 例二.在兩個進程間使用消息隊列進行通信(Perl實現) File: msg_snd.pl #!/usr/bin/perl use strict; use warnings; use IPC::SysV qw(IPC_PRIVATE S_IRWXU S_IRWXG S_IRWXO IPC_CREAT IPC_NOWAIT); use IPC::Msg; my($key, $msg, $msgid, $msgtype, $buf); $key = IPC::SysV::ftok(".",'1'); $msg = new IPC::Msg($key, 0666 | IPC_CREAT) or die "create message queue: $!"; $msgtype = 1; $msgid = $msg->id(); print "MSG_ID: ",$msgid,"\n"; my $pal; foreach $pal('Tom','Dick','Harry','Pete','Hank') { $msg->snd($msgtype, "Hi, $pal", IPC_NOWAIT) or die "send message failed: $!"; print "BUFFER: ",$pal,"\n"; } # end $msg->snd($msgtype, "end", IPC_NOWAIT) or die "send message failed: $!"; print "BUFFER: end\n"; File: msg_rcv.pl #!/usr/bin/perl use strict; use warnings; use IPC::SysV qw(IPC_PRIVATE S_IRWXU S_IRWXG S_IRWXO IPC_CREAT IPC_NOWAIT); use IPC::Msg; my($key, $msg, $msgid, $msgtype, $buf); $key = IPC::SysV::ftok(".",'1'); $msg = new IPC::Msg($key, 0666 | IPC_CREAT) or die "create message queue: $!"; $msgtype = 1; $msgid = $msg->id(); print "MSG_ID: ",$msgid,"\n"; my $running = 1; while ($running) { $msg->rcv($buf, 1024) or die "receive message failed: $!"; print "BUFFER: ",$buf,"\n"; if($buf eq "end") { $running = 0; } } $msg->remove(); 二. C與Perl進程間的消息隊列通信 接收端使用Perl實現 msg_rcv.pl #!/usr/bin/perl use strict; use warnings; use IPC::SysV qw(IPC_PRIVATE S_IRWXU S_IRWXG S_IRWXO IPC_CREAT IPC_NOWAIT); use IPC::Msg; my($key, $msg, $msgid, $msgtype, $buf); #$key = IPC::SysV::ftok(".",'1'); $key = 1234; $msg = new IPC::Msg($key, 0666 | IPC_CREAT) or die "create message queue: $!"; $msgtype = 1; my $running = 1; while ($running) { $msg->rcv($buf, 1024) or die "receive message failed: $!"; print "BUFFER: ",$buf,"\n"; my $pos = index($buf, "end", 0); print "POS: ",$pos,"\n"; if ($pos != -1) { $running = 0; } } $msg->remove(); 發送端采用C代碼實現 msg_snd.c #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/msg.h> #define MAX_TEXT 512 struct my_msg_st { long int my_msg_type; char some_text[MAX_TEXT]; }; int main() { int index; struct my_msg_st some_data; int msgid; msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if (msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } for (index = 0; index < 10; index++) { memset(some_data.some_text, 0, MAX_TEXT); some_data.my_msg_type = 1; snprintf(some_data.some_text,MAX_TEXT, "%s~%d","index",index); if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } } /* ending */ memset(some_data.some_text, 0, MAX_TEXT); some_data.my_msg_type = 1; snprintf(some_data.some_text,MAX_TEXT, "%s","end"); if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } 編譯與運行: $gcc -g -Wall -o msg_snd msg_snd_c.c $./msg_rcv.pl & $./msg_snd 輸出: MSG_ID: 393219 BUFFER: index~0 BUFFER: index~1 BUFFER: index~2 BUFFER: index~3 BUFFER: index~4 BUFFER: index~5 BUFFER: index~6 BUFFER: index~7 BUFFER: index~8 BUFFER: index~9 BUFFER: end