linux进程间通信之------共享内存

概述        

       共享内存是进程间通信最简单的方式之一,是在两个独立的进程用户地址空间中映射到同一块物理内存,因为数据字节由内存映射到用户空间,所以它也是进程通信最快的IPC方式。但是由于内核没有提供对访问共享内存进行同步,所以需要我们自己实现同步机制,一般是使用信号量。

所以一般操作模型是:

  • 获取mutex,锁定共享内存。

  • 将要通信的数据写入(读取)共享内存。

  • 释放mutex。

 

共享内存原理图:

 

共享内存相关函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int semget(key_t key, int size, int flag);
void *shmat(int shmid, void *addr, int flag);
int shmdt(void *addr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

 

1、 ftok() 获得一个key

key_t ftok(const char *pathname, int proj_id);

pathname:一定要在系统中存在并且进程能够访问的;

proj_id:一个1-255之间的一个整数值,典型的值是一个ASCII值;

2、shmget 创建共享内存

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

成功返回一个共享内存标识符,失败返回-1

key:一个用来标识共享内存块的键值(一般由ftok产生)

size:指定了所申请的内存块的大小

shmflg:操作共享内存的标识,IPC_CREAT, IPC_EXCL 的按位或

3、shmat  连接共享内存

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

成功返回共享存储段连接的实际地址,失败返回-1

shm_id:为shmget返回的共享内存标识符。

addr:指明共享内存段要连接到的地址(进程空间内部地址),通常指定为空指针,表示让系统来选择共享内存在进程地址空间中出现的地址。

shmflg:可以设置为两个标志位(通常设置为0)

SHM_RND( 表示第二个参数指定的地址应被向下靠拢到内存页面大小的整数倍)

SHM_RDONLY:是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式

4、shmdt 分离共享内存

int shmdt(const  void *shmaddr) ;

成功时返回0。失败时返回-1。

shmaddr:共享内存的起始地址

5、shmctl 控制共享内存

int  shmctl( int shmid , int cmd , struct shmid_ds *buf );

返回值: 成功:0 失败:-1

shm_id:为shmget返回的共享内存标识符。

cmd:控制命令

buf:一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定

其中cmd的取值如下

cmd描述
IPC_STAT得到共享内存的状态
IPC_SET改变共享内存的状态
IPC_RMID删除共享内存

 

其他关于ipc的命令

ipcs、ipcmk和ipcrm

 

共享内存通信示例程序

写端程序

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

int main()
{ 
    int count = 0;

    key_t  key=ftok(".","m");
    if(key < 0)
    { 
        perror("ftok error!!!\n");
        return -1;
    }

    int shmid = shmget(key,4096,IPC_CREAT|IPC_EXCL|0666);
    if(shmid < 0)
    { 
        perror("shmid error!!\n");
        return -2;
    }

    sleep(5);

    char *buf = shmat(shmid, NULL, 0);

    while(count<4096)
    { 
        buf[count] = 'A'+count%26;
        sleep(2);
        count++;
        buf[count] = '\0';
    }
    shmdt(buf);
    sleep(5);
    DestoryShm(shmid);
    return 0;
}

读端程序

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

int main()
{ 
    int count = 0;

    key_t  key=ftok(".","m");
    if(key < 0)
    { 
        perror("ftok error!!!\n");
        return -1;
    }

    int shmid = shmget(key,4096,IPC_CREAT);
    if(shmid < 0)
    { 
        perror("shmid error!!\n");
        return -2;
    }

    sleep(5);

    char* buf = shmat(shmid, NULL, 0);
    while(1)
    { 
        printf("%s\n", buf);
        sleep(2);
    }

    shmdt(buf);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值