Detailed examples System V shared memory

1 Overview

System V shared memory is similar in concept to Posix shared memory, instead of mmap call after call shm_Open that first call shmget, then call shmat.
For each of the System V shared memory, the kernel maintains the following information structure, which is defined in sys / shm.h header file, which is annotated members of our concern.

struct shmid_ds
{
    struct ipc_perm  shm_perm;
    size_t           shm_segsz;  //共享内存区大小
    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 used to create a new shared memory or open an existing shared memory.

// returns successfully shared memory identifier, 
int shmget (key_t Key, size_t size, int oflag);
  • Size parameter is the size of the shared memory area, the remaining two parameters, and the meaning and usage as System V semaphores
  • When the actual operation of a new shared memory, the memory region size is initialized to 0 bytes
  • When the actual operation to open an existing shared memory, size can be set to 0, read and write permissions needed to oflag

shmat

shmat for connecting shmget create or open a shared memory to the calling process's address space.

// return the starting address mapping area success, else return -1 
void * the shmat (int the shmid, by shmaddr const void *, int In Flag);
  • shmid is shmget return identifier
  • shmaddr recommended to NULL, indicating that the initial decision by the system address map area
  • flag is usually set to 0, because as long as the calling process has read and write access shared memory, the memory mapping area can also read and write
  • flag can be set to read-only access limited SHM_RDONLY

shmdt

shmdt delete a connection established by shmat.

// 0 successful return, else return -1 
int shmdt (const void * by shmaddr);

shmctl

shmctl used for various control operations of the shared memory.

// 0 successful return, else return -1 
int the shmctl (the shmid int, int cmd, struct the shmid_ds * buf);

Cmd command can be used are three:

  • IPC_RMID: Delete the shared memory from the system at this time buf parameter is set to NULL
  • IPC_STAT: Returns shared memory structure corresponding shmid_ds by buf, typically use this command to obtain the size of the shared memory area
  • IPC_SET: shmid_ds provided corresponding to the shared memory structure shm_perm.uid, shm_perm.gid by buf and shm_perm.mode

3. Simple procedures

Code

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

Guess you like

Origin www.linuxidc.com/Linux/2019-09/160733.htm