The IPC: Intel – the process of communication

There are three types of IPC: Shared memory Shared memory semophore Message queue Named pipes can communicate between unrelated processes because of a file type called pipes in user space. For the three IPC types, there is no corresponding file type in user space. The FTOK key ensures that two processes in user space operate on the same IPC object process.

The implementation model of the three IPC objects:

Mapping between file I/O operations:

File I/O IPC
open Msg_get Shm_get Sem_get
read msgrecv shmat semop
write msgsnd shmat semop
close msgctrl shmctrl semctrl

The Shared memory

Shared memory is created and remains in the kernel until it is deleted or shut down.

Shmget function

This creates a shared memory, a cache, similar to an array of user space or space allocated by the malloc function. Create shared memory shmget:

The header file:#include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>Function prototype:int shmget(key_t key, int size, int shmflg)Function parameters: key: returned value of IPC_PRIVATE or ftok SIZE: size of the shared memory area SHMFLG: permission bit of the same function as open, which can also be expressed in base 8 Return: success: shared memory segment identifier, ID, file descriptor, failed: -1Copy the code

Run the ipcs -m command to view the IPC shared memory object. Run the ipcrm -m id command to delete the IPC shared memory object

#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main(a)
{
  int shmid;
  shmid=shmget(IPC_PRIVATE,128.0777);
  if(shmid <0)
  {
	printf("creat share memory failure\n");
	return - 1;
  }
  printf("creat share memory sucess shmid=%d\n",shmid);
  system("ipcs -m");
 // system("ipcrm -m shmid");
  return 0;
}
Copy the code

Ftok function

When the shmget function is used to create the shared memory, if the parameter is IPC_PRIVATE, the key value of the shared memory is 0. Can only be used for communication between related processes. If you want to make the key non-zero, you need the function ftok. User-space processes operate on the same IPC object in the kernel as long as the key value is the same.

Ftok functions: prototypechar ftok(const char *path, char key)Parameters: path: file path and file name key: one character Returned value: returns a key value on success, -1 on failureCopy the code

Shmat function

After the shared memory is created, the memory needs to be mapped to user space to reduce kernel access. The mapping function is shmat

Prototype:void *shmat(int shmid, const void *shmaddr, int shmflg) // Similar to mallocParameter: the first parameter, the ID number, the second parameter, the address mapped to,NULLThe third parameter, SHMFLG, SHM_RDONLY Shared memory is read-only. The default value is 0, indicating that the shared memory can be read or writtenNULL
Copy the code
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main(a)
{
  int shmid;
  int key;
  char *p;
  key=ftok("./a.c".'b');// Generate the key through a.c. The a.c file must exist
  if(key <0 )
  {
	printf("creat key fialure\n");
	return 2 -;
  }
  printf("creat key sucess key=%X\n",key);
  shmid=shmget(key,128,IPC_CREAT | 0777);
  if(shmid <0)
  {
	printf("creat share memory failure\n");
	return - 1;
  }
  printf("creat share memory sucess shmid=%d\n",shmid);
  system("ipcs -m");
 
  p=(char *)shmat(shmid,NULL.0);
  if(p == NULL)
  {
	printf("shmat function failure\n");
	return - 3;
  }
  //write share memory
  fgets(p,128.stdin);
 
  //start read share memory
  printf("share memory data:%s",p);
 
  printf("second read share memory data:%s",p);
 // system("ipcrm -m shmid");
  return 0;
}
Copy the code

SHMDT function

Delete the address mapping SHMDT from a user-space process

Prototype:int  shmdt(const void *shmaddr)Parameter: shmaddr Shared memory mapped address Returned: Success 0, error -1Copy the code

SHMCTL function

Delete the shared memory object SHMCTL from the kernel

