LinuxIPC通信之内存共享(C实现)

本文深入解析共享内存作为进程间通信(IPC)的高效方式,详细介绍了shmget、shmat、shmdt和shmctl等核心函数的使用方法,以及如何通过共享内存实现进程间的数据传输。

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号,配合使用,来实现进程间的同步和通信。

C:

相关函数:

shmget函数:用于开辟或指向一块共享内存,返回获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域。   
           keyt key: 共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。
                      如果两个进程没有任何关系,所以就用ftok()算出来一个标识符(或者自己定义一个)使用了。
           int size: 以字节为单位指定需要共享的内存容量。  
           int flag: 包含9个比特的权限标志,它是这块内存的模式(mode)以及权限标识。  
                      模式可取如下值:        
                        IPC_CREAT 新建(如果已创建则返回目前共享内存的id)  
                        IPC_EXCL   与 IPC_CREAT结合使用,如果已创建则返回错误  
                      将“模式” 和“权限标识”进行或运算,做为第三个参数。如:IPC_CREAT | IPC_EXCL | 0640 
                      其中0640为权限标识,4/2/1 分别表示读/写/执行3种权限,第一个0是UID,第一个6(4+2)表示拥
                      有者的权限,第二个4表示同组权限,第3个0表示他人的权限。
          函数调用成功时返回共享内存的ID,失败时返回-1。
          注:创建共享内存时,shmflg参数至少需要 IPC_CREAT | 权限标识,如果只有IPC_CREAT 则申请的地址都是
             k=0xffffffff,不能使用;
 
shmat函数:用来允许本进程访问一块共享内存的函数。
          第一次创建共享内存时,它不能任何进程访问,要想启用对该共享内存的访问,必须将其连接到一个进程的地址空间中。
          shmat函数就是用来完成此工作的。
          int   shmid  : 共享内存的ID,即共享内存的标识。     
          char *shmaddr: 共享内存连接到进程中的起始地址,如果shmaddr为NULL,内核会把共享内存映射到系统选定的地
                          址空间中;如果shmaddr不为NULL,内核会把共享内存映射到shmaddr指定的位置。
                          注:一般情况下我们很少需要控制共享内存连接的地址,通常都是让系统来选择一个地址,否则就会使应
                             用程序对硬件的依赖性过高。所以一般把shmaddr设为NULL。
          int shmflag :  本进程对该内存的操作模式,可以由两个取值:SHM_RND和SHM_RDONLY。SHM_RND为读写模式,
                          SHM_RDONLY是只读模式。需要注意的是,共享内存的读写权限由它的属主、它的访问权限和当
                          前进程的属主共同决定。如果当shmflg & SM_RDONLY为true时,即使该共享内存的访问权限允许写操
                          作,它也不能被写入。该参数通常会被设为0。
         函数调用成功时,返回共享内存的起始地址,失败时返回-1。
 
shmdt函数:用于函数删除本进程对这块内存的使用。
          shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。 
          char *shmaddr  是那块共享内存的起始地址。
          函数调用成功时返回0,失败时返回-1。
 
shmctl函数: 控制对这块共享内存的使用。
            int shmid: 共享内存的ID,即共享内存标识。
            int cmd  : 控制命令,表示要采取的动作,可取值如下:
                IPC_STAT  得到共享内存的状态:把shmid_ds结构中的数据设置为共享内存的当前关联值
                IPC_SET   改变共享内存的状态:把共享内存的当前关联值设置为shmid_ds结构中给出的值
                IPC_RMID  删除共享内存段
              shmid_ds结构至少包含以下成员:
                  struct shmid_ds {
                       uid_t shm_perm.uid;
                       uid_t shm_perm.gid;
                       uid_t shm_perm.mode;
                  }
            struct shmid_ds *buf: 一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。
                                  如果要改变共享内存的状态,用这个结构体指定。
         函数调用成功时返回0,失败时返回-1

实现内存共享传输数据

先运行,然后输入

#include <signal.h>
#include "headfile.h"

int shmid;

void rmid(int sig)
{
    //delete the share memory
    shmctl(shmid,IPC_RMID,NULL);
}

int main(int argc,char **argv)
{
    //register the signal
    signal(SIGINT,rmid);
    //get the key
    key_t key = ftok(PROJ_PATH,PROJ_ID);
    //create the share memory
    shmid = shmget(key,SHMSIZE,IPC_CREAT|0666);

    //map the share memory and return the address
    char *p = shmat(shmid,NULL,0);
    bzero(p,SHMSIZE);

    pid_t pid = getpid();
    memcpy(p,&pid,sizeof(pid_t));

    fgets(p+sizeof(pid_t),SHMSIZE,stdin);

    pause();
    
    return 0;
}

再运行

#include "headfile.h"

int main(int argc , char **argv)
{
    //get the key
    key_t key = ftok(PROJ_PATH,PROJ_ID);
    //create the shared memory
    int shmid = shmget(key,SHMSIZE,0666);

    //map the share memory and return the address
    char *p = shmat(shmid,NULL,0);
    printf("From SHM: %s",p+sizeof(pid_t));

    //send the SIGINT signal 
    kill(*((pid_t *)p),SIGINT);
    printf("send the SIGINT\n");
    //detach the share memory in process
    shmdt(p);
    printf("detach the share memory\n");
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值