Next | Prev | Up | Top | Contents | Index

System V Shared Memory

Shared memory IPC allows two or more executing processes to share memory and consequently the data contained there. This is done by allowing processes to set up access to a common virtual memory address space. This sharing occurs on a segment basis, which depends on memory management hardware.

This sharing of memory provides the fastest means of exchanging data between processes.

A process initially creates a shared memory segment facility using the shmget() system call. Arguments to this function set the overall operation permissions for the shared memory segment facility, sets its size in bytes, and can specify that the shared memory segment is for reference only (read-only) upon attachment. If the memory segment is not specified to be for reference only, all other processes with appropriate operation permissions can read from or write to the memory segment.

There are two operations that can be performed on a shared memory segment:

Shared memory attach allows processes to associate themselves with the shared memory segment if they have permission. They can then read or write as allowed.

Shared memory detach allows processes to disassociate themselves from a shared memory segment. Therefore, they lose the ability to read from or write to the shared memory segment.

The original owner/creator of a shared memory segment can relinquish ownership to another process using the shmctl() system call. However, the creating process remains the creator until the facility is removed or the system is reinitialized. Other processes with permission can perform other functions on the shared memory segment using the shmctl() system call.

System calls, documented in the IRIX reference pages, make these shared memory capabilities available to processes. The calling process passes arguments to a system call, and the system call attempts to perform its function. If the system call is successful, it performs its function and returns the appropriate information. Otherwise, a known error code (-1) is returned to the process, and the external variable errno is set accordingly.


Using Shared Memory

The sharing of memory between processes occurs on a virtual segment basis. There is one and only one instance of an individual shared memory segment existing in the UNIX operating system at any point in time.

Before memory sharing can be realized, a uniquely identified shared memory segment and data structure must be created. The unique identifier created is called the shared memory identifier (shmid); it is used to identify or reference the associated data structure. The data structure includes the following for each shared memory segment:

The definition for the shared memory segment data structure is located in the /usr/include/sys/shm.h header file. It is as follows:

struct shmid_ds {
struct        ipc_perm shm_perm; /* operation permission struct */
int           shm_segsz;      /* segment size */
struct region *shm_reg;       /* ptr to region structure */
char          pad[4];        /* for swap compatibility */
ushort        shm_lpid;      /* pid of last shmop */
ushort        shm_cpid;      /* pid of creator */
ushort        shm_nattch;    /* used only for shminfo */
ushort        shm_cnattch;   /* used only for shminfo */
time_t        shm_atime;     /* last shmat time */
time_t        shm_dtime;     /* last shmdt time */
time_t        shm_ctime;     /* last change time */ };
Note that the shm_perm member of this structure uses ipc_perm as a template. The ipc_perm data structure is the same for all IPC facilities, and is located in the /usr/include/sys/ipc.h header file.

The shmget() system call is used to perform two tasks when only the IPC_CREAT flag is set in the shmflg argument that it receives:

The task performed is determined by the value of the key argument passed to the shmget() system call. For the first task, if the key is not already in use for an existing shmid, a new shmid is returned with an associated shared memory segment data structure created for it, provided no system tuning parameters would be exceeded.

A provision exists for specifying a key of value zero, known as the private key (IPC_PRIVATE = 0); when specified, a new shmid is always returned with an associated shared memory segment data structure created for it unless a system tuning parameter would be exceeded. When the ipcs command is performed, the KEY field for the shmid is all zeros.

For the second task, if a shmid exists for the key specified, the value of the existing shmid is returned. If you do not want to have an existing shmid returned, a control command (IPC_EXCL) can be set in the shmflg argument passed to the system call. The details of using this system call are discussed in "Getting Shared Memory Segments With shmget()."

When performing the first task, the process that calls shmget() becomes the owner/creator, and the associated data structure is initialized accordingly. Remember, ownership can be changed, but the creating process always remains the creator; see "Controlling Shared Memory: shmctl()." The creator of the shared memory segment also determines the initial operation permissions for it.

Once a uniquely identified shared memory segment data structure is created, shared memory segment operations and control can be used.

Shared memory segment operations consist of attaching and detaching shared memory segments. System calls are provided for each of these operations; they are shmat() and shmdt(). Refer to "Operations for Shared Memory: shmat() and shmdt()" for details of these system calls.

