📄 ch13.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 13 -- Messaging Facilities: The System
V Ipc Functions</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 13</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Messaging Facilities: The System
V Ipc Functions</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#AnIntroductiontotheSystemVIpc" >An Introduction to the System V Ipc</A>
<LI><A HREF="#UsingtheUNIXSystemVIpcFunctions" >Using the UNIX System V Ipc Functions</A>
<UL>
<LI><A HREF="#ThemsggetFunction" >The msgget() Function</A>
</UL>
<LI><A HREF="#TheipcsCommand" >The ipcs Command</A>
<LI><A HREF="#ThemsgsndandmsgrcvFunctions" >The msgsnd() and msgrcv() Functions</A>
<LI><A HREF="#SharedMemory" >Shared Memory</A>
<UL>
<LI><A HREF="#TheshmwriteandshmreadFunctions" >The shmwrite() and shmread() Functions</A>
</UL>
<LI><A HREF="#Semaphores" >Semaphores</A>
<LI><A HREF="#TheSysVIpcModule" >The SysV::Ipc Module</A>
<LI><A HREF="#ApplicationsofIpc" >Applications of Ipc</A>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
This chapter introduces you to the Interprocess Communications
(Ipc) functionality of message queues, shared memory, and semaphores.
The Ipc facilities provide a clean, consistent solution to passing
data between processes on the same machine. (Sockets can extend
across platforms and a network.)
<H2><A NAME="AnIntroductiontotheSystemVIpc"><FONT SIZE=5 COLOR=#FF0000>An
Introduction to the System V Ipc</FONT></A></H2>
<P>
The UNIX system V Ipc enables you to perform the following tasks:
<UL>
<LI><FONT COLOR=#000000>Send messages from one process to another
via a message queue. Processes can add messages to, check the
length of, and remove messages from a queue. </FONT>
<LI><FONT COLOR=#000000>Create and handle shared memory. This
includes the capability to read from and write into areas of shared
memory. </FONT>
<LI><FONT COLOR=#000000>Create and handle semaphores. This includes
the capability to read, set, and reset semaphore values. </FONT>
</UL>
<P>
Each Ipc function is available to calling processes as a system
resource. These resources are available for all processes on a
system-level basis and can be shared by many processes on the
same system. Ipc resources are limited to the system they reside
on and do not offer networking functionality. Because there are
only a limited number of Ipc resources on any UNIX system, it's
important to free up each resource after using it. This is because
each Ipc resource can exist for a long time after the process
that created it has finished executing.
<P>
Each Ipc resource is referred to as an object in the operating
system. For working with Ipc resources, you either have to create
an object or use an existing one. Ipc objects are created via
a <TT><FONT FACE="Courier">get()</FONT></TT> function for that
object. Each <TT><FONT FACE="Courier">get()</FONT></TT> function
call requires a unique positive Ipc key as the identifier for
that object. Keys are converted by the kernel into an ID number
and returned by the <TT><FONT FACE="Courier">get()</FONT></TT>
function. Then the ID is used by other related functions to refer
to that object for all other operations.
<P>
An Ipc key is a long integer and is used to name the Ipc resource.
A key is assigned by the programmer but could also be assigned
by the system. The keys for shared memory, message queues, and
semaphores are unique in the sense that the same key number can
be assigned to Ipc objects of different types. That is, a semaphore
with a key of 11 can coexist on the same system with a message
queue with a key of 11. However, another semaphore cannot coexist
with a key of 11 on the same system. Programmers can force the
underlying operating system to assign a key by specifying the
<TT><FONT FACE="Courier">&Ipc_PRIVATE</FONT></TT> flag (this
is explained shortly).
<P>
When you pass in a key number to a <TT><FONT FACE="Courier">get()</FONT></TT>
function, an ID is returned. Once an object is created and its
ID is returned, the object must then be referred to by its ID.
You can draw the analogy that a file handle is to a file as an
ID is to an Ipc resource. The returned IDs are positive if there
are no errors. (A negative ID is returned if there is an error.)
<P>
You can create a unique key by using the <TT><FONT FACE="Courier">&Ipc_PRIVATE</FONT></TT>
flags if you are not imaginative enough. The kernel then creates
the ID and the key for you.
<P>
Ipc objects are global. Once created, the object is available
to all the processes in the system. In this respect, you have
to be careful how you access the available resources because any
process can overwrite your shared memory, message queue, or semaphore.
Also, your Ipc object remains in memory long after your process
has gone. You, not the kernel, are responsible for cleanup.
<P>
When you create the object, you also have to specify permissions.
The format of the permissions is very similar to that of files:
three groups of read/write for owner, group, and other. The execute
permission bits for the permissions are ignored by the Ipc calls.
To get access to an existing object, you have to specify <TT><FONT FACE="Courier">0</FONT></TT>
for permissions.
<P>
The following flags are permitted for creating objects:<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=119><I>Flag</I></TD><TD WIDTH=471><I>Description</I>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=119><TT><FONT FACE="Courier">&Ipc_CREAT</FONT></TT>
</TD><TD WIDTH=471>This flag creates an Ipc object given a key, or it attaches to an existing object with the same key.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=119><TT><FONT FACE="Courier">&Ipc_EXCL</FONT></TT>
</TD><TD WIDTH=471>This flag creates an Ipc object given a key. It returns an error if the object with this key already exists. This prevents two unrelated processes from creating two objects with the same key.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=119><TT><FONT FACE="Courier">&Ipc_RMID</FONT></TT>
</TD><TD WIDTH=471>Given an ID, this flag removes the object from the system. You must have the permissions on the object to be able to delete it.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=119><TT><FONT FACE="Courier">&Ipc_STAT</FONT></TT>
</TD><TD WIDTH=471>Given an ID, this flag returns the values of each member of an Ipc object.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=119><TT><FONT FACE="Courier">&Ipc_SET</FONT></TT>
</TD><TD WIDTH=471>Given an ID and a data structure for an object, this flag sets the values of each member of the corresponding Ipc object.
</TD></TR>
</TABLE></CENTER>
<H2><A NAME="UsingtheUNIXSystemVIpcFunctions"><FONT SIZE=5 COLOR=#FF0000>Using
the UNIX System V Ipc Functions</FONT></A></H2>
<P>
With Perl you can access all of the Ipc functions via a standard
set of library functions. The information required for the functions
is consistent with a UNIX system interface; therefore, the information
in a UNIX <TT><FONT FACE="Courier">man</FONT></TT> page will provide
enough information about the facilities available on your system.
<P>
System V Ipc functions are defined in Perl header files. For a
Perl installation on a UNIX system, the required information is
in the <TT><FONT FACE="Courier">*.ph</FONT></TT> files. (The <TT><FONT FACE="Courier">ph</FONT></TT>
stands for Perl header.) The following files will be required
by most of the Perl scripts you write to utilize the Ipc facilities:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">require "ipc.ph";<BR>
require "msg.ph";<BR>
require "sem.ph";<BR>
require "shm.ph";</FONT></TT>
</BLOCKQUOTE>
<P>
Keep in mind that this might not work as shown here. Here are
the primary reasons an error occurs when you try to include these
files with the <TT><FONT FACE="Courier">require</FONT></TT> statement:
<UL>
<LI><FONT COLOR=#000000>The </FONT><TT><FONT FACE="Courier">*.ph</FONT></TT>
files do not exist.
<LI><FONT COLOR=#000000>The </FONT><TT><FONT FACE="Courier">*.ph</FONT></TT>
files do exist but are not in the path(s) specified by the <TT><FONT FACE="Courier">@Inc</FONT></TT>
<TT><FONT FACE="Courier">include</FONT></TT> variable.
</UL>
<P>
To cure these problems, you'll have to run the <TT><FONT FACE="Courier">h2ph</FONT></TT>
script in the <TT><FONT FACE="Courier">/usr/lib/perl</FONT></TT>
directory. The <TT><FONT FACE="Courier">h2ph</FONT></TT> script
contains a line (around line 9) that has the variable <TT><FONT FACE="Courier">$perlincl</FONT></TT>
set to a directory. On my machine, this variable is set to <TT><FONT FACE="Courier">/usr/lib/perl5/i486-linux/5.002</FONT></TT>.
On your machine, this value might be different. In any event,
the value of <TT><FONT FACE="Courier">$perlincl</FONT></TT> is
the directory where the <TT><FONT FACE="Courier">*.ph</FONT></TT>
files are stored by the <TT><FONT FACE="Courier">h2ph</FONT></TT>
script.
<P>
Now go to the <TT><FONT FACE="Courier">/usr/include</FONT></TT>
directory and, as root, run the <TT><FONT FACE="Courier">h2ph</FONT></TT>
command as shown here:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">h2ph * sys/*</FONT></TT>
</BLOCKQUOTE>
<P>
The include files on your system may require that more subdirectories
be included in the paths specified to this program. For example,
on a Linux 3.0 system, the command to get most of the required
files is this:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">h2ph * sys/* asm/* linux/*</FONT></TT>
</BLOCKQUOTE>
<P>
The only clear way to know which files are required is to include
the Perl header files in a sample script. If everything goes well,
you should be able to get the script to run. The sample script
shown in Listing 13.1 gives two ignorable warnings on all three
different Linux versions. The script does manage to create the
message queue as expected. I cover the topic of message queues
in the section "Shared Memory," later in this chapter.
<HR>
<BLOCKQUOTE>
<B>Listing 13.1. A sample script to test Perl header file inclusion.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 <BR>
3 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/sys");
<BR>
4 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/linux");
<BR>
5 unshift (@Inc,"/usr/lib/perl5/i486-linux/5.002/asm");
<BR>
6 <BR>
7 print "@Inc";
<BR>
8 <BR>
9 require "ipc.ph";
<BR>
10 require "msg.ph";<BR>
11 require "shm.ph";<BR>
12 require "sem.ph";<BR>
13 <BR>
14 $PERMISSIONS=0666;<BR>
15 $ipckey = &Ipc_PRIVATE;<BR>
16 <BR>
17 $msgid = msgget($ipckey,&Ipc_CREAT | &Ipc_EXCL | $PERMISSIONS);
<BR>
18 <BR>
19 printf "\n Message Id = $msgid";</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The three required files in the sample script are included for
message queues, shared memory, and semaphores, respectively. Only
those that are required have to be included. That is, you do not
have to include <TT><FONT FACE="Courier">shm.ph</FONT></TT> if
you aren't going to be using shared memory. The <TT><FONT FACE="Courier">ipc.ph</FONT></TT>
file is required for any of these three features.
<P>
<TT><FONT FACE="Courier">PERMISSIONS</FONT></TT> is set to <TT><FONT FACE="Courier">0666</FONT></TT>,
meaning that any process can work with or even delete the Ipc
object in question. For a more secure system, you might consider
using <TT><FONT FACE="Courier">0600</FONT></TT> to give permissions
to the owner process only.
<H3><A NAME="ThemsggetFunction">The <TT><FONT SIZE=4 FACE="Courier">msgget()</FONT></TT><FONT SIZE=4>
Function</FONT></A></H3>
<P>
In Listing 13.1 an Ipc message queue was created. To use the System
V message-passing facility, you first create a message queue ID
for a given message queue. Here's the syntax of the <TT><FONT FACE="Courier">msgget()</FONT></TT>
function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$msgid = msgget (<I>$key, $flag</I>);</FONT></TT>
</BLOCKQUOTE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -