System V shared memory

Catalog

1. overview

System V shared memory is conceptually similar to Posix shared memory. Instead of calling shm_Open and mmap, shmget is called first and shmat is called again.
For each System V shared memory, the kernel maintains the following information structure, which is defined in the sys/shm.h header file, with annotations for the members we need to focus on.

struct shmid_ds
{
    struct ipc_perm  shm_perm;
    size_t           shm_segsz;  //Shared memory area size
    pid_t            shm_lpid;
    pid_t            shm_cpid;
    shmatt_t         shm_nattch;
    shmat_t          shm_cnattch;
    time_t           shm_atime;
    time_t           shm_dtime;
    time_t           shm_ctime;
};

2. System V Shared Memory API

shmget

shmget is used to create a new shared memory or open an existing shared memory.

//The shared memory identifier was successfully returned.
int shmget(key_t key, size_t size, int oflag);
  • The parameter size is the shared memory area size, and the other two parameters have the same meaning and usage as the System V semaphore.
  • When the actual operation is to create a new shared memory, the size bytes of the memory area are initialized to 0.
  • When the actual operation is to open the existing shared memory, size can be set to 0, and oflag to read and write as required.

shmat

shmat is used to connect the shared memory created or opened by shmget to the address space of the calling process.

//Successfully returned the starting address of the mapping area, but failed to return - 1
void *shmat(int shmid, const void *shmaddr, int flag);
  • shmid is the identifier returned by shmget
  • The shmaddr recommendation is NULL, which means that the starting address of the mapping area is determined by the system.
  • flag is generally set to 0, because as long as the calling process has read and write access to shared memory, memory in the mapping area can also read and write.
  • flag can also be set to SHM_RDONLY to restrict read-only access

shmdt

shmdt deletes connections established by shmat.

//Successful return 0, failed return - 1
int shmdt(const void *shmaddr);

shmctl

shmctl is used for various control operations on shared memory.

//Successful return 0, failed return - 1
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

There are three commands that cmd can use:

  • IPC_RMID: Delete shared memory from the system, and then set the buf parameter to NULL.
  • IPC_STAT: Returns the shmid_ds structure corresponding to shared memory through buf, which is generally used to obtain the size of shared memory area.
  • IPC_SET: Setting shared memory by buf corresponds to shm_perm.uid, shm_perm.gid and shm_perm.mode in shmid_ds structure.

3. Simple procedures

code implementation

common.h

#ifndef _COMMON_H_
#define _COMMON_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define FTOK_FILE          "/home/delphi/ftok.file"
#define FTOK_ID            1

#define SHM_RD_PERMISSION  0444
#define SHM_WR_PERMISSION  0222
#define SHM_RW_PERMISSION  (SHM_RD_PERMISSION | SHM_WR_PERMISSION)

#endif

shmcreate.c

#include "common.h"

int main(int argc, char **argv)
{
    int length = atoi(argv[1]);
    int oflag = IPC_CREAT | SHM_RW_PERMISSION;
    int shmid = shmget(ftok(FTOK_FILE, FTOK_ID), length, oflag);

    if (shmid >= 0)
    {
        printf("shmget create success, shmid = %d\n", shmid);
    }

    return 0;
}

shmrmid.c

#include "common.h"

int main(int argc, char **argv)
{
    int shmid = shmget(ftok(FTOK_FILE, FTOK_ID), 0, SHM_RW_PERMISSION);
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

shmwrite.c

#include "common.h"

int main(int argc, char **argv)
{
    int shmid;
    unsigned char *shmadd;
    struct shmid_ds buf;
    int i;

    shmid   = shmget(ftok(FTOK_FILE, FTOK_ID), 0, SHM_RW_PERMISSION);
    shmadd  = shmat(shmid, NULL, 0);
    shmctl(shmid, IPC_STAT, &buf);

    for (i = 0; i < buf.shm_segsz; i++)
    {
        *shmadd++ = i % 256;
    }

    return 0;
}

shmread.c

#include "common.h"

int main(int argc, char **argv)
{
    int shmid;
    unsigned char *shmadd;
    unsigned char v;
    struct shmid_ds buf;
    int error = 0;
    int i;

    shmid   = shmget(ftok(FTOK_FILE, FTOK_ID), 0, SHM_RW_PERMISSION);
    shmadd  = shmat(shmid, NULL, 0);
    shmctl(shmid, IPC_STAT, &buf);

    for (i = 0; i < buf.shm_segsz; i++)
    {
        v = *shmadd++;

        if (v != (i % 256))
        {
            printf("error: shmadd[%d] = %d\n", i, v);
            error++;
        }
    }

    if (error == 0)
    {
        printf("all of read is ok\n");
    }

    return 0;
}

Code testing

Keywords: Linux Delphi

Added by phpbeginner on Wed, 18 Sep 2019 18:40:28 +0300