Welcome to pickSourcecode.com Login | Register    
pickZy.com
 Home  | search  | games  | General  | C  | C++  | Java  | Php  | Networking  | Visual Basic  | VC++  | Win32  | MFC  | JavaScript  | Jobs  | JavaScript  | Post jobs
IPC (Inter Process Communication) - Message Queues       Share
2008-11-18 |  MalathiVanaraj  | Viewed: 2108  |    2

Basic Message Passing

IPC messaging lets processes send and receive messages, and queue messages for processing in an arbitrary order. Unlike the file byte-stream data flow of pipes, each IPC message has an explicit length. Messages can be assigned a specific type. Because of this, a server process can direct message traffic between clients on its queue by using the client process PID as the message type. For single-message transactions, multiple server processes can work in parallel on transactions sent to a shared message queue.

Before a process can send or receive a message, the queue must be initialized (through the msgget function see below) Operations to send and receive messages are performed by the msgsnd() and msgrcv() functions, respectively.

When a message is sent, its text is copied to the message queue. The msgsnd() and msgrcv() functions can be performed as either blocking or non-blocking operations. Non-blocking operations allow for asynchronous message transfer -- the process is not suspended as a result of sending or receiving a message. In blocking or synchronous message passing the sending process cannot continue until the message has been transferred or has even been acknowledged by a receiver. IPC signal and other mechanisms can be employed to implement such transfer. A blocked message operation remains suspended until one of the following three conditions occurs:

  • The call succeeds.
  • The process receives a signal.
  • The queue is removed.
Initializing the Message Queue

The msgget() function initializes a new message queue:

int msgget(key_t key, int msgflg)

It can also return the message queue ID (msqid) of the queue corresponding to the key argument. The value passed as the msgflg argument must be an octal integer with settings for the queue's permissions and control flags.

The following code illustrates the msgget() function.

#include <sys/ipc.h>; 
#include <sys/msg.h>;

...


key_t key; /* key to be passed to msgget() */
int msgflg /* msgflg to be passed to msgget() */
int msqid; /* return value from msgget() */

...
key = ...
msgflg = ...