Prototype:int shmctl(int shmid, int cmd, struct shmid_ds * buf)Parameter: shmid, the shared memory identifier to operate CMD: IPC_STAT, to obtain the object attribute value// Implement the command ipcs -mIPC_SET, set the object property IPC_RMID, and delete the object// Implement the command ipcrm-mReturns: success 0, error -1Copy the code
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(a)
{
  int shmid;
  int key;
  char *p;
  key=ftok("./a.c".'b');
  if(key <0 )
  {
	printf("creat key fialure\n");
	return 2 -;
  }
  printf("creat key sucess key=%X\n",key);
  shmid=shmget(key,128,IPC_CREAT | 0777);
  if(shmid <0)
  {
	printf("creat share memory failure\n");
	return - 1;
  }
  printf("creat share memory sucess shmid=%d\n",shmid);
  system("ipcs -m");
 
  p=(char *)shmat(shmid,NULL.0);
  if(p == NULL)
  {
	printf("shmat function failure\n");
	return - 3;
  }
  //write share memory
  fgets(p,128.stdin);
 
  //start read share memory
  printf("share memory data:%s",p);
 
  printf("second read share memory data:%s",p);
  
  shmdt(p);
  shmctl(shmid,IPC_RMID,NULL);
  system("ipcs -m ");
 
  return 0;
}
Copy the code

Example of communication between related processes

A. After the parent process completes the memory mapping, the parent process waits to read user input information. When the input is complete, SIGUSR1 signal is sent to the child process through kill to inform the child process that there is a message to read, and the parent process enters the sleep state.

B. After the child process completes the memory mapping, it goes to sleep. When a signal is received, the process wakes up and reads information from shared memory. When it’s done, it sends a SIGUSR2 signal to the parent to say that the message has been read and you can continue typing.

