Linux--进程间的通信之共享内存
来源:互联网 发布:java如何实现方法重载 编辑:程序博客网 时间:2024/06/06 10:53
概念
共享内存是进程间通信中最简单的方式之一。共享内存允许两个或多个进程访问同一块内存。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
优缺点
因为是所有进程共享的同一块内存,共享内存在各种进程间通信方式中具有最高的效率。但是共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问。
操作函数
创建共享内存
#include<sys/ipc.h>#include<sys/shm.h>int shmget(key_t key,size_t size,int shmflag);
返回值:成功返回共享存储区的shmid,失败返回-1。man
参数:
key:系统对此共享内存存储资源的唯一标识。可以通过ftok函数得到。
size:以字节为单位指定需要共享的内存容量。这个数一般为系统页长的整数倍(4K的整数倍).若申请的size不是页长的整数倍,系统也是按整数倍进行分配的,但是最后一页余下的部分不可用。如果创建一个新的资源,则必须指定size,且段的内容会被初始化为0。若引用一个已经存在的,则将size置为0。
shmflag:与消息队列的参数相同。有两个选项,IPC_CREAT和IPC_EXCL。使用的时候有两种情况:
1. IPC_CREAT和IPC_EXCL一起使用(IPC_CREAT|IPC_EXCL),表示申请创建一个新的IPC资源,若要申请的资源已经存在,则错误返回。若不存在,则创建。
2. IPC_CREAT单独使用,表示申请创建一个IPC资源,若要申请的IPC资源已经存在,则直接使用;若不存在,则创建新的。
一般我们还会在后面加上资源的默认权限(如0666)。
删除共享内存
#include<sys/ipc.h>#include<sys/shm.h>int shmctl(int shmid,int cmd,struct shmid_ds *buf);
返回值:成功返回0,失败返回-1。
参数:
shmid:shmget的返回值。
cmd:是要采取的操作,它可以取下面的三个值:
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
这里我们cmd取IPC_RMID。
buf:是一个结构体的指针,它指向共享内存模式和访问权限的结构。shmid_ds的结构如下:
struct shmid_ds{ struct ipc_perm shm_perm; size_t shm_segsz; pid_t shm_lpid; pid_t shm_cpid; shmatt_t shm_nattch;//shmatt_t定义为无符号整型,他至少和unsigned short一样大。 time_t shm_atime; time_t shm_dtime; time_t shm_ctime; ...}
把进程连接到共享内存
#include<sys/types.h>#include<sys/shm.h>void* shmat(int shmid,const void* shmaddr,int shmflag)
返回值:成功返回指向共享内存存储的指针,失败返回-1。
参数:
shmid:shmget函数的返回值。
shmaddr:shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
shmflag:shm_flg是一组标志位,通常为0。
把进程从共享内存中分离
#include<sys/types.h>#include<sys/shm.h>int shmdt(const void* shmaddr)
返回值:成功返回0,失败返回-1。
参数:
shmadd:是shmat函数返回的地址指针。
控制指令
系统同样为我们提供了查看共享内存IPC资源的指令:
ipcs -m
删除共享内存资源:
ipcrm -m [shmid]
代码实现
客户机-服务器模式
comm.h
ifndef __COMM__#define __COMM_#include<stdio.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>#define PATHNAME "."#define PROJID 0x666#define SIZE 4096int commMem(int flags);int creatMem();int getMem();int destroyMem(int shmid);#endif
comm.c:
#include"comm.h"int commMem(int flags){ key_t _k=ftok(PATHNAME,PROJID); if(_k<0) { perror("ftok"); return -1; } int shmid = shmget(_k,SIZE,flags); if(shmid<0) { perror("shmget"); return -2; } return shmid;}int creatMem(){ return commMem(IPC_CREAT | IPC_EXCL | 0666);}int getMem(){ return commMem(IPC_CREAT);}int destroyMem(int shmid){ int ret = shmctl(shmid,IPC_RMID,NULL); if(ret<0) { perror("destroy shmctl"); return -1; } return 0;}
client.c
#include"comm.h"int main(){ printf("client\n"); int shmid = getMem(); if(shmid < 0) { printf("getMem error!"); return -1; } printf("shmid: %d\n",shmid); sleep(5); char *addr=shmat(shmid,NULL,0); if(addr == NULL) { printf("addr is NULL!\n"); } printf("Debug add %p\n",addr); if(addr < 0) { perror("client shmat"); return -1; } int i = 0; while(i < SIZE-1) { addr[i] ='a' ; addr[i+1] = '\0'; sleep(1); i++; } int ret=shmdt(addr); printf("Debug shmdt\n"); if(ret < 0) { perror("client shmdt"); return -1; } return 0;}
server.c:
#include "comm.h"int main(){ printf("server\n"); int shmid = creatMem(); sleep(10); if(shmid < 0) { printf("creatMem error!\n"); return -1; } char *addr=shmat(shmid,NULL,0); if(addr < 0) { perror("shmat"); return -2; } while(1) { printf("# "); printf("%s",addr); printf(" #\n"); sleep(1); } int ret = shmdt(addr); if(ret < 0) { perror("shmdt"); return -1; } int ret_des=destroyMem(shmid); if(ret_des < 0) { printf("destroyMem error!\n"); return -1; } return 0;}
- linux进程间通信之共享内存
- linux进程间通信之共享内存
- Linux进程间通信之共享内存
- Linux进程间通信之共享内存
- linux进程间通信之共享内存
- linux进程间通信之共享内存
- Linux进程间通信之共享内存
- linux进程间通信之共享内存
- 【Linux】进程间通信之共享内存
- linux进程间通信之共享内存
- Linux进程间通信之共享内存
- Linux 进程间通信之共享内存
- Linux 进程间通信之共享内存
- Linux--进程间通信之共享内存
- Linux进程间通信之共享内存
- 进程间通信 之 共享内存(Linux)
- Linux进程间通信之共享内存
- linux进程间通信之共享内存
- 网易云音乐搜索引擎 python+whoosh---(2)搜索引擎
- css3设置边框阴影的属性
- C/C++中的switch/case陷阱
- 有一个姑娘,我无法忘记她
- Excel省市区三级联动
- Linux--进程间的通信之共享内存
- 你要是学习能力强,6年前年学as,3年前学cocos,去年学unity,月薪16k算低
- 《Inside C#》笔记(五) 方法
- 类加载机制ClassLoader
- android:installLocation = "auto" 的用法
- 安装maven过程
- Linux下tomcat的安装和配置
- 朋友,你还好吗?
- wget因为https和ssl的原因不能下载