📄 ch13.htm
字号:
<P>
<TT><FONT FACE="Courier">$key</FONT></TT> is set to either <TT><FONT FACE="Courier">&Ipc_PRIVATE</FONT></TT>
or an arbitrary constant. If <TT><FONT FACE="Courier">$key</FONT></TT>
is <TT><FONT FACE="Courier">&Ipc_PRIVATE</FONT></TT> or <TT><FONT FACE="Courier">$flag</FONT></TT>
has <TT><FONT FACE="Courier">&Ipc_CREAT</FONT></TT> set, the
message queue is created and its queue ID is returned in <TT><FONT FACE="Courier">$msgid</FONT></TT>.
For <TT><FONT FACE="Courier">&Ipc_EXCL</FONT></TT>, the object
must not already exist. If <TT><FONT FACE="Courier">msgget()</FONT></TT>
cannot create the message queue, <TT><FONT FACE="Courier">$msgid</FONT></TT>
is set to <TT><FONT FACE="Courier">undef</FONT></TT>.
<H2><A NAME="TheipcsCommand"><FONT SIZE=5 COLOR=#FF0000>The </FONT><TT><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">ipcs</FONT></TT><FONT SIZE=5 COLOR=#FF0000>
Command</FONT></A></H2>
<P>
After running the test script, you can see what the object created
looks like by using the <TT><FONT FACE="Courier">ipcs</FONT></TT>
command. The <TT><FONT FACE="Courier">ipcs</FONT></TT> command
lists the status of any Ipc objects in the system. Here is the
output from the <TT><FONT FACE="Courier">ipcs</FONT></TT> command
after creating the message queue.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">------ Shared Memory Segments --------
<BR>
shmid owner perms
bytes nattch status
<BR>
<BR>
------ Semaphore Arrays --------<BR>
semid owner perms
nsems status<BR>
<BR>
------ Message Queues --------<BR>
msqid owner perms
used-bytes messages<BR>
128 khusain 666
0
0</FONT></TT>
</BLOCKQUOTE>
<P>
The output from the <TT><FONT FACE="Courier">ipcs</FONT></TT>
command on your machine may be different than the one shown here.
However, most of the information should be the same. For instance,
in this example one message queue is shown as being created. The
ID of this queue is <TT><FONT FACE="Courier">128</FONT></TT>;
it is owned by <TT><FONT FACE="Courier">khusain</FONT></TT> and
has permissions of <TT><FONT FACE="Courier">0666</FONT></TT>,
thereby allowing any process to manipulate it. The message queue
has no messages in it and is not using any memory for queuing
messages.
<H2><A NAME="ThemsgsndandmsgrcvFunctions"><FONT SIZE=5 COLOR=#FF0000>The
</FONT><TT><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">msgsnd()</FONT></TT><FONT SIZE=5 COLOR=#FF0000>
and </FONT><TT><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">msgrcv()</FONT></TT><FONT SIZE=5 COLOR=#FF0000>
Functions</FONT></A></H2>
<P>
Use the <TT><FONT FACE="Courier">msgsnd()</FONT></TT> function
to send a message to a message queue. The syntax of the <TT><FONT FACE="Courier">msgsnd</FONT></TT>
function is this:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$err = msgsnd ($msgid, $message, $flags);</FONT></TT>
</BLOCKQUOTE>
<P>
<TT><FONT FACE="Courier">$msgid</FONT></TT> is the message queue
ID returned by <TT><FONT FACE="Courier">msgget()</FONT></TT>;
<TT><FONT FACE="Courier">$message</FONT></TT> is the content of
what you are sending (the content does not have to be text). The
<TT><FONT FACE="Courier">$flags</FONT></TT> specifies options
to use when sending the message. The <TT><FONT FACE="Courier">msgsnd()</FONT></TT>
function returns a non-zero value if the <TT><FONT FACE="Courier">send</FONT></TT>
operation succeeds and <TT><FONT FACE="Courier">0</FONT></TT>
if an error occurs. You can check <TT><FONT FACE="Courier">$!</FONT></TT>
for the <TT><FONT FACE="Courier">errno</FONT></TT> code if you
get a value of <TT><FONT FACE="Courier">0</FONT></TT> back from
this call.
<P>
Call the <TT><FONT FACE="Courier">msgrcv()</FONT></TT> function
to read messages from a message queue. The syntax of the <TT><FONT FACE="Courier">msgrcv</FONT></TT>
function is this:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$err = msgrcv ($msgid, $rcvd, $size,
$mesgtype, $flags);</FONT></TT>
</BLOCKQUOTE>
<P>
<TT><FONT FACE="Courier">$msgid</FONT></TT> is the ID of the message
queue. <TT><FONT FACE="Courier">$rcvd</FONT></TT> is a scalar
variable in which the incoming data is stored. <TT><FONT FACE="Courier">$size</FONT></TT>
is set to the number of bytes of the incoming message plus the
size of the message type.
<P>
The message type is specified in <TT><FONT FACE="Courier">$mesgtype</FONT></TT>
by the caller. If <TT><FONT FACE="Courier">$mesgtype</FONT></TT>
is <TT><FONT FACE="Courier">0</FONT></TT>, any message on the
queue is pulled off. A positive non-zero value implies that the
first message of the type equal to the value in <TT><FONT FACE="Courier">$mesgtype</FONT></TT>
will be pulled. A negative non-zero value of <TT><FONT FACE="Courier">$mesgtype</FONT></TT>
requests to pull any message whose ID is greater than the absolute
value of <TT><FONT FACE="Courier">$mesgtype</FONT></TT>.
<P>
<TT><FONT FACE="Courier">$flags</FONT></TT> specifies options
that affect the message. If <TT><FONT FACE="Courier">&Ipc_NOWAIT</FONT></TT>
is specified, the function returns immediately with the appropriate
error code. If the <TT><FONT FACE="Courier">&Ipc_WAIT</FONT></TT>
flag is set, the function waits until there is a message on the
queue. The <TT><FONT FACE="Courier">msgrcv()</FONT></TT> function
returns a non-zero value if a message has arrived; otherwise it
returns <TT><FONT FACE="Courier">0</FONT></TT>. You can check<B>
</B><TT><FONT FACE="Courier">$!</FONT></TT> for the <TT><FONT FACE="Courier">errno</FONT></TT>
code if you get a value of <TT><FONT FACE="Courier">0</FONT></TT>
back from this call.
<P>
Let's see how to send a message. A message has a long integer
as the first four bytes followed by the body of the message. The
first bytes are used as identifiers for each message. It's up
to the receiver to know how many bytes to expect from the type
of the message. First, Listing 13.2 presents a script that creates
a message queue using a unique key and then sends a message on
it.
<HR>
<BLOCKQUOTE>
<B>Listing 13.2. Creating a message queue and sending a message
on it.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/sys");
<BR>
3 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/linux");
<BR>
4 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/asm");
<BR>
5 require "ipc.ph";
<BR>
6 require "msg.ph";<BR>
7 $PERMISSIONS=0666;
<BR>
8 $ipckey = 42;<BR>
9 $msgid = msgget($ipckey,&Ipc_CREAT
| $PERMISSIONS);<BR>
10 printf "\n Message Id = $msgid \n";<BR>
11 $msg_type = 1;<BR>
12 $msg = pack("L a*", $msg_type, "Elvis Lives!");
<BR>
13 msgsnd($msgid, "$msg", &Ipc_NOWAIT);</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Don't forget to replace lines 2 through 4 with your machine's
specific path!
<P>
Lines 5 and 6 include the header files for the message queue facility.
Line 7 sets the permissions to be globally vulnerable; that is,
anyone can attach to or even destroy an object created with these
permissions. The <TT><FONT FACE="Courier">$ipckey</FONT></TT>
value is set to <TT><FONT FACE="Courier">42</FONT></TT> because
it's a unique number. Had this value been left as <TT><FONT FACE="Courier">Ipc_PRIVATE</FONT></TT>,
a new message queue would be created every time this script is
run. Too many queues will eat up system resources, so use these
scripts judiciously.
<P>
The message itself is created in lines 11 and 12 using the <TT><FONT FACE="Courier">pack</FONT></TT>
statement. The <TT><FONT FACE="Courier">L</FONT></TT> parameter
to pack sets up the message type, and the <TT><FONT FACE="Courier">a*</FONT></TT>
parameter specifies a null-terminated string. The message will
be 12 bytes long, including the null terminator for the string,
but not including the four-byte message type.
<P>
Line 13 is where the message is actually sent. The <TT><FONT FACE="Courier">&Ipc_NOWAIT</FONT></TT>
flag requests that the message returns immediately even if it
could not be sent. If you want to wait, use <TT><FONT FACE="Courier">&Ipc_WAIT</FONT></TT>
instead. Be warned, however, that the script making the call is
suspended until the message is sent.
<P>
To see if the message made it to the message queue, check the
output from the <TT><FONT FACE="Courier">ipcs</FONT></TT> command:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">------ Shared Memory Segments --------
<BR>
shmid owner perms
bytes nattch status
<BR>
<BR>
------ Semaphore Arrays --------<BR>
semid owner perms
nsems status<BR>
<BR>
------ Message Queues --------<BR>
msqid owner perms
used-bytes messages<BR>
512 khusain 666
12 1</FONT></TT>
</BLOCKQUOTE>
<P>
Note that there isn't a receiver to receive the message just yet.
If we do not create a receiving process, the messages in the queue
will just sit there until the queue is destroyed. Queues have
to be destroyed manually; the system will not destroy them for
you automatically.
<P>
There is one message with an ID of <TT><FONT FACE="Courier">512</FONT></TT>
and a length of 12 bytes in the queue. The message stays in the
queue until it's retrieved by something else. That something else
is the script shown in Listing 13.3.
<HR>
<BLOCKQUOTE>
<B>Listing 13.3. Receiving messages on the message queue.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/sys");
<BR>
3 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/linux");
<BR>
4 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/asm");
<BR>
5 require "ipc.ph";
<BR>
6 require "msg.ph";<BR>
7 $PERMISSIONS=0666;
<BR>
8 $ipckey = 42;<BR>
9 $msgid = msgget($ipckey,&Ipc_CREAT
| $PERMISSIONS);<BR>
10 printf "\n Message Id = $msgid";<BR>
11 $msg_type = 0;<BR>
12 #<BR>
13 # Keep in mind that the message packed was:<BR>
14 # $msg = pack("L a*", $msg_type, "Elvis Lives!");
<BR>
15 msgrcv($msgid, $msg, 80, $mgt_type, 0);<BR>
16 printf "\n Message Recvd = [%s]\n", $msg;</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Again, don't forget to modify lines 2 through 4 for your machine.
Line 15 in Listing 13.3 is of importance to us. Note how the message
type is set to <TT><FONT FACE="Courier">0</FONT></TT>, even though
the message type sent was <TT><FONT FACE="Courier">1</FONT></TT>.
The message type in the <TT><FONT FACE="Courier">msgrcv()</FONT></TT>
function can take three sets of values:
<UL>
<LI><FONT COLOR=#000000>If the message type is zero (0), to pull
off the next available message on the queue.</FONT>
<LI><FONT COLOR=#000000>If the message type is greater than zero,
to pull off only messages of the type explicitly specified in
the message type.</FONT>
<LI><FONT COLOR=#000000>If the message type is less than zero,
the absolute value of the message type is used. The first message
type greater than or equal to this type of message will be pulled
off the message queue.</FONT>
</UL>
<P>
Run the receiver script. The message queue should be empty now.
Let's confirm that the message queue is empty by examining the
output of the <TT><FONT FACE="Courier">ipcs</FONT></TT> command.
In the following output, look at the information for the message
queues. You should see zero for the number of messages and zero
bytes by the queue.
<BLOCKQUOTE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -