今天分享一下,进程通信(IPC)——实现共享内存。
我们知道进程间通信的本质是让不同的进程看到同一内存。这之前我们用了不同的方式(管道,消息队列,信号量等等)让进程间能够通信,现在我们尝试着在内存共享区中开辟一段内存,即共享内存,让需要通信的两个进程通过页表映射到共享内存上,从而各自得到一个能映射到这段共享内存的虚拟地址的指针,进程间即可通过含有虚拟地址的指针对共享内存进行相应读写操作了。
实现共享内存的步骤:
1)创建共享内存(得到共享内存),使用shmget。
2)把共享内存挂接到各自进程,使用shmat。
3)各个进程对共享进程相应操作。
4)使用完毕后,取消共享内存对各自进程的挂接,使用shmdt。
5)最后,销毁共享内存,使用shmctl。注:谁创建谁销毁。
注:若不懂使用方式man一下,直接看文档。就不详细介绍共享内存相关函数的使用了。
由于共享内存也是随内核的,不主动释放会一直存在于内核中。所以系统有查看共享类存的相应命令,截图如下:
由于是在内存共享区中开辟一段内存,所以共享类存的速度是进程通信所有方法中最快的,但是它的缺点是:共享内存没有自带进程的同步与互斥,所以可能会导致进程间信息冲突。所有一般情况下,共享内存都会和信号量结合在一起用,这个以后有时间会补写一个完整的,今天就这样吧!
源代码和运行结果如下:
comm.h
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
union semu{
int val;
struct semid_ds* buf;
unsigned short* array;
struct seminfo* _buf;
};
#define PATHNAME "."
#define PROJ_ID 0X6666
int GreatShm(int nums);
int GetShm(int nums);
int DestoryShm(int semid);
#endif
ret.h
#include"comm.h"
int Common(int nums,int flags){
key_t keys = ftok(PATHNAME, PROJ_ID);
if(keys<0){
perror("ftok");
return -3;
}
int shmid = shmget(keys, nums, flags);
if(shmid < 0){
perror("shmget");
return -1;
}
return shmid;
}
int GreatShm(int nums){
return Common(nums, IPC_CREAT|IPC_EXCL);
}
int GetShm(int nums){
return Common( nums, IPC_CREAT);
}
int DestoryShm(int shmid){
if(shmctl(shmid, IPC_RMID, NULL)<0){
perror("shmctl");
return -2;
}
return 0;
}
serves.c
#include"comm.h"
#include<unistd.h>
int main(){
int shmid = GreatShm(4096);
printf("shmid id:%d\n", shmid);
char* addr = shmat(shmid, NULL, 0);
*addr = '\0';
int i=0;
while(i<12){
i++;
printf("addr:%s\n", addr);
sleep(1);
}
shmdt(addr);
DestoryShm(shmid);
return 0;
}
client.c
#include"comm.h"
#include<string.h>
int main(){
int shmid = GetShm(4096);
printf("shmid id:%d\n", shmid);
char* addr = shmat(shmid, NULL, 0);
int i=0;
while(i<8){
addr[i] = 'a';
i++;
printf("addr:%s\n", addr);
sleep(1);
}
addr[i] = '\0';
shmdt(addr);
// DestoryShm(shmid);
return 0;
}
Makefile
.PHONY:all
all:client serve
client:client.c ret.c
gcc -o $@ $^
serve:serves.c ret.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f serve client
运行结果
分享如上,望大家天天有进步!还有注各位看文的小朋友,节日快乐哈!