Shared memory segment control is done by using the shmctl() system call. It permits you to control the shared memory facility in the following ways:

Refer to "Controlling Shared Memory: shmctl()" for details of the shmctl() system call.


Getting Shared Memory Segments With shmget()

This section gives a detailed description of using the shmget() system call along with an example program illustrating its use.

The prototype found in the shmget(2) reference page is as follows:

int shmget (key_t key, size_t size, int shmflg);

The integer returned from this function upon successful completion is the shared memory identifier (shmid) that was discussed earlier.

A new shmid with an associated shared memory data structure is provided when either of the following conditions is true:

The value passed to the shmflg argument specifies access permissions, execution modes, and command options.

Access permissions determine the read/write attributes, and execution modes determine the user/group/other attributes of the shmflg argument. They are collectively referred to as "operation permissions." Table 2-6 shows the numeric values (expressed in octal notation) for the valid operation permissions codes.

Operation Permissions Codes
Operation PermissionsOctal Values
Read by User00400
Write by User00200
Read by Group00040
Write by Group00020
Read by Others00004
Write by Others00002

A specific octal value is derived by adding the octal values for the operation permissions desired. That is, if read by user and read/write by others are desired, the code value would be 00406 (00400 plus 00004 plus 00002).

Constants located in the shm.h header file can be used for the owner. They include:

SHM_R 0400

SHM_W 0200

Control command constants are predefined in the ipc.h header file. Table 2-7 contains the names of the constants that apply to the shmget() system call along with their values.

Control Commands (Flags)
ControlValue
IPC_CREAT0001000
IPC_EXCL0002000

The value for shmflg is a combination of operation permissions and control commands, usually an expression using bitwise OR (|) with the operation permissions.

shmid = shmget (key, size, (IPC_CREAT | 0400));

shmid = shmget (key, size, (IPC_CREAT | IPC_EXCL | 0400));

As specified by the shmget(2) reference page, success or failure of this system call depends upon the argument values for key, size, and shmflg, and on system tuning parameters. The system call attempts to return a new shmid if one of the following conditions is true:

The second condition is satisfied if the value for key is not already associated with a shmid and the bitwise ANDing of shmflg and IPC_CREAT is not zero. Exceeding the SHMMNI system tuning parameter in either case causes a failure. The SHMMNI system tuning parameter determines the maximum number of unique shared memory segments (shmids) in the UNIX operating system.

IPC_EXCL is another control command used with IPC_CREAT to exclusively have the system call fail if, and only if, a shmid exists for the specified key provided. This is necessary to prevent the process from thinking that it has received a new (unique) shmid when it has not. In other words, when both IPC_CREAT and IPC_EXCL are specified, a unique shmid is returned if the system call is successful. Any value for shmflg returns a new shmid if the key equals zero (IPC_PRIVATE).

The system call fails if the value for the size argument is less than SHMMIN or greater than SHMMAX. These tunable parameters specify the minimum and maximum shared memory segment sizes.

Refer to the shmget(2) reference page for specific associated data structure initialization for successful completion. The specific failure conditions with error names are contained there also.


Example Program

The example program in this section (Example 2-10) is a menu-driven program that exercises all possible combinations of the shmget() system call. The program begins (lines 4-7) by including the required header files as specified by the shmget(2) reference page. Note that the errno.h header file is included as opposed to declaring errno as an external variable; either method works.

Variable names have been chosen to be as close as possible to those in the synopsis for the system call. Their declarations are self-explanatory. These names make the program more readable, and this is perfectly legal since they are local to the program. The variables declared for this program and their purposes are as follows:

keyThe desired semaphore key
oppermThe desired operation permissions
flagsThe desired control commands (flags)
opperm_flagsThe combination from the logical ORing of the opperm and flags variables, used in the system call to pass the shmflg argument
shmidThe message queue identification number from a successful system call or the error code (-1) for an unsuccessful one
sizeThe shared memory segment size

The program begins by prompting for a hexadecimal key, an octal operation permissions code, and finally for the control command combinations (flags), which are selected from a menu (lines 14-31). All possible combinations are allowed even though they might not be viable. Thus you can observe the errors for illegal combinations.

Next, the menu selection for the flags is combined with the operation permissions, and the result is stored in the opperm_flags variable (lines 35-50).

