进程间通信——共享内存

本文详细介绍了Linux系统下如何使用共享内存进行进程间通信,包括shmget、shmat、shmdt和shmctl等关键接口的用法,并通过代码示例展示了创建、链接、解除映射及删除共享内存的过程。此外,还提到了ipcs和ipcrm命令用于查看和管理共享内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

目录

前言

共享内存

接口

    shmget

    代码示例

    shmat

    shmdt

    shmctl

    ipcs -m 指令

    ipcrm -m shmid 指令

    代码示例


前言

    共享内存区别于管道,是最快的进程间通信方式,不需要对数据进行拷贝就可以实现数据交换。不同进程将共享内存链接到各自的空间,所有链接了这块共享内存的进程都可以共同访问这个共享内存中的数据。

    另外一题,共享内存没有同步机制,而管道具有同步机制。

共享内存

    作用:实现多个进程间的数据共享

    特性:最快的进程间通信,生命周期不随进程而是随内核(不会因为进程退出而释放)

    原理:开辟一块物理内存,多个进程将这块内存映射到自己的虚拟地址,然后可以通过虚拟地址访问这块共享内存

 

接口

    shmget

    ① int shmget(key_t key,size_t size,int shmflg);创建共享内存

        key:共享内存标识符(名字),key的值为IPC_PRIVATE时表示系统每次都会申请一个新的标识符。

        size:共享内存大小

        shmflg:权限标志,常用有IPC_CREAT和 IPC_EXCL ,后面再加权限

                      IPC_CREAT  ——  共享内存不存在时创建共享内存,存在则打开

                      IPC_EXCL  ——  与IPC_CREAT共同使用,不存在时创建,存在则报错

              例如:IPC_CREAT | IPC_EXCL | 0644

        返回值:成功返回操作句柄,失败返回-1。

    代码示例

#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdlib.h>


int main(){
  int shmid = shmget(IPC_PRIVATE,4096,IPC_CREAT|0644);

  if(shmid<0){
    printf("shmget failed!\n");
    exit(-1);
  }else{
    printf("shmid=%d\n",shmid);
  }
  return 0;
}                                                

   

 

    shmat

    ② void* shmat(int shmid,void *addr,int shmflg); 链接共享内存

        shmid:打开一个共享内存时返回的操作句柄

        addr:映射首地址,通常置为NULL,来让系统进行分配

        shmflg:默认为0,表示可读可写,置为SHM_RDONLY表示只读

        返回值:成功时返回映射首地址,失败返回-1。

    shmdt

    ③ int shmdt(const void *shmaddr); 解除与共享内存的映射关系

        shmaddr是映射的首地址,也就是shmat的返回值

    shmctl

    ④ int shmctl(int shmid,int cmd,struct shmid_ds *buf); 可用于删除共享内存

        shmid:是shmget返回的句柄

        cmd:要进行的操作,值为IPC_RMID时表示标记一个共享内存需要被删除

        buf:用于设置或获取共享内存信息,如果cmd是IPC_RMID,则buf被忽略,删除时置NULL

        注意:shmctl在删除一块共享内存时不会立刻删除,而是先阻断链接(后来的进程无法链接),等连接数为0后(已经链接的进程全退出后)再执行删除。

    ipcs -m 指令

    该指令可用于查看共享内存的信息

    ipcrm -m shmid 指令

    该指令可在程序外面手动删除共享内存,因为有些时候我们在运行程序时会ctrl+c暂停,或是遇到其他意外导致之前创建的共享内存没能被及时删除,此时如果需要删除就可以用这个指令,当然重新开机也可以清除所有的共享内存。

    上面的nattch是连接数    

    代码示例

    注意shmat和shmdt要一起使用才起作用

#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>


int main(){
  int shmid = shmget(IPC_PRIVATE,4096,IPC_CREAT | 0666);
                                            
  if(shmid<0){                              
    printf("shmget failed!\n");             
    exit(-1);                               
  }else{                                    
    printf("shmid=%d\n",shmid);             
  }                                         
                                            
                                            
  char *str = (char*)shmat(shmid,NULL,0);//链接shmid的共享内存
  if(str<0){                                
    printf("connection failed!\n");         
    exit(-1);                               
  }else{                                    
    printf("连接成功\n");                   
  }                                         
                                            
  shmdt(str);//删除链接                     
                                            
  shmctl(shmid,IPC_RMID,0);//删除共享内存                     
  return 0;                                 
}                                           

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值