⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch13.htm

📁 《Perl 5 Unreleased》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<P>

<TT><FONT FACE="Courier">$key</FONT></TT> is set to either <TT><FONT FACE="Courier">&amp;Ipc_PRIVATE</FONT></TT>

or an arbitrary constant. If <TT><FONT FACE="Courier">$key</FONT></TT>

is <TT><FONT FACE="Courier">&amp;Ipc_PRIVATE</FONT></TT> or <TT><FONT FACE="Courier">$flag</FONT></TT>

has <TT><FONT FACE="Courier">&amp;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">&amp;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&nbsp;&nbsp;&nbsp;&nbsp; owner&nbsp;&nbsp;&nbsp;&nbsp; perms&nbsp;&nbsp;&nbsp;&nbsp;

bytes&nbsp;&nbsp;&nbsp;&nbsp; nattch&nbsp;&nbsp;&nbsp;&nbsp;status

<BR>

<BR>

------ Semaphore Arrays --------<BR>

semid&nbsp;&nbsp;&nbsp;&nbsp; owner&nbsp;&nbsp;&nbsp;&nbsp; perms&nbsp;&nbsp;&nbsp;&nbsp;

nsems&nbsp;&nbsp;&nbsp;&nbsp; status<BR>

<BR>

------ Message Queues --------<BR>

msqid&nbsp;&nbsp;&nbsp;&nbsp; owner&nbsp;&nbsp;&nbsp;&nbsp; perms&nbsp;&nbsp;&nbsp;&nbsp;

used-bytes&nbsp;&nbsp;messages<BR>

128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; khusain&nbsp;&nbsp;&nbsp;666&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

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">&amp;Ipc_NOWAIT</FONT></TT>

is specified, the function returns immediately with the appropriate

error code. If the <TT><FONT FACE="Courier">&amp;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">&nbsp;1 #!/usr/bin/perl<BR>

&nbsp;2 unshift (@Inc,&quot;/usr/lib/perl5/i486-linux/5.002/sys&quot;);

<BR>

&nbsp;3 unshift (@Inc,&quot;/usr/lib/perl5/i486-linux/5.002/linux&quot;);

<BR>

&nbsp;4 unshift (@Inc,&quot;/usr/lib/perl5/i486-linux/5.002/asm&quot;);

<BR>

&nbsp;5 require &quot;ipc.ph&quot;;

<BR>

&nbsp;6 require &quot;msg.ph&quot;;<BR>

&nbsp;7 $PERMISSIONS=0666;

<BR>

&nbsp;8 $ipckey = 42;<BR>

&nbsp;9 $msgid = msgget($ipckey,&amp;Ipc_CREAT

| $PERMISSIONS);<BR>

10 printf &quot;\n&nbsp;&nbsp;Message Id = $msgid \n&quot;;<BR>

11 $msg_type = 1;<BR>

12 $msg = pack(&quot;L a*&quot;, $msg_type, &quot;Elvis Lives!&quot;);

<BR>

13 msgsnd($msgid, &quot;$msg&quot;, &amp;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">&amp;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">&amp;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&nbsp;&nbsp;&nbsp;&nbsp; owner&nbsp;&nbsp;&nbsp;&nbsp; perms&nbsp;&nbsp;&nbsp;&nbsp;

bytes&nbsp;&nbsp;&nbsp;&nbsp; nattch&nbsp;&nbsp;&nbsp;&nbsp;status

<BR>

<BR>

------ Semaphore Arrays --------<BR>

semid&nbsp;&nbsp;&nbsp;&nbsp; owner&nbsp;&nbsp;&nbsp;&nbsp; perms&nbsp;&nbsp;&nbsp;&nbsp;

nsems&nbsp;&nbsp;&nbsp;&nbsp; status<BR>

<BR>

------ Message Queues --------<BR>

msqid&nbsp;&nbsp;&nbsp;&nbsp; owner&nbsp;&nbsp;&nbsp;&nbsp; perms&nbsp;&nbsp;&nbsp;&nbsp;

used-bytes&nbsp;&nbsp;messages<BR>

512&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; khusain&nbsp;&nbsp;&nbsp;666&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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">&nbsp;1 #!/usr/bin/perl<BR>

&nbsp;2 unshift (@Inc,&quot;/usr/lib/perl5/i486-linux/5.002/sys&quot;);

<BR>

&nbsp;3 unshift (@Inc,&quot;/usr/lib/perl5/i486-linux/5.002/linux&quot;);

<BR>

&nbsp;4 unshift (@Inc,&quot;/usr/lib/perl5/i486-linux/5.002/asm&quot;);

<BR>

&nbsp;5 require &quot;ipc.ph&quot;;

<BR>

&nbsp;6 require &quot;msg.ph&quot;;<BR>

&nbsp;7 $PERMISSIONS=0666;

<BR>

&nbsp;8 $ipckey = 42;<BR>

&nbsp;9 $msgid = msgget($ipckey,&amp;Ipc_CREAT

| $PERMISSIONS);<BR>

10 printf &quot;\n&nbsp;&nbsp;Message Id = $msgid&quot;;<BR>

11 $msg_type = 0;<BR>

12 #<BR>

13 # Keep in mind that the message packed was:<BR>

14 # $msg = pack(&quot;L a*&quot;, $msg_type, &quot;Elvis Lives!&quot;);

<BR>

15 msgrcv($msgid, $msg, 80, $mgt_type, 0);<BR>

16 printf &quot;\n Message Recvd = [%s]\n&quot;, $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 + -