A display then prompts for the size of the shared memory segment, which is stored in the size variable (lines 51-54).

The system call is made next, and the result is stored in the shmid variable (line 56).

Since the shmid variable now contains a valid message queue identifier or the error code (-1), it is tested to see if an error occurred (line 58). If shmid equals -1, a message indicates that an error resulted and the external errno variable is displayed (lines 60, 61). If no error occurred, the returned shared memory segment identifier is displayed (line 65).

Example 2-10 : shmget() System Call Example

1  /*This is a program to illustrate 
2   *the shared memory get, shmget(), 
3   *system call capabilities.*/
4   #include <sys/types.h> 
5   #include <sys/ipc.h> 
6   #include <sys/shm.h>
7   #include <errno.h>
8   /*Start of main C language program*/ 
9   main() 
10  { 
11     key_t key; /*declare as long integer*/ 
12     int opperm, flags; 
13     int shmid, size, opperm_flags; 
14     /*Enter the desired key*/ 
15     printf("Enter the desired key in hex = "); 
16     scanf("%x", &key);
17     /*Enter the desired octal operation 
18       permissions.*/
19     printf("\nEnter the operation\n"); 
20     printf("permissions in octal = ");
21     scanf("%o", &opperm);
22     /*Set the desired flags.*/
23     printf("\nEnter corresponding number to\n"); 
24     printf("set the desired flags:\n"); 
25     printf("No flags = 0\n"); 
26     printf("IPC_CREAT = 1\n"); 
27     printf("IPC_EXCL = 2\n"); 
28     printf("IPC_CREAT and IPC_EXCL = 3\n"); 
29     printf(" Flags = "); 
30     /*Get the flag(s) to be set.*/ 
31     scanf("%d", &flags);
32     /*Check the values.*/
33     printf ("\nkey =0x%x, opperm = 0%o, flags = 0%o\n", 
34       key, opperm, flags);
35     /*Incorporate the control fields (flags) with 
36       the operation permissions*/
37     switch (flags) 
38     { 
39     case 0: /*No flags are to be set.*/
40       opperm_flags = (opperm | 0); 
41       break; 
42     case 1: /*Set the IPC_CREAT flag.*/ 
43       opperm_flags = (opperm | IPC_CREAT);
44       break;
45     case 2: /*Set the IPC_EXCL flag.*/
46       opperm_flags = (opperm | IPC_EXCL);
47       break; 
48     case 3: /*Set the IPC_CREAT and IPC_EXCL flags.*/
49       opperm_flags = (opperm | IPC_CREAT | IPC_EXCL); 
50     }
51     /*Get the size of the segment in bytes.*/
52     printf ("\nEnter the segment"); 
53     printf ("\nsize in bytes = ");
54     scanf ("%d", &size);
55     /*Call the shmget system call.*/
56     shmid = shmget (key, size, opperm_flags);
57     /*Perform the following if the call is unsuccessful.*/ 
58     if(shmid == -1)
59     {
60       printf ("\nThe shmget system call failed!\n");
61       printf ("The error number = %d\n", errno); 
62     } 
63     /*Return the shmid upon successful completion.*/ 
64     else 
65       printf ("\nThe shmid = %d\n", shmid); 
66     exit(0);
67   }

Controlling Shared Memory: shmctl()

This section details using the shmctl() system call and provides an example program that exercises all of its capabilities.

The prototype found in the shmctl(2) reference page is as follows:

int shmctl (int shmid, int cmd [, struct shmid_ds *buf] );

The shmctl() system call requires two or three arguments to be passed to it, and it returns an integer value. Upon successful completion, a zero value is returned; when unsuccessful, shmctl() returns a -1.

The shmid variable must be a nonnegative integer returned by shmget(). The cmd argument can be replaced by one of following control commands (flags):

IPC_STATReturn the status information contained in the associated data structure for the specified shmid and place it in the data structure pointed to by the buf pointer in the user memory area.
IPC_SETFor the specified shmid, set the effective user and group identification, and operation permissions.
IPC_RMIDRemove the specified shmid along with its associated shared memory segment data structure.
SHM_LOCKLock the specified shared memory segment in memory; must be super user.
SHM_UNLOCKUnlock the shared memory segment from memory; must be super user.

