Linux进程间的通信----->共享内存

本文介绍了如何在Linux中使用共享内存进行进程间通信,展示了创建、映射和同步共享内存的过程。随后,通过引入信号量解决共享内存通信中的问题,使两个进程按顺序交替打印数据。作者详细讲解了代码实现和信号量同步的原理,适合学习进程间通信和同步技术。
摘要由CSDN通过智能技术生成

共享内存:

        顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用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这些文件都在:我的另一篇博客中:

Linux编程题:信号量同步三进程依次打印若干次ABC_神厨小福贵!的博客-CSDN博客三个进程依次打印ABC.....思路及大致流程如下:思路取自这位大哥:Linux编程题:创建3个线程分别打印abc,用信号量进行同步_cleverlemon的博客-CSDN博客这位大哥写的是线程,不需要自己封装sem那些初始化函数,pv操作函数以及销毁函数,这篇写的是多进程,麻烦一些,大致思路一毛一样来看代码实现:先来对sem所需的初始化函数,pv操作函数,销毁函数进行封装:sem.h#include <stdio.h>#include <stdl.https://blog.csdn.net/qq_45829112/article/details/121222304  

代码实现: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(); //该程序是最后退出的  由该程序完成信号量的销毁
}

然后进行可执行程序的编译链接:

 看运行结果:

 该程序的难点在于仅仅使用共享内存进行通信的时候,输出输入达不到预期效果(也就是输出端一直打印同一个值),这时候就得想到使用信号量来同步两个进程,来使得两进程可以达到通信的效果!

“能看到这里的亲兄弟们,都是认真上进的亲兄弟,加油!!!”

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值