Using an IPC Resource

IPC resources are created by invoking the semget( ), msgget( ), or shmget( )

functions, depending on whether the new resource is a semaphore, a message queue, or a shared memory region.

The main objective of each of these three functions is to derive from the IPC key (passed as the first parameter) the corresponding IPC identifier, which is then used by the process for accessing the resource. If there is no IPC resource already associated with the IPC key, a new resource is created. If everything goes right, the function returns a positive IPC identifier; otherwise, it returns one of the error codes listed in Table 19-6.

Table 19-6. Error codes returned while requesting an IPC identifier

Error code

Description

EACCESS

Process does not have proper access rights.

EEXIST

Process tried to create an IPC resource with the same key as one that already exists.

EIDRM

Resource is marked to be deleted.

ENOENT

No IPC resource with the requested key exists and the process did not ask to create it.

ENOMEM

No more storage is left for an additional IPC resource.

ENOSPC

Maximum limit on the number of IPC resources has been exceeded.

Assume that two independent processes want to share a common IPC resource. This can be achieved in two possible ways:

• The processes agree on some fixed, predefined IPC key. This is the simplest case, and it works quite well for any complex application implemented by many processes. However, there's a chance that the same IPC key is chosen by another unrelated program. In this case, the IPC functions might be successfully invoked and still return the IPC identifier of the wrong resource. [5]

[5] The ftok( ) function attempts to create a new key from a file pathname and an 8-bit project identifier passed as parameters. It does not guarantee, however, a unique key number, since there is a small chance that it will return the same IPC key to two different applications using different pathnames and project identifiers.

• One process issues a semget( ), msgget( ), or shmget( ) function by specifying ipc_private as its IPC key. A new IPC resource is thus allocated, and the process can either communicate its IPC identifier to the other process in the application-6! or fork the other process itself. This method ensures that the IPC resource cannot be used accidentally by other applications.

[6] This implies, of course, the existence of another communication channel between the processes not based on IPC.

The last parameter of the semget( ), msgget( ), and shmget( ) functions can include two flags. ipc_creat specifies that the IPC resource must be created, if it does not already exist; ipc_excl specifies that the function must fail if the resource already exists and the ipc_creat flag is set.

Even if the process uses the ipc_creat and ipc_excl flags, there is no way to ensure exclusive access to an IPC resource, since other processes may always refer to the resource by using its IPC identifier.

To minimize the risk of incorrectly referencing the wrong resource, the kernel does not recycle IPC identifiers as soon as they become free. Instead, the IPC identifier assigned to a resource is almost always larger than the identifier assigned to the previously allocated resource of the same type. (The only exception occurs when the 32-bit IPC identifier overflows.) Each IPC identifier is computed by combining a slot usage sequence number relative to the resource type, an arbitrary slot index for the allocated resource, and an arbitrary value chosen in the kernel that is greater than the maximum number of allocatable resources. If we choose s to represent the slot usage sequence number, M to represent the upper bound on the number of allocatable resources, and /'to represent the slot index, where 0 — i<M, each IPC resource's ID is computed as follows: IPC identifier = s x M + i

In Linux 2.4, the value of M is set to 32,768 (ipcmni macro). The slot usage sequence number s is initialized to 0 and is incremented by 1 at every resource allocation. When s reaches a predefined threshold, which depends on the type of IPC resource, it restarts from 0.

Every type of IPC resource (semaphores, message queues, and shared memory areas) owns an ipc_ids data structure, which includes the fields shown in Table 19-7.

Table 19-7. The fields of the ipc_ids data structure

Type

Field

Description

int

size

Current maximum number of IPC resources

int

in_use

Number of allocated IPC resources

int

max id

Maximum slot index in use

unsigned short

seq

Slot usage sequence number for the next allocation

unsigned short

seq max

Maximum slot usage sequence number

struct semaphore

sem

Semaphore protecting the ipc ids data structure

spinlock t

ary

Spin lock protecting the IPC resource descriptors

struct ipc_id *

entries

Array of IPC resource descriptors

The size field stores the maximum number of allocatable IPC resources of the given type. The system administrator may increase this value for any resource type by writing into the /proc/sys/kernel/sem, /proc/sys/kernel/msgmni, and /proc/sys/kernel/shmmni special files,

The entries field points to an array of pointers to kern_ipc_perm data structures, one for every allocatable resource (the size field is also the size of the array). Each kern_ipc_perm data structure is associated with an IPC resource and contains the fields shown in Table 19-8. The uid, gid, cuid, and cgid fields store the user and group identifiers of the resource's creator and the user and group identifiers of the current resource's owner, respectively. The mode bit mask includes six flags, which store the read and write access permissions for the resource's owner, the resource's group, and all other users. IPC access permissions are similar to file access permissions described in Section 1.5.5, except that the Execute permission flag is not used.

Table 19-8. The fields in the kern_ipc_ perm structure

Type

Field

Description

int

key

IPC key

unsigned int

uid

Owner user ID

unsigned int

gid

Owner group ID

unsigned int

cuid

Creator user ID

unsigned int

cgid

Creator group ID

unsigned short

mode

Permission bit mask

unsigned long

seq

Slot usage sequence number

The kern_ipc_perm data structure also includes a key field (which contains the IPC key of the corresponding resource) and a seq field (which stores the slot usage sequence number s used to compute the IPC identifier of the resource).

The semctl( ), msgctl( ), and shmctl( ) functions may be used to handle IPC resources. The ipc_SET subcommand allows a process to change the owner's user and group identifiers and the permission bit mask in the ipc_perm data structure. The IPC_STAT and ipc_info subcommands retrieve some information concerning a resource. Finally, the ipc_RMID subcommand releases an IPC resource. Depending on the type of IPC

resource, other specialized subcommands are also available. £7!

Continue reading here: The ipc System Call

Was this article helpful?

0 0