A process must have the effective user identification of the owner/creator of the segment, or of superuser, to perform an IPC_SET or IPC_RMID control command. Only the superuser can perform a SHM_LOCK or SHM_UNLOCK control command. A process must have read permission to perform the IPC_STAT control command.

The details of this system call are discussed in the example program for it. If you have problems understanding the logic manipulations in this program, read "Getting Shared Memory Segments With shmget()"; it goes into more detail than would be practical to do for every system call.


Example Program

The example program in this section (Example 2-11) is a menu-driven program that exercises all possible combinations of the shmctl() system call. From studying this program, you can observe the method of passing arguments and receiving return values. The user-written program requirements are pointed out.

This program begins (lines 5-9) by including the required header files as specified by the shmctl(2) reference page. Note in this program that errno is declared as an external variable, and therefore, the errno.h header file does not have to be included.

Variable and structure names have been chosen to be as close as possible to those in the synopsis for the system call. Their declarations are self-explanatory. These names make the program more readable, and it is perfectly legal since they are local to the program. The variables declared for this program and their purposes are as follows:

uidThe IPC_SET value for the effective user identification.
gidThe IPC_SET value for the effective group identification.
modeThe IPC_SET value for the operation permissions.
rtrnThe return integer value from the system call.
shmidThe shared memory segment identifier to the system call.
commandThe code for the desired control command so that subsequent processing can be performed on it.
choiceWhich member for the IPC_SET control command is to be changed.
shmid_dsThe data structure returned from an IPC_STAT control command.
bufAddress of the data structure in the user memory area where IPC_STAT is to place its return values or where the IPC_SET command gets the values to set.

Note that the shmid_ds data structure in this program (line 16) uses the data structure located in the shm.h header file of the same name as a template for its declaration. This is a perfect example of the advantage of local variables.

The next important thing to observe is that although the *buf pointer is declared to be a pointer to a data structure of the shmid_ds type, it must also be initialized to contain the address of the user memory area data structure (line 17).

First, the program prompts for a valid shared memory segment identifier that is stored in the shmid variable (lines 18-20). This is required for every shmctl() system call.

Then, the code for the desired control command must be entered (lines 21-29), and it is stored in the command variable. The code is tested to determine the control command for subsequent processing.

If the IPC_STAT control command is selected (code 1), the system call is performed (lines 39, 40) and the status information returned is printed out (lines 41-71). Note that if the system call is unsuccessful (line 146), the status information of the last successful call is printed out. In addition, an error message is displayed and the errno variable is printed out (lines 148, 149). If the system call is successful, a message indicates this along with the shared memory segment identifier used (lines 151-154).

If the IPC_SET control command is selected (code 2), the first thing done is to get the current status information for the message queue identifier specified (lines 90-92). This is necessary because this example program provides for changing only one member at a time, and the system call changes all of them. Also, if an invalid value happened to be stored in the user memory area for one of these members, it would cause repetitive failures for this control command until corrected. The next thing the program does is to prompt for a code corresponding to the member to be changed (lines 93-98). This code is stored in the choice variable (line 99). Now, depending upon the member picked, the program prompts for the new value (lines 105-127). The value is placed in the appropriate member in the user memory area data structure, and the system call is made (lines 128-130). Depending upon success or failure, the program returns the same messages as for IPC_STAT above.

If the IPC_RMID control command (code 3) is selected, the system call is performed (lines 132-135), and the shmid along with its associated message queue and data structure are removed from the UNIX operating system. Note that the *buf pointer is not required as an argument to perform this control command and its value can be zero or NULL. Depending upon the success or failure, the program returns the same messages as for the other control commands.

If the SHM_LOCK control command (code 4) is selected, the system call is performed (lines 137,138). Depending upon the success or failure, the program returns the same messages as for the other control commands.

If the SHM_UNLOCK control command (code 5) is selected, the system call is performed (lines 140-142). Depending upon the success or failure, the program returns the same messages as for the other control commands.

Example 2-11 : shmctl() System Call Example

