Creating a Shared Memory Segment

The shmget system call is used to create the shared memory segment and generate the associated system data structure or to gain access to an existing segment. The shared memory segment and the system data structure are identified by a unique shared memory identifier that the shmget system call returns (see Table 8.1).

Providing no system parameters are exceeded, the shmget system call creates a new shared memory segment if

As with previous IPC system calls for message queues and semaphores, the ftok library function can be used to generate a key value.

The argument size determines the size in bytes of the shared memory segment. If we are using shmget to access an existing shared memory segment, size can be set to 0, as the segment size is set by the creating process. Common overall default system maximums, as related to shared memory, are shown in Table 8.2.

Table 8.2. Shared Memory Limits.

Shared Memory Segment Defaults

Constant

Value

Maximum segment size

SHMMAX

4 MB

Minimum segment size

SHMMIN

1 byte

Systemwide maximum number of segments

SHMMNI

4096

Maximum number of segments per process

SHMSEG

Not specified

The last argument for shmget , shmflg , is used to indicate segment creation conditions (e.g., IPC_CREAT, IPC_EXCL) and access permissions (stored in the low order 9 bits of shmflg ). At this time the system does not use the execute permission settings. To specify creation conditions along with access permissions, the individual items are bitwise OR ed (e.g., 0660 IPC_CREAT).

The shmget system call does not entitle the creating process to actually use the allocated memory; it merely reserves the requested memory. To be used by the process, the allocated memory must be attached to the process using a separate system call. The technique for accomplishing this is discussed in Section 8.4.

If shmget is successful in allocating a shared memory segment, it returns an integer shared memory identifier. At creation time, the system data structure shmid_ds , defined in the header file, is generated and initialized . As with other System V IPC facilities, the user does not directly include but instead includes the standard header file for shared memory , which in turn includes the . The standard definition for the shmid_ds data structure follows :

struct shmid_ds { struct ipc_perm shm_perm; /* operation permission struct */ size_t shm_segsz; /* size of segment in bytes */ __time_t shm_atime; /* time of last shmat() */ unsigned long int __unused1; __time_t shm_dtime; /* time of last shmdt() */ unsigned long int __unused2; __time_t shm_ctime; /* time of last change by shmctl() */ unsigned long int __unused3; __pid_t shm_cpid; /* pid of creator */ __pid_t shm_lpid; /* pid of last shmop */ shmatt_t shm_nattch; /* number of current attaches */ unsigned long int __unused4; unsigned long int __unused5; };

The source files for the kernel for System V IPC (found in /usr/src/ linux-XX.XX.XX/ipc where XX are the version numbers of the operating system) defines a similar private kernel shared memory structure called shmid_kernel .

The shmid_ds structure contains an ipc_perm permission structure called shm_perm . When created, the shm_perm.cuid and shm_perm.uid members are assigned the effective user ID of the calling process, and the shm_perm.cgid and shm_perm.gid members are set to the group ID of the calling process. The access permission bits, stored in the shm_perm.mode member, are set according to the value specified by the shmflg value. The shm_segsz member is set to the specified size from the shmget system call. The shm_lpid , shm_nattch , shm_atime , and shm_dtime members are each set to 0, while the shm_ctime member is set to the current time. The shm_cpid member stores the ID of the creating process.

If shmget fails, it returns a value of -1 and sets the value in errno to indicate the specific error condition. The values that errno may be assigned and their interpretations are shown in Table 8.3.

Table 8.3. shmget Error Messages

#

Constant

perror Message

Explanation

2

EOENT

No such file or directory

The shared memory identifier does not exist for this key , and IPC_CREAT was not set.

12

ENOMEM

Cannot allocate memory

When creating a shared memory segment, insufficient memory is available.

13

EACCES

Permission denied

The shared memory identifier exists for this key , but the requested operation is not allowed by the current access permissions.

17

EEXIST

File exists

Shared memory identifier exists for this key , but IPC_CREAT and IPC_EXCL are both set.

22

EINVAL

Invalid argument

  • The value of size is less than system minimum or greater than system maximum.
  • The shared memory identifier exists, but the requested size is too large.

28

ENOSPC

No space left on device

System-imposed limit for number of shared memory segments has been reached.

43

EIDRM

Identifier removed

Memory segment is marked as removed.

Program 8.1 attempts to create two shared memory segments of differing sizes.

Program 8.1 Creating shared memory segments.

File : p8.1.cxx /* Allocating a shared memory segment */ #include + #include #include #include using namespace std; int 10 main( ) { key_t key = 15; int shmid_1, shmid_2; if ((shmid_1=shmget(key, 1000, 0640IPC_CREAT)) == -1){ perror("shmget shmid_1"); + return 1; } cout << "First shared memory identifier is : " << shmid_1 << endl; if ((shmid_2=shmget(IPC_PRIVATE, 20, 0640)) == -1){ perror("shmget shmid_2"); 20 return 2; } cout << "Second shared memory identifier is: " << shmid_2 << endl; return 0; }

Figure 8.2 shows the output of Program 8.1 when invoked twice in succession.

Figure 8.2 Output of Program 8.1.

linux$ p8.1 <-- 1 First shared memory identifier is : 40665091 Second shared memory identifier is: 40697860 linux$ ipcs -m <-- 2 ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x0000000f 40665091 gray 640 1000 0 0x00000000 40697860 gray 640 20 0 linux$ p8.1 <-- 3 First shared memory identifier is : 40665091 Second shared memory identifier is: 40730629 linux$ ipcs -m <-- 4 ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x0000000f 40665091 gray 640 1000 0 0x00000000 40697860 gray 640 20 0 0x00000000 40730629 gray 640 20 0

(1) Run the program.

(2) Check with ipcs .

(3) Run the program again.

(4) Recheck with ipcs .

Examination of the output shows the first invocation created two shared memory segments with the identifier values of 40665091 and 40697860 . The first segment, with the shared memory identification value of 40665091 , was created by the first call to shmget , as the key value (15) coded in the program was not associated with any other previously allocated memory segment. The second segment, identified by the 40697860 , was created by shmget , since IPC_PRIVATE was specified. However, when the program was invoked the second time, the results were slightly different. The first call to shmget returned the shared memory identifier from the first invocation of the program, as the shared memory segment already existed for the key value of 15. The second call to shmget , since it uses IPC_PRIVATE, produced another unique shared memory segment (40730629) . Notice that the output for the ipcs command shows that the key value entries for both of the unique shared memory segments generated with IPC_PRIVATE are set to zero.

EXERCISE

Write a program that determines by trial and error if the maximum shared memory segment size is or is not the 4 MB noted. If the maximum is not this value, what is the maximum (to the nearest 1K)? Note : Please be sure to remove any shared memory segments you generate for this exercise. You may want to look ahead to Section 8.3 to obtain the proper syntax to accomplish the removal of the shared memory segment within your program (versus using the ipcrm command on the command line). Of course, if you modified the cleanup script (Exercise 7.1), you could use it to remove your shared memory segments.

Категории