#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void myfun(int signum)
{
  return ;
}
int main(a)
{
  int shmid;
  int key;
  char *p;
  int pid;
  shmid=shmget(IPC_PRIVATE,128,IPC_CREAT | 0777);
  if(shmid <0)
  {
	printf("creat share memory failure\n");
	return - 1;
  }
  printf("creat share memory sucess shmid=%d\n",shmid);
 
  pid=fork();
  if(pid > 0)//parent process 
  { 
	signal(SIGUSR2,myfun);
    p=(char *)shmat(shmid,NULL.0);
    if(p == NULL)
    {
	   printf("parent process:shmat function failure\n");
	   return - 3;
    }
    while(1)
    {
      //write share memory
	  printf("parent process start write share memory:\n");
      fgets(p,128.stdin);
	  kill(pid,SIGUSR1);// child process read data 
	  pause();// wait child process read}}if(pid == 0)//child process 
  {
	signal(SIGUSR1,myfun);
	p=(char *)shmat(shmid,NULL.0);
	if(p == NULL)
	{
     printf("child process shmat function failure\n");
	 return - 3;
	}
    while(1)
	{
	 pause();// wait parent process write
     //start read share memory
     printf("share memory data:%s",p);
	 kill(getppid(),SIGUSR2);
	}
  }
  
  shmdt(p);
  shmctl(shmid,IPC_RMID,NULL);
  system("ipcs -m ");
 
  return 0;
}
Copy the code

Non – kin process

server.c

#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct mybuf
{
    int pid;
    char buf[124];
};
void myfun(int signum)
{
    return ;
}
int main(a)
{
    int shmid;
    int key;
    struct mybuf  *p;
    int pid;
    key=ftok("./a.c".'a');
    if(key < 0)
    {
        printf("creat key failure\n");
        return - 1;
    }
    printf("creat key sucess\n");
    shmid=shmget(key,128,IPC_CREAT | 0777);
    if(shmid <0)
    {
        printf("creat share memory failure\n");
        return - 1;
    }
    printf("creat share memory sucess shmid=%d\n",shmid);


    signal(SIGUSR2,myfun);
    p=(struct mybuf *)shmat(shmid,NULL.0);
    if(p == NULL)
    {
        printf("parent process:shmat function failure\n");
        return - 3;
    }
    //get client pid
    p->pid=getpid();//write server pid to share memory

    pause();//wait client read server pid;

    pid=p->pid;
    //write
    while(1)
    {
        //write share memory
        printf("parent process start write share memory:\n");
        fgets(p->buf,128.stdin);
        kill(pid,SIGUSR1);// client process read data 
        pause();// wait client process read
    }
    shmdt(p);
    shmctl(shmid,IPC_RMID,NULL);
    system("ipcs -m ");

    return 0;
}
Copy the code

client.c

#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct mybuf
{
    int pid;
    char buf[124];
};
void myfun(int signum)
{
    return ;
}
int main(a)
{
    int shmid;
    int key;
    struct mybuf  *p;
    int pid;
    key=ftok("./a.c".'a');
    if(key < 0)
    {
        printf("creat key failure\n");
        return - 1;
    }
    printf("creat key sucess\n");
    shmid=shmget(key,128,IPC_CREAT | 0777);
    if(shmid <0)
    {
        printf("creat share memory failure\n");
        return - 1;
    }
    printf("creat share memory sucess shmid=%d\n",shmid);


    signal(SIGUSR1,myfun);
    p=(struct mybuf *)shmat(shmid,NULL.0);
    if(p == NULL)
    {
        printf("parent process:shmat function failure\n");
        return - 3;
    }
    //get server pid
    //read share memory 
    pid=p->pid;
    //write client pid to share memory 
    p->pid=getpid();
    //kill signal
    kill(pid,SIGUSR2);

    //client start read data from share memory
    while(1)
    {
        pause();//wait server write data to share memory;
        printf("client process receve data from share memory:%s",p->buf);//read data 
        kill(pid,SIGUSR2);//server may write share memory
    }


    shmdt(p);
    shmctl(shmid,IPC_RMID,NULL);
    system("ipcs -m ");

    return 0;
}
Copy the code

The message queue

Message queues are chained, and messages can be of different types.

The maintenance queue structure msqID_ds in the message queue, where the first message pointer MSG_FIRST and the last pointer MSG_last.. Each message contains data data, data length, and data type type. The common message structure msgbuf is as follows:

struct msgbuf{
longMtype;// Message type
car mtext[N]; // Message body
}
Copy the code

Msgget function

The message queue creation function msgget can be used to view queue information through system(“ipcs -q”) :

The header file:#include <sys/types.h>
        #include <sys/ipc.h>
        #include <sys/msg.h>Function prototype:int msgget(key_t key, int flag); Parameter: key, key value associated with message queue flag, access permission of message queue Return: success, message queue ID, error:- 1
Copy the code

msgsnd

Function prototype:int msgsnd(int msqid, const void *msgp, size_t size, int flag)Parameters: MSqID, message queue ID MSGP, pointer to the message size, number of bytes in the message body flag, IPC_NOWAIT, the function will return 0 immediately before the message is sent, and will not return until the function is sent: success 0, error -1Copy the code

Receive message function MSGRCV

Function prototype:int msgrcv(int msgid, void *msgp, size_t size, long msgtype, int flag)Parameters: msgid, message queue number MSGP, buffer size to receive messages, number of message bytes to receive msgType, 0: The first message in the receiving message queue >0, the first message of type MSgType in the receiving message queue <0, the message whose type value is not greater than the absolute value of msgType and the smallest message in the receiving message queue Flag, 0: If there is no message, the process immediately returns to ENOMSG: success, received message length, error -1Copy the code

Message queue control function MSGCTL

Prototype:int msgctl(int msgqid, int cmd, struct msgqid_ds *buf)Parameters: msgid, message queue ID CMD, IPC_STAT, read the attributes of the message queue and save them in the buffer IPC_SET that buF points to, set the attributes of the message queue, this value is taken from the BUF parameter IPC_RMID, delete the message queue buf from the system, the message queue buffer returns: Success 0, error -1Copy the code

The sample

#include "sys/types.h"
#include "sys/msg.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct msgbuf
{
  long type;
  char voltage[124];
  char ID[4];
};
int main(a)
{
  int msgid;
  int readret;
  struct msgbuf sendbuf.recvbuf;
  msgid=msgget(IPC_PRIVATE,0777);
  if(msgid <0)
  {
	printf("creat message queue failure\n");
	return - 1;
  }
  printf("creat message queue sucess msgid=%d\n",msgid);
  system("ipcs -q");
  //init sendbuf
  sendbuf.type=100;
  printf("please input message:\n");
  fgets(sendbuf.voltage,124.stdin);
  //start write message to message queue
  msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
 
  //start read message from message queue
  memset(recvbuf.voltage,0.124);
  readret=msgrcv(msgid,(void *)&recvbuf,124.100.0);
  printf("recv:%s",recvbuf.voltage);
  printf("readret=%d\n",readret);
  //second read message queue
  msgrcv(msgid,(void *)&recvbuf,124.100.0);
  printf("second read after\n");
  //delete message queue
  msgctl(msgid,IPC_RMID,NULL);
  system("ipcs -q");
  return 0;
}
Copy the code

light

The IPC object of a semaphore is a semaphore collection containing multiple semaphore functions that operate on a collection.

POSIX semaphores compared to IPC semaphores

function POSIX semaphore The IPC lights
define sem_t sem1 semget
Initialize the sem_init semctl
P operation sem_wait semop
V operation sem_post semop

Semget function

The header file:#include <sys/types.h>
  #include <sys/ipc.h>
  #include <sys/sem.h>Function prototype:int semget(key_t key, int nsems, int semflg)Parameter: key: key associated with semaphore NSEMS: number of semaphore sets semflg: semaphore sets Access permission Returned: Success: semaphore set ID, error -1Copy the code

Semop function

Function prototype:int semop(int semid, struct sembuf *opsptr, size_t nops)Struct sembuf struct sembuf{
    short sem_num;// The number of the signal lamp to operate
    short sem_op;Wait until the semaphore value becomes 0. //1: release resources, V operation. //-1: allocates resources. Operation P
    short sem_flg;// 0,IPC_NOWAIT, SEM_UNDO}; Nops: indicates the number of semaphore operations. Returned: Succeeded0Error,- 1
Copy the code

Semctl function

Prototype:int semctl(int semid, int semnum, int cmd, ...union semun arg)Parameter: semID Semnum: ID of the semaphore to be modified CMD: GETVAL Get the value of the semaphore SETVAL Set the value of the semaphore IPC_RMID Delete the semaphore set from the system return: Success 0, error -1Copy the code

The sample

Threads synchronize using semaphores

#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
//#include "semaphore.h"
#include "sys/ipc.h"
#include "sys/sem.h"
//sem_t sem;
union semun 
{	                
	int  val;  	/* Value for SETVAL*/
	struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
								                  
	unsigned short  *array;  /* Array for GETALL, SETALL */
												                 
	struct seminfo* __buf;  /* Buffer for IPC_INFO(Linux-specific) */
};
 
int semid;
union semun mysemun;
struct sembuf mysembuf;
void *fun(void *var)//child thread code
{
  int j;
  //p wait
 // sem_wait(&sem); //sleep
  mysembuf.sem_op=- 1;
  semop(semid,&mysembuf,1);
  for(j=0; j<10; j++)//second
  {
    usleep(100);
	printf("this is fun j=%d\n",j); }}int main(a)//main thread code
{
  int i;
  char str[]="hello linux\n";
  pthread_t tid;
  int ret;
  semid=semget(IPC_PRIVATE,3.0777);
  if(semid < 0)
  {
	printf("creat semaphore failure\n");
	return - 1;
  }
  printf("creat semaphore sucess,semid=%d\n",semid);
  system("ipcs -s");
  mysemun.val=0;
  semctl(semid,0,SETVAL,mysemun);
  / / sem_init (& sem, 0, 0); //sem=0
  mysembuf.sem_num=0;
  mysembuf.sem_flg=0;
  ret=pthread_create(&tid,NULL,fun,(void *)str);
  if(ret<0)
  {
	printf("creat thread failure\n");
	return - 1;
  }
  for(i=0; i<10; i++)//first 
  {
	usleep(100);
	printf("this is main fun i=%d\n",i);
  }
  //v
 // sem_post(&sem);
  mysembuf.sem_op=1;
  semop(semid,&mysembuf,1);
  while(1);
  return 0;
}
Copy the code