1  /*This is a program to illustrate 
2  *the shared memory control, shmctl(), 
3  *system call capabilities. 
4  */
5  /*Include necessary header files.*/ 
6  #include <stdio.h> 
7  #include <sys/types.h> 
8  #include <sys/ipc.h> 
9  #include <sys/shm.h>
10  /*Start of main C language program*/ 
11  main() 
12  {
13     extern int errno; 
14     int uid, gid, mode; 
15     int rtrn, shmid, command, choice;
16     struct shmid_ds shmid_ds, *buf; 
17     buf = &shmid_ds;
18     /*Get the shmid, and command.*/ 
19     printf("Enter the shmid = "); 
20     scanf("%d", &shmid); 
21     printf("\nEnter the number for\n"); 
22     printf("the desired command:\n");
23     printf("IPC_STAT = 1\n"); 
24     printf("IPC_SET = 2\n"); 
25     printf("IPC_RMID = 3\n"); 
26     printf("SHM_LOCK = 4\n"); 
27     printf("SHM_UNLOCK = 5\n"); 
28     printf("Entry = "); 
29     scanf("%d", &command);
30     /*Check the values.*/
31     printf ("\nshmid =%d, command = %d\n", 
32     shmid, command);
33     switch (command)
34     { 
35     case 1: /*Use shmctl() to duplicate 
36       the data structure for 
37         shmid in the shmid_ds area pointed 
38         to by buf and then print it out.*/
39       rtrn = shmctl(shmid, IPC_STAT, 
40         buf); 
41       printf ("\nThe USER ID = %d\n", 
42         buf->shm_perm.uid); 
43       printf ("The GROUP ID = %d\n", 
44         buf->shm_perm.gid); 
45       printf ("The creator's ID = %d\n",
46         buf->shm_perm.cuid); 
47       printf ("The creator's group ID = %d\n",
48         buf->shm_perm.cgid); 
49       printf ("The operation permissions = 0%o\n", 
50         buf->shm_perm.mode); 
51       printf ("The slot usage sequenceen");
52       printf ("number = 0%x\n", 
53         buf->shm_perm.seq); 
54       printf ("The key= 0%x\n", 
55         buf->shm_perm.key); 
56       printf ("The segment size = %d\n", 
57         buf->shm_segsz); 
58       printf ("The pid of last shmop = %d\n", 
59         buf->shm_lpid);
60       printf ("The pid of creator = %d\n", 
61         buf->shm_cpid); 
62       printf ("The current # attached = %d\n", 
63         buf->shm_nattch); 
64       printf("The in memory # attached = %d\n", 
65         buf->shm_cnattach); 
66       printf("The last shmat time = %d\n", 
67         buf->shm_atime); 
68       printf("The last shmdt time = %d\n",
69         buf->shm_dtime);
70       printf("The last change time = %d\n", 
71         buf->shm_ctime); 
72       break;
         /* Lines 73 - 87 deleted */
88     case 2: /*Select and change the desired
89       member(s) of the data structure.*/
90       /*Get the original data for this shmid 
91          data structure first.*/ 
92       rtrn = shmctl(shmid, IPC_STAT, buf);
93       printf("\nEnter the number for the\n"); 
94       printf("member to be changed:\n"); 
95       printf("shm_perm.uid = 1\n");
96       printf("shm_perm.gid = 2\n"); 
97       printf("shm_perm.mode = 3\n"); 
98       printf("Entry = ");
99       scanf("%d", &choice); 
100      /*Only one choice is allowed per 
101        pass as an illegal entry will
102        cause repetitive failures until
103         shmid_ds is updated with 
104         IPC_STAT.*/
105      switch(choice){
106      case 1: 
107        printf("\nEnter USER ID = "); 
108        scanf ("%d", &uid); 
109        buf->shm_perm.uid = uid; 
110        printf("\nUSER ID = %d\n", 
111        buf->shm_perm.uid); 
112        break;
113      case 2: 
114        printf("\nEnter GROUP ID = "); 
115        scanf("%d", &gid); 
116        buf->shm_perm.gid = gid; 
117        printf("\nGROUP ID = %d\n", 
118        buf->shm_perm.gid); 
119        break;
120      case 3: 
121        printf("\nEnter MODE = "); 
122        scanf("%o", &mode); 
123        buf->shm_perm.mode = mode; 
124        printf("\nMODE = 0%o\n", 
125        buf->shm_perm.mode); 
126        break; 
127    } 
128    /*Do the change.*/ 
129    rtrn = shmctl(shmid, IPC_SET, 
130    buf); 
131    break;
132    case 3: /*Remove the shmid along with its 
133      associated 
134      data structure.*/
135      rtrn = shmctl(shmid, IPC_RMID, NULL); 
136      break;
137    case 4: /*Lock the shared memory segment*/ 
138      rtrn = shmctl(shmid, SHM_LOCK, NULL);
139      break; 
140    case 5: /*Unlock the shared memory
141      segment.*/
142      rtrn = shmctl(shmid, SHM_UNLOCK, NULL); 
143      break; 
144    } 
145    /*Perform the following if the call fails.*/ 
146    if(rtrn == -1) 
147    { 
148      printf ("\nThe shmctl system call failed!\n"); 
149      printf ("The error number = %d\n", errno); 
150    } 
151    /*Return the shmid upon successful completion.*/ 
152    else 
153      printf ("\nShmctl was successful for shmid = %d\n", 
154      shmid);
155    exit (0);
156 }

