当前位置:首页 > 公众号精选 > 嵌入式云IOT技术圈
[导读]上节和上上节我们分享了Linux进程间通信的管道、消息队列、信号以及信号量的基本原理和实践,文章如下: Linux进程间通信(上)之管道、消息队列实践 Linux进程间通信(中)之信号、信号量实践 这节我们就来分享一下Linux的最后一种进程间通信的方式:共享内存。


上节和上上节我们分享了Linux进程通信的管道、消息队列、信号以及信号量的基本原理和实践,文章如下:

Linux进程间通信(上)之管道、消息队列实践

Linux进程间通信(中)之信号、信号量实践

这节我们就来分享一下Linux的最后一种进程间通信的方式:共享内存

1、什么是共享内存

共享内存就是两个不相关的进程之间可以直接访问同一段内存,共享内存在两个正在运行的进程之间共享和传递数据起到了非常有效的方式。在不同的进程之间共享的内存通常安排为同一段物理内存,进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以直接访问共享内存中的地址。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程;其实就是映射一段能够被其它内存所访问到的内存,这段内存由一个进程创建,但是多个进程都可以去访问。共享内存是最快的IPC方式,它是通过其它通信方式的效率不足而专门设计的。往往都是和其它通信机制配合使用,来实现进程间的同步和通信。

共享内存的使用和信号量其实也是差不多的,都是使用接口的形式,共享内存的接口比信号量的接口更加的简单,我们一起去了解下共享内存的使用。

共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。我们下面来分析每一个函数的用法。

1.1、创建共享内存

int shmget(key_t key, size_t size, int shmflg);

第一个参数是共享内存段的命名,shmget成功时返回一个关于key相关的标识符,用于后续的共享内存函数。当调用失败返回-1。其它进程也可以通过shmget函数返回值访问同一个共享内存。第二个参数是指定共享内存的容量;第三个shmflg是一个权限标志,它的作用和open和mode函数都是相同的,当共享内存不存在的时候则通过IPC_CREAT来创建。共享内存的权限标准和文件读写的权限一样。

1.2、启动对共享内存的访问

void *shmat(int shm_id, const void *shm_addr, int shmflg);

当我们第一次创建完共享内存时,它还不能被任何进程访问,shmat函数就是用来启动对共享内存的访问,并把共享内存连接到当前进程的地址空间。

shm_id是由shmget函数返回的共享内存标识;shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。最后一个参数是标志位通常都是0。调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1。

1.3、共享内存从当前内存中分离

int shmdt(const void *shmaddr);

这个函数只是从共享内存中分离而不是删除,这一点要分清楚,对于初学者而言这里很容易掉坑,使共享内存在当前进程中不可再用。

参数shmaddr是shmat函数返回的地址指针,调用成功时返回0,失败时返回-1。

1.4、控制共享内存

int shmctl(int shm_id, int command, struct shmid_ds *buf);

第一个参数是shaget函数返回的共享内存标识符;command参数是要采取的操作,它由 IPC_STAT、IPC_SET和IPC_RMID组成,分别IPC_STAT代表把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值;IPC_SET代表如果进程有足够的权限,就可以把共享内存的当前关联值设置为shmid_ds结构中给出的值;IPC_RMID代表删除共享内存段。第三个参数buf代表一个结构指针,它指向共享内存的模式或访问权限的结构。

shmid_ds结构至少包括以下成员:

struct shmid_ds  
{  
  uid_t shm_perm.uid;
  uid_t shm_perm.gid;
  mode_t shm_perm.mode;
};

2、共享内存案例

shm_snd.c

#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024

int main()
{
        int shmid;
        char *shmptr;   
        //创建共享内存
        shmid = shmget(0x66, SHM_SIZE, IPC_CREAT|0666);
        //创建失败
        if(shmid < 0)
        {               
            perror("shmget");
            return -1 ;
        }
        //对共享内存的访问
        shmptr = shmat(shmid, 0, 0);
         if (shmptr == (void *)-1)
        {
            perror("shmat");
            return -2 ;
        }
        // 往共享内存写数据
        strcpy(shmptr, "shmat write ok");
        shmdt(shmptr);
        return 0 ;
}

shm_rcv.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024

int main()
{
    int shmid;
    char *shmptr;
    shmid = shmget(0x66, SHM_SIZE, IPC_CREAT|0666);
    if(shmid < 0)
    {
        perror("shmget");
        return -1 ;
    }
    shmptr = shmat(shmid, 0, 0);
    if (shmptr == (void *)-1)
    {
        perror("shmat");
        return -2 ;
    }
    // 从共享内存读数据
    printf("read:%s\n", shmptr);
    shmdt(shmptr);
    return 0 ;
}

运行结果:

先分别编译shm_snd.c和shmrcv.c这两个程序,生成shmrcv和shmsnd这两个可执行程序。

接下来,首先执行shmsnd,会得到以下结果:

什么都没有?共享内存创建成功了吗?当然是成功了,可以通过ipcs –m命令查看:

如图上图所示,nattch项下的数字为0那个就是刚刚使用shmsnd这个可执行程序创建的一段共享内存。当然,我们还往共享内存发了shmat write ok这个字符串,下面运行shmrcv这个程序,看看是否能把写进共享内存的数据读出来。

成功读出。同样的,也可以删除共享内存,如何删除?也一样有两种方法。

(1)使用ipcrm –m shmid可以删除共享内存

如上图,我们已经知道0x66的shmid为1835021,所以只要执行ipcrm –m 1835021命令即可删除,如下图所示,成功删除。

(2)使用shmctl 函数写入IPC_RMID指令删除共享内存

shmrm.c

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(void)
{
        int shmid ;
        //同样,首先先打开共享内存
        shmid = shmget(0x66 , 0 , 0);
        if(-1 == shmid)
        {
                perror("open  shmkey 0x66 fail");
                return -1 ;
        }
        //成功的话,向shmctl写入参数,IPC_RMID表示立刻删除,后面的参数被忽略,为0
        int ret ;
        //写入的是参数
        ret = shmctl(shmid , IPC_RMID , NULL);
        if(ret < 0)
        {
                perror("remove shm fail");
                return -2 ;
        }
        printf("remove key:%d success ... \n" , 0x66);
        return 0 ;
}

运行结果:

往期精彩

Linux进程间通信(中)之信号、信号量实践

Linux进程通信(上)之管道、消息队列实践

【Linux系统编程】IO标准缓冲区

替代传统串口屏的Yoxios了解一下!

觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