共享内存:
顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。(取自博客一位大哥-->Linux进程间通信——使用共享内存_tianmo2010的专栏-CSDN博客)
创建虚拟内存之后返回的地址空间属于用户空间, 不同进程可以将同一物理内存区域映射到各自的用户空间中
知道共享内存的原理之后,开始代码实现:
**首先创建共享内存:
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);
//1234这个可以随意给 只要是大于0的32位整数就好
//128是共享内存空间大小
//IPC_CREAT是创建共享内存的命令 0600是权限
**第一次创建完共享内存时,它还不能被任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
char *s = (char*)shmat(shmid,NULL,0);
//shmid就是上面shmget之后的返回值int shmid
shmat函数原型:
如上图所示shmat中第二个参数为空:如果为空的话,由系统选择一个合适的进程地址
然后shmat中第三个int shmflg置为零是他要是为0 读和写的权限都有的
**然后断开映射 (这块断开映射可有可无,因为进程结束后,自动就断开映射了)
shmdt(s);
//s是上述共享内存的地址
代码统一起来实现:
进程shma.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
int main()
{
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);
assert(shmid != -1);
char *s = (char*)shmat(shmid,NULL,0);
while(1)
{
printf("input : \n");
char buff[128] = {0};
fgets(buff,128,stdin);
strcpy(s,buff);//向共享内存s中写入数据
if(strncmp(buff,"end",3) == 0)
{
break;
}
}
shmdt(s);
}
shmb.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
int main()
{
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);
assert(shmid != -1);
char *s = (char*)shmat(shmid,NULL,0);
while(1)
{
if(strncmp(s,"end",3) == 0)
{
break;
}
printf("read: %s\n",s);
sleep(1);
}
shmdt(s);
}
ok 来看运行结果:在输入端shma.c中输入abc 然后输出端shmb.c就会不停的打出abc 直到shma.c输入end结束输入端 它才会停止打印abc
那么遇到这种情况该怎么办呢?前面一篇博客我写过 :凡是想让进程依次运行最好的办法就是信号量Linux编程题:信号量同步三进程依次打印若干次ABC_神厨小福贵!的博客-CSDN博客和这个是类似的问题
然后下面进行信号量的同步这两进程:实现原理
下面所使用的sem.c sem.h这些文件都在:我的另一篇博客中:
代码实现:shma.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
#include "sem.h"
int main()
{
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);
assert(shmid != -1);
char *s = (char*)shmat(shmid,NULL,0);
sem_init();
while(1)
{
printf("input : \n");
char buff[128] = {0};
fgets(buff,128,stdin);
sem_p(SEM1);
strcpy(s,buff);//向共享内存s中写入数据
sem_v(SEM2);
if(strncmp(buff,"end",3) == 0)
{
break;
}
}
shmdt(s);
}
shmb.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
#include "sem.h"
int main()
{
int shmid = shmget((key_t)1234,128,IPC_CREAT|0600);
assert(shmid != -1);
char *s = (char*)shmat(shmid,NULL,0);
sem_init();
while(1)
{
sem_p(SEM2);
if(strncmp(s,"end",3) == 0)
{
break;
}
printf("read: %s\n",s);
sleep(1);
}
shmdt(s);
sem_destroy(); //该程序是最后退出的 由该程序完成信号量的销毁
}
然后进行可执行程序的编译链接:
看运行结果:
该程序的难点在于仅仅使用共享内存进行通信的时候,输出输入达不到预期效果(也就是输出端一直打印同一个值),这时候就得想到使用信号量来同步两个进程,来使得两进程可以达到通信的效果!
“能看到这里的亲兄弟们,都是认真上进的亲兄弟,加油!!!”