Operations for Shared Memory: shmat() and shmdt()

This section details the shmat() and shmdt() system calls, and presents an example program that exercises all of their capabilities.

The prototypes found in the shmop(2) reference page, which includes both shmat() and shmaddr(), are as follows:

void *shmat(int shmid, void *shmaddr, int shmflg); int shmdt (void *shmaddr);

Attaching to a Shared Memory Segment

The shmat() system call takes three arguments and it returns a character pointer value. The returned value can be cast to an integer value. Upon successful completion, this value is the address in memory where the process is attached to the shared memory segment, and when unsuccessful, it is -1.

The shmid argument must be a nonnegative integer returned from shmget(). The shmaddr argument can be 0 or nonzero. When it is 0 , IRIX picks the address of the shared segment. When shmaddr is nonzero it must be a valid address that IRIX would pick. It is wise to let the operating system pick addresses so as to improve portability.

The shmflg argument passes the SHM_RND and SHM_RDONLY flags to shmat().

Detaching Shared Memory Segments

The shmdt() system call takes one argument and returns an integer value, 0 if it completes successfully, otherwise -1. Further details of this system call are discussed in the example program.

Example Program

The example program in Example 2-12 is a menu-driven program that exercises all possible combinations of the shmat() and shmdt() system calls.

This program begins (lines 5-9) by including the required header files as specified by the shmop(2) reference page. Note that in this program, errno is declared as an external variable, and therefore, the errno.h header file does not have to be included.

Variable and structure names were chosen to be as close as possible to those in the synopsis. Their declarations are self-explanatory. The names make the program more readable; this is legal since they are local to the program. The variables declared for this program and their purposes include:

flagsThe codes of SHM_RND or SHM_RDONLY for the shmat() system call
addrThe address of the shared memory segment for the shmat() and shmdt() system calls
iA loop counter for attaching and detaching
attachThe desired number of attach operations
shmidThe desired shared memory segment identifier
shmflgThe value of flags to the shmat() system call
rtrnThe return values from both system calls
detachThe desired number of detach operations

This example program combines both the shmat() and shmdt() system calls. The program prompts for the number of attachments, and enters a loop until they are done, for the specified shared memory identifiers. Then, the program prompts for the number of detachments to be performed, and enters a loop until they are done, for the specified shared memory segment addresses.

Example Use of shmat()

The program prompts for the number of attachments to be performed, and the value is stored in the attach variable (lines 17-21).

A loop is entered using the attach variable and the i counter (lines 23-70) to perform the specified number of attachments. In this loop, the program prompts for a shared memory segment identifier (lines 24-27) and it is stored in the shmid variable (line 28). Next, the program prompts for the address where the segment is to be attached (lines 30-34), and it is stored in the addr variable (line 35). Then, the program prompts for the desired flags to be used for the attachment (lines 37-44), and the code representing the flags is stored in the flags variable (line 45). The flags variable is tested to determine the code to be stored for the shmflg variable used to pass them to the shmat() system call (lines 46-57). The system call is made (line 60). If the call succeeds, a message stating so is displayed along with the attach address (lines 66-68). If the call is unsuccessful, a message stating so is displayed and the error code is displayed (lines 62, 63). The loop then continues.

Example Use of shmdt

After the attach loop completes, the program prompts for the number of detach operations to be performed (lines 71-75), and the value is stored in the detach variable (line 76).

