Linux – Interprocess Communication (System V)

Table of Contents

1. Shared memory

Apply for shared memory shmget

Control shared memory shmctl

Associative shared memory shmat / Deassociated shared memory shmdt

2. Message queue

Create or open a message queue msgget

send message msgsnd / receive message msgrcv

Control message msgctl

3. Semaphore

Create or open a semaphore semget

Semaphore operation semop

Semaphore control semctl


One, shared memory

Shared memory is the fastest form of inter-process communication IPC, which allows two or more processes to share the same area of physical memory (usually called a segment), and inter-process data transfer will no longer involve the kernel (that is, it will no longer pass kernel system calls to pass data);

Maintain shared memory data structures

//vim /usr/include/bits/shm.h
struct shmid_ds {
    struct ipc_perm shm_perm; /* operation perms */
    int shm_segsz; /* size of segment (bytes) */
    __kernel_time_t shm_atime; /* last attach time */
    __kernel_time_t shm_dtime; /* last detach time */
    __kernel_time_t shm_ctime; /* last change time */
    __kernel_ipc_pid_t shm_cpid; /* pid of creator */
    __kernel_ipc_pid_t shm_lpid; /* pid of last operator */
    unsigned short shm_nattch; /* no. of current attaches */
    unsigned short shm_unused; /* compatibility */
    void *shm_unused2; /* ditto - used by DIPC */
    void *shm_unused3; /* unused */
};
//vim /usr/include/bits/ipc.h
 /* Data structure used to pass permission information to IPC operations. */
  struct ipc_perm
    {
      __key_t __key; /* Key. */
      __uid_t uid; /* Owner's user ID. */
      __gid_t gid; /* Owner's group ID. */
      __uid_t cuid; /* Creator's user ID. */
      __gid_t cgid; /* Creator's group ID. */
      unsigned short int mode; /* Read/write permission. */
      unsigned short int __pad1;
      unsigned short int __seq; /* Sequence number. */
      unsigned short int __pad2;
      __syscall_ulong_t __unused1;
      __syscall_ulong_t __unused2;
    }; 

Apply for shared memory shmget

  • key, used to uniquely distinguish shared memory, can be generated by the ftok function;
  • size, it is recommended to be a multiple of 4KB;
  • shmflg, label;
    • IPC_CREAT, if the target shared memory does not exist, create it, otherwise obtain it;
    • IPC_CREAT | IPC_EXCL, if the target shared memory does not exist, create it, otherwise an error occurs;

//vim /usr/include/bits/ipc.h
  #include <bits/types.h>
      
  /* Mode bits for `msgget', `semget', and `shmget'. */
  #define IPC_CREAT 01000 /* Create key if key does not exist. */
  #define IPC_EXCL 02000 /* Fail if key exists. */
  #define IPC_NOWAIT 04000 /* Return error on wait. */
      
  /* Control commands for `msgctl', `semctl', and `shmctl'. */
  #define IPC_RMID 0 /* Remove identifier. */
  #define IPC_SET 1 /* Set `ipc_perm' options. */
  #define IPC_STAT 2 /* Get `ipc_perm' options. */
  #ifdef __USE_GNU
  # define IPC_INFO 3 /* See ipcs. */
  #endif 

Control shared memory shmctl

Associated shared memory shmat / delinked shared memory shmdt

//makefile
CC=gcc
.PHONY:all
all: server client
    
server:server.c
  $(CC) -o $@ $^
client:client.c
  $(CC) -o $@ $^
        
.PHONY:clean
clean:
  rm -rf server client 
//comm.h
#pragma once
#include <stdio.h>
    
#define PATH_NAME "/home/wz/Desktop/pipe"
#define PROJ_ID 0x6666

#define SIZE 4097
//server.c
include "comm.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
    
int main()
{
  key_t k = ftok(PATH_NAME, PROJ_ID);
  if(k < 0){
    perror("ftok");
    return 1;
  }
  printf("key: %x\
", k);
  sleep(3);
    
  int shmid = shmget(k, SIZE, IPC_CREAT|IPC_EXCL|0644);
  if(shmid < 0){
    perror("shmget");
    return 2;
  }
  printf("shmid: %d\
", shmid);
  sleep(3);
    
  char* start = (char*)shmat(shmid, NULL, 0);
  printf("server already attach on shared memory!\
");
  while(1){
    printf("%s\
", start);
    sleep(1);
    if(strlen(start) == 26)
      break;
  }
    
  shmdt(start);
  printf("server already dattach off shared memory!\
");
  sleep(3);
    
  shmctl(shmid, IPC_RMID, NULL);
  printf("delete %d\
", shmid);
  return 0;
} 
//client.c
#include "comm.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
    
