当前位置:网站首页>Interprocess communication (IPC): shared memory
Interprocess communication (IPC): shared memory
2022-07-05 18:41:00 【*Flowers bloom on the street】
Interprocess communication IPC : The Conduit 、 Semaphore 、 Shared memory 、 Message queue 、 Socket
Interprocess communication , Passing information between two processes
Except for sockets , The first few are mainly about the communication between two processes on the same host
Shared memory
Shared memory provides an effective way for multiple processes to share and transfer data . Shared memory is to apply for a piece of space in physical memory first , Multiple processes can map it to their own virtual address space . All processes have access to addresses in shared memory , It's like they're made of malloc The distribution is the same . If a process writes to shared memory data , The changes will be immediately seen by any other process that can access the same shared memory . Because it does not provide a synchronization mechanism , So we usually need to use other mechanisms to synchronize access to shared memory .
Interface
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
int shmget(key_t key, size_t size, int shmflg); // Create shared memory
shmget() Used to create or get shared memory
shmget() Successfully returned... Of shared memory ID, Failure to return -1
key: Different processes use the same key Value can get to the same shared memory
size: When creating shared memory , Specify the size of the shared memory space to request , In bytes
shmflg: contain 9 One bit permission flag
IPC_CREAT IPC_EXCL
IPC_CREAT: Existence opens , Create if it does not exist
IPC_EXCL and IPC_CREAT At the same time, an error will be reported , There is no creation ;
( Permissions are directly added to the back for assignment )
void* shmat(int shmid, const void *shmaddr, int shmflg); // mapping , Map shared memory to the address space of the process
shmat() Map the physical memory of the requested shared memory to the virtual address space of the current process
shmat() The first address of shared memory is returned successfully , Failure to return NULL
shmaddr: General NULL, The system automatically selects the mapped virtual address space
shmflg: A set of flag bits ,SHM_RND( This logo is related to shm_addr A combination of , Used to control the address of shared memory link ) SHM_RDONLY( It makes the connected memory read-only ), If not specified, give 0 Can
int shmdt(const void *shmaddr); // Break mapping
shmdt() Disconnect the current process shmaddr Shared memory mapping to
shmdt() Successfully returns 0, Failure to return -1
shmaddr Return address pointer
int shmctl(int shmid, int cmd, struct shmid_ds *buf); // Control shared memory ,eg: Delete
shmctl() Control shared memory
shmctl() Successfully returns 0, Failure to return -1
cmd: Actions to be taken
IPC_STAT hold shmid__ds The data in the structure is set to the current association value of the shared memory
IPC_SET If the process has sufficient permissions , Set the current association value of shared memory to shmid_dsThe value given in the structure
IPC_RMID Delete shared memory segmentbuf: It's a pointer , It points to a structure that contains shared memory patterns and access permissions .
Code implementation
process a Write data to shared memory , process b Read data from shared memory and display shma.c Code for :
a File input ,b File output
a.c file
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
int main()
{
// Create shared memory
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);//key The value is 1234, The shared memory size is 128,IPC_CREAT Existence opens , There is no creation , jurisdiction 0600
if(shmid==-1)
{
printf("shmget err\n");// Create failure
exit(1);
}
// mapping , Map shared memory to the address space of the process
// After the mapping is successful, you can use the pointer s Access this space
char*s=(char*)shmat(shmid,NULL,0);//shmat Itself returns a value void* type , Forced to char*,shmid Shared memory id, to NULL. The system automatically selects that the mapped virtual address space flag bit is not specified as 0
if(s==(char *)-1)
{
printf("shmat err\n");// Mapping failed
exit(1);
}
// Write data to shared memory
strcpy(s,"hello");
shmdt(s);// Break mapping
exit(0);
}
b.c file
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
int main()
{
// Create shared memory , Get shared memory if it exists
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);//key The value is 1234, The shared memory size is 128,IPC_CREAT Existence opens , There is no creation , jurisdiction 0600
if(shmid==-1)
{
printf("shmget err\n");// Create failure
exit(1);
}
// mapping , Map shared memory to the address space of the process
// After the mapping is successful, you can use the pointer s Access this space
char*s=(char*)shmat(shmid,NULL,0);//shmat Itself returns a value void* type , Forced to char*,shmid Shared memory id, to NULL. The system automatically selects the mapped virtual address space mark
The niche is not specified as 0
if(s==(char *)-1)
{
printf("shmat err\n");// Mapping failed
exit(1);
}
// use test File reads the value in the shared memory space
printf("read:%s\n",s);
shmdt(s);// Break mapping
exit(0);
}
After the shared memory is created successfully , There will always be , Even if the program is finished , There will be , Unless you delete this shared memory or restart
a.c The file is continuously written ,b.c The file is continuously read
a.c file
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
int main()
{
// Create shared memory
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);//key The value is 1234, The shared memory size is 128,IPC_CREAT Existence opens , There is no creation , jurisdiction 0600
if(shmid==-1)
{
printf("shmget err\n");// Create failure
exit(1);
}
// mapping , Map shared memory to the address space of the process
// After the mapping is successful, you can use the pointer s Access this space
char*s=(char*)shmat(shmid,NULL,0);//shmat Itself returns a value void* type , Forced to char*,shmid Shared memory id, to NULL. The system automatically selects that the mapped virtual address space flag bit is not specified as 0
if(s==(char *)-1)
{
printf("shmat err\n");// Mapping failed
exit(1);
}
while(1)
{
printf("input\n");
char buff[128]={0};// Put the input data in buff in
fgets(buff,128,stdin);
strcpy(s,buff);// Write the data to the shared memory first so that you can also read the data with end For the end sign
if(strncmp(buff,"end",3)==0)
{
break;// With end For the end of the input flag
}
}
shmdt(s);// Break mapping
exit(0);
}
b.c file
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
int main()
{
// Create shared memory , Get shared memory if it exists
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);//key The value is 1234, The shared memory size is 128,IPC_CREAT Existence opens , There is no creation , jurisdiction 0600
if(shmid==-1)
{
printf("shmget err\n");// Create failure
exit(1);
}
// mapping , Map shared memory to the address space of the process
// After the mapping is successful, you can use the pointer s Access this space
char*s=(char*)shmat(shmid,NULL,0);//shmat Itself returns a value void* type , Forced to char*,shmid Shared memory id, to NULL. The system automatically selects the mapped virtual address space mark
The niche is not specified as 0
if(s==(char *)-1)
{
printf("shmat err\n");// Mapping failed
exit(1);
}
while(1)
{
if(strncmp(s,"end",3)==0)
{
break;// First judge whether it is the end sign , Not output
}
sleep(1);
printf("resf:%s\n",s);// To read data
}
shmdt(s);// Break mapping
exit(0);
}
The operation results are as follows :
We can see ,b You can read the shared memory ,a input data b Can read , But as long as we don't enter new data ,b Just keep reading the last data ,
The result we want is to write once , Read it once , Don't write, don't read , We can go through Semaphore Solve this problem
Use semaphores to control shared memory
At this point, we need two semaphores ,s1,s2
sem.h
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/sem.h>
#define SEM1 0 // The first semaphore
#define SEM2 1 // The second semaphore
#define NUM 2 // The total number of semaphores
union semun
{
int val;// Initial value
};// Define your own
void sem_init();// Semaphore initialization
void sem_p(int index);//P operation , Create two semaphores , Distinguish by subscript
void sem_v(int index);//V operation
void sem_destroy();// The destruction
sem.c
#include"sem.h"
static int semid = -1;// Semaphore id, Only valid in this document
void sem_init()// Semaphore initialization
{
semid = semget((key_t)1234,NUM,IPC_CREAT|IPC_EXCL|0600);//key The value is 1234,SEM A semaphore , Create a new semaphore , If it already exists, an error will be reported , Access rights 0600
if(semid == -1)// New creation failed , Description already exists or creation failed
{
semid=semget((key_t)1234,NUM,0600);
//semid = semget((key_t)1234,SEM,0600);// When the signal already exists , Acquisition semaphore
if(semid == -1)
{
printf("semget err\n");// The previous description of the acquisition failure indicates that the creation failed
}
}
else// Because you want to create NUM A semaphore , Loop initialization
{
union semun a;
int arr[NUM]={1,0};// Semaphore initial value array
for(int i=0;i<NUM;i++)
{
a.val = arr[i];// Initial value of semaphore
if(semctl(semid,i,SETVAL,a)==-1)//i, The number of semaphores .SETVAL,a, Assign initial value to
{
printf("semctl init err\n");// Initialization failed print this statement
}
}
}
}
void sem_p(int index)//P operation
{
if(index<0 || index>=NUM)
{
return;
}
struct sembuf buf;// Changes to semaphores
buf.sem_num=index;// The subscript of the semaphore
buf.sem_op=-1;// What is performed on semaphores is p operation
buf.sem_flg = SEM_UNDO;// Sign a , If the program is abnormal, it can help v operation
if(semop(semid,&buf,1)==-1)
{
printf("semop p err\n");
}
}
void sem_v(int index)//V operation
{
if(index<0 || index>=NUM)
{
return;
}
struct sembuf buf;// Changes to semaphores
buf.sem_num=index;// The subscript of the semaphore
buf.sem_op=1;// What is performed on semaphores is v operation
buf.sem_flg = SEM_UNDO;
if(semop(semid,&buf,1)==-1)
{
printf("semop v err\n");
}
}
void sem_destroy()// The destruction
{
if(semctl(semid,0,IPC_RMID)==-1)//semid Signal to be deleted ,0 placeholder , according to semid Delete all signals created .IPC_RMID Delete semaphores
{
printf("semctl destroy err\n");
}
}
a.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
#include"sem.h"
int main()
{
// Create shared memory
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);//key The value is 1234, The shared memory size is 128,IPC_CREAT Existence opens , There is no creation , jurisdiction 0600
if(shmid==-1)
{
printf("shmget err\n");// Create failure
exit(1);
}
// mapping , Map shared memory to the address space of the process
// After the mapping is successful, you can use the pointer s Access this space
char*s=(char*)shmat(shmid,NULL,0);//shmat Itself returns a value void* type , Forced to char*,shmid Shared memory id, to NULL. The system automatically selects the mapped virtual address space mark >
The niche is not specified as 0
if(s==(char *)-1)
{
printf("shmat err\n");// Mapping failed
exit(1);
}
sem_init();// Semaphore initialization
while(1)
{
printf("input\n");
char buff[128]={0};// Put the input data in buff in
fgets(buff,128,stdin);
sem_p(SEM1);// Yes a File first P operation
strcpy(s,buff);// Write the data to the shared memory first so that you can also read the data with end For the end sign
sem_v(SEM2);// Yes b Document carried out v operation , Can't be v The operation is put after the following interpretation , Because if the final output end After the end ,b File cannot be v If the operation obtains permission, it cannot print the last
One
if(strncmp(buff,"end",3)==0)
{
break;// With end For the end of the input flag
}
}
shmdt(s);// Break mapping
exit(0);
}
b.c file
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
#include"sem.h"
int main()
{
// Create shared memory , Get shared memory if it exists
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);//key The value is 1234, The shared memory size is 128,IPC_CREAT Existence opens , There is no creation , jurisdiction 0600
if(shmid==-1)
{
printf("shmget err\n");// Create failure
exit(1);
}
// mapping , Map shared memory to the address space of the process
// After the mapping is successful, you can use the pointer s Access this space
char*s=(char*)shmat(shmid,NULL,0);//shmat Itself returns a value void* type , Forced to char*,shmid Shared memory id, to NULL. The system automatically selects the mapped virtual address space mark >
The niche is not specified as 0
if(s==(char *)-1)
{
printf("shmat err\n");// Mapping failed
exit(1);
}
sem_init();// Initialize semaphores
while(1)
{
sem_p(SEM2);
if(strncmp(s,"end",3)==0)
{
break;// First judge whether it is the end sign , Not output
}
printf("resf:%s\n",s);// To read data
sem_v(SEM1);
}
shmdt(s);// Break mapping
sem_destroy();// Destroy semaphore
exit(0);
}
Run the program
Running results
边栏推荐
- Whether to take a duplicate subset with duplicate elements [how to take a subset? How to remove duplicates?]
- Common time complexity
- 关于服装ERP,你想知道的都在这里了
- How to write good code defensive programming
- Cronab log: how to record the output of my cron script
- 如何写出好代码 - 防御式编程
- About statistical power
- Introduction to Resampling
- 2022年阿里Android高级面试题分享,2022阿里手淘Android面试题目
- How to obtain the coordinates of the aircraft passing through both ends of the radar
猜你喜欢
AI金榜题名时,MLPerf榜单的份量究竟有多重?
SAP 特征 特性 说明
LeetCode 6111. 螺旋矩阵 IV
websocket 工具的使用
A2L file parsing based on CAN bus (3)
Record eval() and no in pytoch_ grad()
Various pits of vs2017 QT
vulnhub之darkhole_2
深入底层C源码讲透Redis核心设计原理
Whether to take a duplicate subset with duplicate elements [how to take a subset? How to remove duplicates?]
随机推荐
输油管的布置数学建模matlab,输油管布置的数学模型
7-2 保持链表有序
【在优麒麟上使用Electron开发桌面应】
LeetCode 6109. 知道秘密的人数
Use QT to traverse JSON documents and search sub objects
What are the cache interfaces of nailing open platform applet API?
中文版Postman?功能真心强大!
技术分享 | 常见接口协议解析
Is it safe to open an account, register and dig money? Is there any risk? Is it reliable?
The origin of PTS, DTS and duration of audio and video packages
Fix vulnerability - mysql, ES
IDEA配置npm启动
buuctf-pwn write-ups (9)
Is it complicated to open an account? Is online account opening safe?
Record eval() and no in pytoch_ grad()
解决 contents have differences only in line separators
【pm2详解】
Solutions contents have differences only in line separators
如何写出好代码 - 防御式编程
常见时间复杂度