A loop is entered using the detach variable and the i counter (lines 78-95) to perform the specified number of detachments. In this loop, the program prompts for the address of the shared memory segment to be detached (lines 79-83), and it is stored in the addr variable (line 84). Then, the shmdt() system call is performed (line 87). If the call succeeeds, a message stating so is displayed along with the address that the segment was detached from (lines 92,93). When the call is unsuccessful, the error number is displayed (line 89). The loop continues.

Example 2-12 : shmat() and shmdt() System Call Example

1  /*This is a program to illustrate
2   *the shared memory operations, shmop(),
3   *system call capabilities. 
4   */
5   /*Include necessary header files.*/
6   #include <stdio.h> 
7   #include <sys/types.h> 
8   #include <sys/ipc.h> 
9   #include <sys/shm.h> 
10  /*Start of main C language program*/ 
11  main() 
12  { 
13     extern int errno; 
14     int flags, addr, i, attach; 
15     int shmid, shmflg, retrn, detach;
16     /*Loop for attachments by this process.*/ 
17     printf("Enter the number ofen"); 
18     printf("attachments for this\n"); 
19     printf("process (1-4).\n"); 
20     printf(" Attachments = ");
21     scanf("%d", &attach); 
22     printf("Number of attaches = %d\n", attach);
23     for(i = 1; i <= attach; i++) {
24       /*Enter the shared memory ID.*/ 
25       printf("\nEnter the shmid ofen"); 
26       printf("the shared memory segment to\n");
27       printf("be operated on = "); 
28       scanf("%d", &shmid); 
29       printf("\nshmid = %d\n", shmid);
30       /*Enter the value for shmaddr.*/ 
31       printf("\nEnter the value for\n");
32       printf("the shared memory address\n"); 
33       printf("in hexadecimal:\n"); 
34       printf(" Shmaddr = "); 
35       scanf("%x", &addr); 
36       printf("The desired address = 0x%x\n", addr);
37       /*Specify the desired flags.*/ 
38       printf("\nEnter the corresponding\n");
39       printf("number for the desireden"); 
40       printf("flags:\n"); 
41       printf("SHM_RND = 1\n"); 
42       printf("SHM_RDONLY = 2\n"); 
43       printf("SHM_RND and SHM_RDONLY = 3\n");
44       printf(" Flags = "); 
45       scanf("%d", &flags);
46       switch(flags) 
47       { 
48       case 1: 
49         shmflg = SHM_RND; 
50         break; 
51       case 2: 
52         shmflg = SHM_RDONLY; 
53         break;
54       case 3: 
55         shmflg = SHM_RND | SHM_RDONLY; 
56         break;
57       }
58       printf("\nFlags = 0%o\n", shmflg);
59       /*Do the shmat system call.*/ 
60       retrn = (int)shmat(shmid, addr, shmflg); 
61       if(retrn == -1) { 
62         printf("\nShmat failed. "); 
63         printf("Error = %d\n", errno); 
64       } 
65       else { 
66         printf ("\nShmat was successful\n"); 
67         printf("for shmid = %d\n", shmid); 
68         printf("The address = 0x%x\n", retrn); 
69       } 
70   }
71   /*Loop for detachments by this process.*/
72   printf("Enter the number ofen");
73   printf("detachments for this\n"); 
74   printf("process (1-4).\n"); 
75   printf(" Detachments = ");
76   scanf("%d", &detach);
77   printf("Number of attaches = %d\n", detach);
78   for(i = 1; i <= detach; i++) {
79     /*Enter the value for shmaddr.*/
80     printf("\nEnter the value for\n");
81     printf("the shared memory address\n");
82     printf("in hexadecimal:\n");
83     printf(" Shmaddr = ");
84     scanf("%x", &addr);
85     printf("The desired address = 0x%x\n", addr);
86     /*Do the shmdt system call.*/
87     retrn = (int)shmdt(addr);
88     if(retrn == -1) {
89       printf("Error = %d\n", errno);
90     }
91     else {
92       printf ("\nShmdt was successful\n"); 
93       printf("for address = 0%x\n", addr);
94     }
95   } 
96 }

Surveys the different facilities available for programming parallel computations, comparing the advantages of each.


Next | Prev | Up | Top | Contents | Index