linux 进程间通信-----共享内存(上)
来源:互联网 发布:宜兴俊知集团招聘2016 编辑:程序博客网 时间:2024/06/01 10:27
文章内容参考网络、unix网络编程-进程间通信(卷二)
共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
他允许两个无关的进程访问相同的逻辑内存。共享内存是在两个运行的程序之间传递数据的有效手段。尽管X/Open标准并没有要求,很可能绝大数的共享内存实现都是会将不同进程之间正在共享的内存安排在相同的物理内存中。
共享内存为在多个进程之间共享与传递数据提供一个有效的手段。因为他并没有提供同步的方法,所以通常我们需要使用其他的机制来同步对共享内存的访问。通常,我们也许会使用共享内存来提供对大块内存区的有效访问,并且传递少量的消息来同步对此内存的访问。
共享内存是由IPC为一个进程所创建并且出现在这个进程的地址空间中的一段特殊的地址序列。其他的进程可以将同样的共享内存段关联到他们自己的地址空间中。所有的进程都可以访问这段内存地址,就如同这段内存是由malloc所分配的。如果一个进程写入共享内存,这些改变立即就可以为访问相同共享内存的其他进程所见。
用于共享内存的函数如下:
#include<sys/shm.h>
void *shmat(intshm_id, const void *shm_addr, int shmflg);
int shmctl(intshm_id, int cmd, struct shmid_ds *buf);
int shmdt(constvoid *shm_addr);
int shmget(key_tkey, size_t size, int shmflg);
通常需要在包含shm.h文件之前包含sys/types.h与sys/ipc.h这两个头文件。
shmget
我们使用shmget函数创建共享内存:
int shmget(key_tkey, size_t size, int shmflg);
/* key: 标识符的规则
这个函数也提供了key,这可以有效的命名共享内存段,而且shmget函数会返回一个共享内存标识符,这个标识符可以用于后续的共享内存函数中。还有一个特殊的关键值,IPC_PRIVATE,这可以创建进程私有的共享内存。我们通常并不会使用这个值,而且与信号量相类似,我们会发现私有的共享内存在许多Linux系统上实际上并不是私有的。
第三个参数,shmflg,是由9个权限标记所组成的,这些标记的使用与用于创建文件的模型参数相同。IPC_CREAT定义了一个特殊位,必须与权限标记进行位或操作来创建一个新的共享内存段。设置IPC_CREAT标记并且传递一个已经存在的共享内存段并不是错误。如果不需要,IPC_CREAT只是简单的被忽略掉。
权限标记是十分有用的,因为这些权限标记可以允许创建共享内存所有者进程可以写入而其他用户所创建的进程只能读取的共享内存。我们可以应用这个特点通过将数据放入共享内存中,从而提供对于只读数据的有效访问,而不必担心数据被其他用户修改的风险。
如果共享内存成功创建,shmget会返回一个非负整数,共享内存标识符。如果失败,则会返回-1。
shmat
void *shmat(intshm_id, const void *shm_addr, int shmflg);
当我们第一次创建一个共享内存段时,他并不能为任何进程所访问。为了能够访问共享内存,我们必须将其与一个进程地址空间关联到一起。我们可以使用shmat函数来达到这一目的:
第三个参数,shmflg,是一个位标记集合。两个可能的值为SHM_RND与SHM_RDONLY。前者与shm_addr联合,控制将被关联的共享内存所在的地址;而后者使得关联的内存只读。通常很少需要来控制被关联的内存所在的地址;我们通常应允许系统来为我们选择一个地址,否则就会使得程序变得高度硬件相关。
共享内存将会依据所有者(共享内存的创建者),权限与当前进程的所有者而具有读或写权限。共享内存上的权限与文件上的权限相类似。
shmfgl &SHM_RDONLY为真的情况是这个规则的一个例外。此时共享内存并不可写,尽管权限已经允许了写访问。
shmdt
int shmdt(void *addr);
shmdt函数将共享内存与当前进程相分离。他传递一个指向由shmat所返回的地址的指针。如果成功,则会返回0;如果失败,则会返回-1。注意,分离共享内存并不会删除他;他只是使得内存对于当前进程不可用。
shmctl
共享内存的控制函数要比复杂的信号量控制函数简单得多:
int shmctl(intshm_id, int command, struct shmid_ds *buf);
/*shmid:共享存储段的id
* cmd:一些命令,有:IPC_STAT,IPC_RMID,SHM_LOCK,SHM_UNLOCK
*/shmid_ds结构至少具有下列成员:
struct shmid_ds {
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
}
第二个参数,command,是要执行的动作。他可以有三个值:
命令 描述
IPC_STAT 设置shmid_ds结构中的数据反射与共享内存相关联的值。
IPC_SET 如果进程有相应的权限,将与共享内存相关联的值设置为shmid_ds数据结构中所提供的值。
IPC_RMID 删除共享内存段。
第三个参数,buf,是一个指向包含共享内存模式与权限的结构的指针。
如果成功,则返回0,如果失败,则会返回-1。X/Open并没有说明如果我们尝试删除一个已经关联的共享内存时会发生什么。通常,一个已经关联但是被删除的共享内存通常会继续发挥作用,直到他与最后一个进程相分离。然而,因为这个行为并没有被规范,所以最好不要依赖于他。
下面通过一个具体的例子来说明,一个往共享内存中写,一个从共享内存中读取,但是写程序在使用参数IPC_PRIVATE,是系统自动分配的key,由系统产生的,并且没有任何标志独特性的key_t的值。那么读共享内存的程序怎么获取shm_id?
1.建立具有非常鲜明特征,独特的key值
2.通过信号量,消息队列或者管道(FIFO)传输这个shm_id
就第一种方法尝试write_ftok.c#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>#include <unistd.h>typedef struct{ char name; int age;}stu;int main(int argc,char **argv){ int shm_id,i; key_t key; char temp_char; stu*p_map; char *name="/dev/shm/myshm1"; key = ftok(name,0); printf("key=%d\n",key); if(key==-1) perror("ftok error"); shm_id=shmget(IPC_PRIVATE,4096,IPC_CREAT); printf("shm_id=%d\n",shm_id); if(shm_id==-1) {perror("shmget error");return;} p_map=(stu*)shmat(shm_id,NULL,0); temp_char='a'; for(i=0;i<10;i++) { (*(p_map+i)).name=temp_char; temp_char+=1; (*(p_map+i)).age=20+i; } if(shmdt(p_map)==-1) perror("detach error"); return 0;}
读取内存的程序read_ftok.c
#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>#include <unistd.h>typedef struct{ char name; int age;}stu;int main(int argc,char **argv){ int shm_id,i; key_t key; people *p_map; char *name="/dev/shm/myshm1"; key = ftok(name,0); if(key==-1) perror("ftok error"); shm_id=shmget(key,4096,IPC_CREAT); printf("shm_id=%d\n",shm_id); if(shm_id==-1) {perror("shmget error");return;} p_map=(stu*)shmat(shm_id,NULL,0); p_map=(stu*)shmat(393216,NULL,0); for(i=0;i<10;i++) { printf("name----------%c\n",(*(p_map+i)).name); printf("age-----------%d\n",(*(p_map+i)).age); } if(shmdt(p_map)==-1) perror("detach error"); return 0;}
- Linux 进程间通信:共享内存(上)
- Linux环境进程间通信 共享内存(上)
- Linux环境进程间通信之共享内存(上)
- Linux环境进程间通信--共享内存(上)
- Linux环境进程间通信: 共享内存(上)
- Linux环境进程间通信---共享内存(上)
- Linux环境进程间通信(五): 共享内存 (上)
- Linux进程间通信(五): 共享内存(上)
- linux 进程间通信-----共享内存(上)
- Linux进程间通信 —— 共享内存(上)
- Linux环境进程间通信:共享内存(上)
- Linux进程间通信-基于内存(共享内存)
- Linux环境进程间通信(五): 共享内存(上)(mmap)
- Linux环境进程间通信(五): 共享内存(上)(及mmap详解)
- Linux环境进程间通信(五): 共享内存(上)(转载)
- Linux环境进程间通信(五): 共享内存(上)
- Linux环境进程间通信(五): 共享内存(上)
- Linux环境进程间通信(五): 共享内存(上)
- 关于矩阵中的特征值和特征向量
- uva 10012
- ActionBar
- Android Watchdog(看门狗)分析
- Facebook数据仓库揭秘:RCFile高效存储结构
- linux 进程间通信-----共享内存(上)
- Windows 编程之服务-1
- 视图的作用
- Intel 64 and IA-32 架构的软件开发手册
- vim清空文件所有内容 cat 查找内容
- HDU-2092
- MFC播放声音文件
- kmp匹配算法
- 函数堆栈