if ((msqid = msgget(key, msgflg)) == &ndash;1)
{
perror("msgget: msgget failed");
exit(1);
} else
(void) fprintf(stderr, &ldquo;msgget succeeded");

...

IPC Functions, Key Arguments and Creation Flags

Processes requesting access to an IPC facility must be able to identify it. To do this, functions that initialize or provide access to an IPC facility use a key_t key argument. (key_t is essentially an int type defined in <sys/types.h>

The key is an arbitrary value or one that can be derived from a common seed at run time. One way is with ftok() , which converts a filename to a key value that is unique within the system. Functions that initialize or get access to messages (also semaphores or shared memory see later) return an ID number of type int. IPC functions that perform read, write, and control operations use this ID. If the key argument is specified as IPC_PRIVATE, the call initializes a new instance of an IPC facility that is private to the creating process. When the IPC_CREAT flag is supplied in the flags argument appropriate to the call, the function tries to create the facility if it does not exist already. When called with both the IPC_CREAT and IPC_EXCL flags, the function fails if the facility already exists. This can be useful when more than one process might attempt to initialize the facility. One such case might involve several server processes having access to the same facility. If they all attempt to create the facility with IPC_EXCL in effect, only the first attempt succeeds. If neither of these flags is given and the facility already exists, the functions to get access simply return the ID of the facility. If IPC_CREAT is omitted and the facility is not already initialized, the calls fail. These control flags are combined, using logical (bitwise) OR, with the octal permission modes to form the flags argument. For example, the statement below initializes a new message queue if the queue does not exist.

msqid = msgget(ftok("/tmp",
key), (IPC_CREAT | IPC_EXCL | 0400));

Controlling the Message Queues:

 

The first argument evaluates to a key based on the string ("/tmp"). The second argument evaluates to the combined permissions and control flags.

The msgctl() function alters the permissions and other characteristics of a message queue. The owner or creator of a queue can change its ownership or permissions using msgctl() Also, any process with permission to do so can use msgctl() for control operations.

The msgctl() function is prototypes as follows:

int msgctl(int msqid, int cmd, struct msqid_ds *buf )

The msqid argument must be the ID of an existing message queue. The cmd argument is one of:

IPC_STAT
-- Place information about the status of the queue in the data structure pointed to by buf. The process must have read permission for this call to succeed.
IPC_SET
-- Set the owner's user and group ID, the permissions, and the size (in number of bytes) of the message queue. A process must have the effective user ID of the owner, creator, or superuser for this call to succeed.
IPC_RMID
-- Remove the message queue specified by the msqid argument.

The following code illustrates the msgctl() function with all its various flags:

#include<sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
...
if (msgctl(msqid, IPC_STAT, &buf) == -1) {
perror("msgctl: msgctl failed");
exit(1);
}
...
if (msgctl(msqid, IPC_SET, &buf) == -1) {
perror("msgctl: msgctl failed");
exit(1);
}
...

Sending and Receving Messages

The msgsnd() and msgrcv() functions send and receive messages, respectively:

int msgsnd(int msqid, const void *msgp, size_t msgsz,
int msgflg);

int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);

The msqid argument must be the ID of an existing message queue. The msgp argument is a pointer to a structure that contains the type of the message and its text. The structure below is an example of what this user-defined buffer might look like:

struct mymsg {
long mtype; /* message type */
char mtext[MSGSZ]; /* message text of length MSGSZ */
}

The msgsz argument specifies the length of the message in bytes.

The structure member msgtype is the received message's type as specified by the sending process.

The argument msgflg specifies the action to be taken if one or more of the following are true:

  • The number of bytes already on the queue is equal to msg_qbytes.
  • The total number of messages on all queues system-wide is equal to the system-imposed limit.
These actions are as follows:
  • If (msgflg & IPC_NOWAIT) is non-zero, the message will not be sent and the calling process will return immediately.
  • If (msgflg & IPC_NOWAIT) is 0, the calling process will suspend execution until one of the following occurs:
    • The condition responsible for the suspension no longer exists, in which case the message is sent.
    • The message queue identifier msqid is removed from the system; when this occurs, errno is set equal to EIDRM and -1 is returned.
    • The calling process receives a signal that is to be caught; in this case the message is not sent and the calling process resumes execution.

    Upon successful completion, the following actions are taken with respect to the data structure associated with msqid:

    • msg_qnum is incremented by 1.
    • msg_lspid is set equal to the process ID of the calling process.
    • msg_stime is set equal to the current time.

The following code illustrates msgsnd() and msgrcv():

#include <sys/types.h> 
#include <sys/ipc.h>
#include <sys/msg.h>

...

int msgflg; /* message flags for the operation */
struct msgbuf *msgp; /* pointer to the message buffer */
int msgsz; /* message size */
long msgtyp; /* desired message type */
int msqid /* message queue ID to be used */

...

msgp = (struct msgbuf *)malloc((unsigned)(sizeof(struct msgbuf)
- sizeof msgp->mtext + maxmsgsz));

if (msgp == NULL) {
(void) fprintf(stderr, "msgop: %s %d byte messages.\n",
"could not allocate message buffer for", maxmsgsz);
exit(1);

...

msgsz = ...
msgflg = ...

if (msgsnd(msqid, msgp, msgsz, msgflg) == -1)
perror("msgop: msgsnd failed");
...
msgsz = ...
msgtyp = first_on_queue;
msgflg = ...
if (rtrn = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) == -1)
perror("msgop: msgrcv failed");
...


Latest topics
C - Arrays of structures  Viewed: 285
C - structures and functions  Viewed: 292
tcpdump by host name or ip  Viewed: 292
C - For loop statements  Viewed: 295
C - pointers and Arrays  Viewed: 295
C - File Access  Viewed: 295
C - pointers to pointers  Viewed: 296
C - Register variables  Viewed: 297
C - Pass-by-reference parameters  Viewed: 299
C - Static variables  Viewed: 299

Comments:





Submit comment's

Type:

User Comment's:

Submitted By:
Prof: Software Engineer
Tech: C ,Cpp
Send Mail: ratheesh



Related topics
C - Static variables
C - Local and global variables
C - Register variables

Related References
c - static variables
c - global and internal variables
c - global variables , static variables

Web site contents © Copyright 2007, All rights reserved.
Help | Terms and Conditions | Privacy Policy | About Us