#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> iinntt sshhmmggeett((_m_e_m_k_e_y,, _s_i_z_e,, _f_l_a_g)) kkeeyy__tt _m_e_m_k_e_y;; iinntt _s_i_z_e,, _f_l_a_g;;shmget() creates a shared-memory identifier, associated data structure, and shared-memory segment, links them to the identifier memkey, and returns the shared-memory identifier that it has associated with memkey.
memkey is an identifier that your application generates to identify its shared-memory segments. To guarantee that each key is unique, you should use the function call ftok() to generate keys.
size gives the size, in bytes, of the shared-memory segment that you want shmget() to create.
flag can be bitwise OR'd to include the following constants:
struct shmid_ds {
struct ipc_perm shm_perm;/* operation permission struct */
int shm_segsz; /* segment size */
char *__unused; /* for binary compatibility */
char __pad [4]; /* for binary compatibility */
pid_t shm_lpid; /* pid of last shmop */
pid_t shm_cpid; /* pid of creator */
unsigned short shm_nattch; /* current # attached */
unsigned short shm_cnattach; /* for binary compatibility */
time_t shm_atime; /* last shmat time */
time_t shm_dtime; /* last shmdt time */
time_t shm_ctime; /* last change time */
};
Field shm_perm is a structure of type ipc_perm, which header file <sys/ipc.h> defines as follows:
struct ipc_perm {
unsigned short uid; /* owner's user id */
unsigned short gid; /* owner's group id */
unsigned short cuid; /* creator's user id */
unsigned short cgid; /* creator's group id */
unsigned short mode; /* access modes */
unsigned short seq; /* slot usage sequence number */
key_t key; /* key */
};
shmget() initializes shm_id as follows:
( (_f_l_a_g & IPC_CREAT) && (_f_l_a_g & IPC_EXCL) )
is true (EEEEXXIISSTT).
The example consists of two programs: writeshm, which captures input from the keyboard and writes it into a shared-memory segment; and readshm, which reads and displays from the shared-memory segment the text that writeshm put there. Each program terminates when you type ``end''.
Note that this example is most effective if you run each program from its own virtual console.
The first program gives the source for writeshm:
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h>
main()
{
int iShmId; /* Segment id */
char *cpShm; /* Pointer to the segment */
key_t key; /* Segment key */
key = ftok("/etc/passwd", 'S'); /* Get a key */
/* if a shared-memory segment exists, get it; otherwise, create one */
if ((iShmId = shmget(key, 256, 0644 | IPC_CREAT)) < 0) {
perror("get");
exit(1);
}
/* Attach segment to process. Use an attach address of zero to
* let the system find a correct virtual address to attach.
*/
if ((cpShm = shmat(iShmId, 0, 0644)) == (char *) -1) {
perror("shmat");
exit(1);
}
printf("Server is ready.\n");
printf("Any message to continue, 'end' to exit\n");
for (;;) {
printf("Enter the message -> ");
gets(cpShm);
if (!strcmp(cpShm, "end")) {
puts("Bye");
shmdt(cpShm); /* Detach segment */
break;
}
}
}
The next program gives the source for readshm:
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h>
main()
{
int iShmId; /* Segment id */
char *cpShm; /* Pointer to the segment */
key_t key; /* Segment key */
char cBuf[16]; /* Read buffer */
/* Get a key */
key = ftok("/etc/passwd", 'S');
/* Get shared memory id. If it does not exist, do *not* create it. */
if ((iShmId = shmget(key, 256, 0644)) < 0) {
perror("get");
exit(1);
}
/* attach shared-memory segment to the process */
if ((cpShm = shmat(iShmId, 0, 0644)) == (char *) -1) {
perror("shmat");
exit(1);
}
printf("Client is ready\n");
for (;;) {
printf("Press enter to read the message -> ");
gets(cBuf);
printf("Got: \"%s\"\n", cpShm);
/* Exit on the 'end': detach and remove segment */
if (!strcmp(cpShm, "end")) {
struct shmid_ds stShmId;
puts("Bye");
shmdt(cpShm);
if (shmctl(iShmId, IPC_RMID, &stShmId)) {
perror("shmctl");
exit(1);
}
break;
}
}
}
A The kernel variables SHMMAX and SHMMNI set, respectively, the maximum size of a shared-memory segment and the number of shared-memory segments that can exist at any given time. Daredevil system operators who have large amounts of memory at their disposal may wish to change these variables to increase the system- defined limits. For details on how to do so, see the Lexicon entry mtune.