进程间通信(IPC)
进程间通信,InterProcess Communication。进程间通信的常见方式有:管道、消息队列、共享内存、信号量
共享内存
简介
可实现两个进程访问同一个逻辑内存。共享内存是由IPC为进程创建的一个特殊的地址范围,出现在该进程的地址空间中,其他进程可以将同一段共享内存连接到它们自己的地址空间中。所有进程都可以访问共享内存中的地址。
系统调用接口
#include<sys/tpyes.h>
#include<sys/ipc.h>
#include<sys/shm.h>
/* key: 整数值,不相关的进程可以通过它来访问同一个共享内存,以此键值来获取一个有效的共享内存标识符;
size: 要申请的共享内存大小,以字节为单位;
shmflg: 权限位;
返回值: 创建成功则返回共享内存标识符,失败返回-1;
*/
int shmget(key_t key, size_t size, int shmflg);
/*第一次创建共享时,还不能被程序使用,必须使用shmat函数将其连接到一个进程的地址空间中*/
/* shm_id: shmget返回的共享内存标识符;
shm_addr: 指定共享内存连接到当前进程中的地址位置,此参数值通常是个空指针,表示让系统来选择共享内存的地址;
shmflg: 一组表示位,如读写权限等;
返回值: 调用成功则返回共享内存第一个字节的指针,如果失败则返回-1;
*/
void* shmat(int shm_id, const void* shm_addr, int shmflg);
/*shmdt函数用来将共享内存从当前进程中分离*/
/* shm_addr: shmat返回的地址指针;
返回值: 成功返回0,失败返回-1;
*/
int shmdt(const void* shm_addr);
/* shm_id: shmget返回的共享内存标识符;
command: 要采取的动作,例如删除共享内存;
buf: 指向包含内存模式和访问权限的结构;
返回值:成功返回0,失败返回-1;
*/
int shmctl(int shm_id, int command, struct shmid_ds* buf);
例子
生产者、消费者
需求:消费者创建一个共享内存段,并将其中的内容显示出来;生产者连接到一个已有的共享内存段,并允许我们向其中写入数据
/* share.h */
#define TEXT_SZ 2048
struct shared_use_st{
int written_by_you;
char some_text[TEXT_SZ];
};
/* consumer.cpp */
//
// Created by renjie on 2020/11/12.
//
#include<unistd.h>
#include <string.h>
#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<memory>
#include<stdio.h>
#include<stdlib.h>
#include"share.h"
using namespace std;
int main(){
int running=1;
int shmId=shmget((key_t)1234, sizeof( shared_use_st), 0666|IPC_CREAT);
if(shmId==-1){
perror("shmget error");
exit(EXIT_FAILURE);
}
void* shmAddr=shmat(shmId,(void*)0,0);
if(shmAddr==(void*)-1){
perror("shmat error");
exit(EXIT_FAILURE);
}
cout<<"consumer";
cout<<"memory attached at "<<shmAddr;
shared_use_st* shared_buff=(shared_use_st*)shmAddr;
shared_buff->written=0;
while(running){
if(shared_buff->written){
cout<<shared_buff->someText<<endl;
sleep(1);
shared_buff->written=0;
if(strcmp(shared_buff->someText,"end")==0){
running=0;
}
}
}
if(shmdt(shmAddr)==-1){
perror("shmdt error");
exit(EXIT_FAILURE);
}
if(shmctl(shmId,IPC_RMID,0)==-1){
perror("shmctl error");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
/* producer.cpp */
//
// Created by renjie on 2020/11/12.
//
#include<unistd.h>
#include <string.h>
#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<memory>
#include<stdio.h>
#include<stdlib.h>
#include"share.h"
using namespace std;
#define BUFSIZ 2048
int main(){
int running=1;
char buffer[BUFSIZ];
int shmId=shmget((key_t)1234, sizeof( shared_use_st), 0666|IPC_CREAT);
if(shmId==-1){
perror("shmget error");
exit(EXIT_FAILURE);
}
void* shmAddr=shmat(shmId,(void*)0,0);
if(shmAddr==(void*)-1){
perror("shmat error");
exit(EXIT_FAILURE);
}
shared_use_st* shared_buff=(shared_use_st*)shmAddr;
while(running){
while(shared_buff->written==1){
sleep(1);
cout<<"waiting for client ..\n";
}
printf("enter some text:");
cin>>buffer;
//wmemcpy(reinterpret_cast<wchar_t *>(shared_buff->someText), reinterpret_cast<const wchar_t *>(buffer), TEXT_SZ);
strcpy(shared_buff->someText,buffer);
shared_buff->written=1;
if(strcmp(shared_buff->someText,"end") == 0){
running=0;
}
}
}