Shared Memory

The interface of shared memory.

int shmget(key_t key, size_t size, int flag);
int shmctl(int shmid, int cmd, struct shmid_ds *buf );

The cmd argument specifies one of the following five commands to be performed, on the segment specified by shmid.

  • IPC_STAT
  • IPC_SET
  • IPC_RMID
  • SHM_LOCK
  • SHM_UNLOCK

SHM_LOCK, SHM_UNLOCK can be executed only by superuser.

void *shmat(int shmid, const void *addr, int flag);

The address in the calling process at which the segment is attached depends on the addr
argument and whether the SHM_RND bit is specified in flag.

  • If addr is 0, the segment is attached at the first available address selected by the kernel. This is the recommended technique.Unless we plan to run the application on only a single type of hardware (which is highly unlikely today), we should not specify the address where the segment is to beattached. Instead, we should specify an addr of 0 and let the system choose the address.
  • If addr is nonzero and SHM_RND is not specified, the segment is attached at the address given by addr.
  • If addr is nonzero and SHM_RND is specified, the segment is attached at the address given by (addr − (addr modulus SHMLBA)). The SHM_RND command stands for ‘‘round.’’ SHMLBA stands for ‘‘low boundary address multiple’’ and is always a power of 2. What

The flag argument has two possible values.

  • SHM_RND
  • SHM_RDONLY
int shmdt(const void *addr);

Snippets of manipulate shared memory.

#include "apue.h"

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

#include <string.h>

#define PATH    "/workspace/c/apue/shm_x"
#define ID      1234
#define MESG    "Oh Scent"

#define SHM_SIZE    10000
#define SHM_MODE    0600

int
shm_init(void) {
    int shmid;
    key_t key;

    key = ftok(PATH, ID);
    if (key == -1) {
        err_sys("ftok failed");
    }

    if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT|SHM_MODE)) == -1) {
        err_sys("shmget failed");
    }

    return shmid;

}

void
shm_status(int shmid) {
    struct shmid_ds shm_buf;


    if (shmctl(shmid, IPC_STAT, &shm_buf) < 0) {
        err_sys("shmctl failed");
    }

    printf("shmid: %d\n", shmid);
    printf("shm_perm.uid: %d\n", shm_buf.shm_perm.uid);
    printf("shm_perm.gid: %d\n", shm_buf.shm_perm.gid);
    printf("shm_lpid: %d\n", shm_buf.shm_lpid);
    printf("shm_cpid: %d\n", shm_buf.shm_cpid);
    printf("shm_atime: %ld\n", shm_buf.shm_atime);
    printf("shm_dtime: %ld\n", shm_buf.shm_dtime);
    printf("shm_ctime: %ld\n", shm_buf.shm_ctime);

    printf("shm_nattch: %hu\n", shm_buf.shm_nattch);
}


void
shm_set(int shmid) {
    char *ptr;

    ptr = shmat(shmid, 0, 0);
    if (ptr == (void *) -1) {
        err_sys("shmat failed");
    }

    strncpy(ptr, MESG, strlen(MESG));

    shmdt(ptr);
}


void
shm_get(int shmid) {
    char *ptr;

    ptr = shmat(shmid, 0, 0);
    if (ptr == (void *) -1) {
        err_sys("shmat failed");
    }

    printf("get: %s\n", ptr);

    shmdt(ptr);
}

void
shm_rm(int shmid) {
   if (shmctl(shmid, IPC_RMID, 0) < 0) {
       err_sys("shmctl rm failed");
   }
}

int
main(void) {
    int shmid;

    shmid = shm_init();

    shm_set(shmid);
    shm_get(shmid);
    shm_status(shmid);

    exit(0);
}

POSIX Shared Memory

POSIX shared memory has nothing new, just using mmap combined with tmpfs file system.

shm_open + mmap

results matching ""

    No results matching ""