int main()
{
  key_t k = ftok(PATH_NAME, PROJ_ID);
  if(k < 0){
    perror("ftok");
    return 1;
  }
  printf("key: %x\
", k);
  sleep(3);
    
  int shmid = shmget(k, SIZE, IPC_CREAT);
  if(shmid < 0){
    perror("shmget");
    return 2;
  }
  printf("client shmid: %d\
", shmid);
  sleep(3);
    
  char* start = (char*)shmat(shmid, NULL, 0);
  printf("client already attach on shared memory!\
");
    
  char c = 'A';
  while(c <= 'Z'){
    start[c - 'A'] = c;
    c++;
    sleep(1);
  }
    
  shmdt(start);
  printf("client already dattach off shared memory!\
");
  sleep(3);
  return 0;
}
//View shared memory
[wz@192 pipe]$ ipcs -m
//Delete shared memory with specified id
[wz@192 pipe]$ ipcrm -m 426047

The life cycle of shared memory depends on the OS;

Shared memory does not provide any synchronization or mutual exclusion and is independent of each other;

Shared memory is the fastest among all inter-process communications;

The shm allocated by the shared memory system is based on 4KB as the basic unit. If you specify something other than a multiple of 4KB, the excess will be wasted;

Two, message queue

Message queue is a method of inter-process communication, providing a way to send a piece of data from one process to another process;

Maintain message queue data structures

//vim /usr/include/bits/msq.h
/* Structure of record for one message inside the kernel.
     The type `struct msg' is opaque. */
  struct msqid_ds
  {
E> struct ipc_perm msg_perm; /* structure describing operation permission */
    __time_t msg_stime; /* time of last msgsnd command */
  #ifndef __x86_64__
    unsigned long int __unused1;
  #endif
    __time_t msg_rtime; /* time of last msgrcv command */
  #ifndef __x86_64__
    unsigned long int __unused2;
  #endif
    __time_t msg_ctime; /* time of last change */
  #ifndef __x86_64__
    unsigned long int __unused3;
  #endif
    __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
    msgqnum_t msg_qnum; /* number of messages currently on queue */
    msglen_t msg_qbytes; /* max number of bytes allowed on queue */
    __pid_t msg_lspid; /* pid of last msgsnd() */
    __pid_t msg_lrpid; /* pid of last msgrcv() */
    __syscall_ulong_t __unused4;
    __syscall_ulong_t __unused5;
  }; 

Create or open message queue msgget

  • key, used to uniquely distinguish shared memory, can be generated by the ftok function;
  • msgflg,label;
    • IPC_CREAT, if the target message queue does not exist, create it, otherwise obtain it;
    • IPC_CREAT | IPC_EXCL, if the target message queue does not exist, create it, otherwise an error occurs;

send message msgsnd / receive message msgrcv

Control message msgctl

Three, semaphore

The semaphore is not originally used to transmit data between processes, it is used as the original synchronization process, mainly used for synchronization and mutual exclusion; because the process requires shared resources, some resources need to be mutually exclusive; some resources in the system are only allowed to be used at one time A process uses these resources as critical resources or mutually exclusive resources; a program segment involving mutually exclusive resources is called a critical section;

Maintain the semaphore data structure

//vim /usr/include/bits/sem.h
  /* Data structure describing a set of semaphores. */
  struct semid_ds
  {
    struct ipc_perm sem_perm; /* operation permission struct */
    __time_t sem_otime; /* last semop() time */
    __syscall_ulong_t __unused1;
    __time_t sem_ctime; /* last time changed by semctl() */
    __syscall_ulong_t __unused2;
    __syscall_ulong_t sem_nsems; /* number of semaphores in set */
    __syscall_ulong_t __unused3;
    __syscall_ulong_t__unused4;
  };

create or open semaphore semget

semaphore operation semop

semaphore control semctl