Linux下IPC主题三----------------共享内存

来源:互联网 发布:java equals int 编辑:程序博客网 时间:2024/06/05 20:29

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以,共享内存本身并不提供。

共享内存为什么效率高:因为不像管道以及消息队列一样,读写时进行拷贝两次,而共享内存直接进行内存读写,不需要进行拷贝。

共享内存申请的空间内存-----------------堆栈之间。


先介绍一些函数

1shmget函数

函数原型:int shmget(key_t key, size_t size, int shmflg);  
函数参数:
第一个参数,与信号量的semget函数一样,程序需要提供一个参数key(非0整数),它有效地为共享内存段命名,shmget函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1.


不相关的进程可以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调用shmget函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget函数的返回值),只有shmget函数才直接使用信号量键,所有其他的信号量函数使用由semget函数返回的信号量标识符。


第二个参数,size以字节为单位指定需要共享的内存容量


第三个参数,shmflg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存


2 shmctl函数
函数原型:int shmctl(int shm_id, int command, struct shmid_ds *buf);  
函数参数:
第一个参数,shm_id是shmget函数返回的共享内存标识符。

第二个参数,command是要采取的操作,它可以取下面的三个值 :
    IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
    IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
    IPC_RMID:删除共享内存段,删除时第三个参数置为NULL。

第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。


3shmat函数

函数原型:void *shmat(int shm_id, const void *shm_addr, int shmflg);  

函数参数:

第一个参数,shm_id是由shmget函数返回的共享内存标识。
第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
第三个参数,shm_flg是一组标志位,通常为0。

函数返回值:
调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.


4shmdt函数

函数原型:int shmdt(const void *shmaddr);

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


共享内存的使用:

内存区域的操作:创建内存区域mshget  -> 虚拟内存映射物理地址mshat -> 解除映射 mshdt -> 删除共享内存msgctl


comm.h //头文件

#ifndef _COMM_H_#define _COMM_H_#include<stdio.h>#include<stdlib.h>#include<sys/ipc.h>#include<sys/shm.h>#include<sys/types.h>#define PATHNAME "."#define PROJ_ID 0x6666int shm_create(int size);int shm_get();int shm_destory(int shmid);#endif


comm.c //函数的具体实现

/*************************************************************************> File Name: client.c> Author: WenQiang> Mail: wenqiangw1208@gmail.com> Created Time: Wed 15 Mar 2017 04:54:13 PM PDT ************************************************************************/#include"comm.h"int main(){int shmid = shm_get();char *buf = shmat(shmid,NULL,0);sleep(10);int count = 0;while(count < 4096){printf("%s\n",buf);sleep(1);count++;}shmdt(buf);return 0;}


测试代码:server 创建共享内存,挂接虚拟地址,写入字符串 循环写入A-Z

 client 挂接虚拟地址,输出字符串

server.c

/*************************************************************************> File Name: server.c> Author: WenQiang> Mail: wenqiangw1208@gmail.com> Created Time: Wed 15 Mar 2017 04:54:13 PM PDT ************************************************************************/#include"comm.h"int main(){int shmid = shm_create(4096);sleep(1);char *buf = shmat(shmid,NULL,0);int count = 0;sleep(15);while(count < 4096){buf[count++] = 'A'+count%26;buf[count] = 0;sleep(1);}shmdt(buf);shm_destory(shmid);return 0;}

client.c

/*************************************************************************> File Name: client.c> Author: WenQiang> Mail: wenqiangw1208@gmail.com> Created Time: Wed 15 Mar 2017 04:54:13 PM PDT ************************************************************************/#include"comm.h"int main(){int shmid = shm_get();char *buf = shmat(shmid,NULL,0);sleep(10);int count = 0;while(count < 4096){printf("%s\n",buf);sleep(1);count++;}shmdt(buf);return 0;}

运行结果:




0 0