共享内存总结
来源:互联网 发布:我朝太祖知乎 编辑:程序博客网 时间:2024/06/03 19:16
Posix共享内存涉及以下两个步骤:
1、指定一个名字参数调用shm_open,以创建以一个新的共享内存区对象或打开一个已存在的共享内存区对象。
2、调用mmap把这个共享内存区映射到调用进程的地址空间。
头文件:
#include<sys/mman.h>
#include<sys/stat.h>
#include<fcntl.h>
int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name);
Link with -lrt(要注意连接这个库)
oflag参数是O_CRTEA|O_RDWR等标志;
mode参数指定权限位如果没有指定O_CREAT标志,那么该参数可以指定为0。(如果是创建的话权限要给够,平常是0644的权限,否则别的进程可能没有权限)。
一般创建的文件是自动放在/dev/shm/的目录下的。
新创建的文件大小一般为0,所以mmap函数调用文件标识符的时候会出错,这时候要用ftruncate()函数扩大文件
#include<unistd.h>
int ftruncate(int fd,off_t length); 成功返回0,出错返回-1
对于一个普通文件:如果该文件的大小大于length参数,额外的数据就会被丢掉。
对于一个共享内存区对象:把该对象的大小设置成length字节。
当打开一个已存在的共享内存对象时,我们可以调用fstat来获取有关该对象的信息。
#include<sys/types.h>
#include<sys/stat.h>
int fstat(int fd, struct stat *buf);
stat结构有12个或以上的成员, 但当fd指代一个共享内存区对象时,只有四个成员含有信息。
struct stat{
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
off_t st_size;
};
调用时不用定义这个结构体,直接实例化就行了,如:struct stat sta;
下面例子为一个往共享内存里写入内容,另一个读取。‘
读取端:
#include<stdio.h>
#include<unistd.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<string.h>
#include<sys/stat.h>
int main(int argc,char* argv[])
{
int fd = shm_open(argv[1],O_RDONLY,0);
void* buf = NULL;
if((buf = mmap(NULL,BUFSIZ,PROT_READ,MAP_SHARED,fd,0)) ==MAP_FAILED ){
perror("mmap error\n");
return 1;
}
sleep(1);
while(1){
printf("read:%s\n",buf);
sleep(3);
}
munmap(buf,BUFSIZ);
close(fd);
}
写入端:
int main(int argc,char* argv[])
{
int fd = shm_open(argv[1],O_CREAT|O_RDWR,0644);
if(fd == -1){
perror("shm_open error\n");
return 1;
}
ftruncate(fd,100);
void* buf = NULL;
if((buf = mmap(NULL,BUFSIZ,PROT_WRITE,MAP_SHARED,fd,0))== MAP_FAILED){
perror("mmap error\n");
return 1;
}
int i;
for(i=2;i<argc;i++){
strcpy(buf,argv[i]);
sleep(3);
}
munmap(buf,BUFSIZ);
close(fd);
}
System v共享内存
#include<sys/shm.h>
int shmget(key_t key,size_t size,int oflag); 返回:成功则为共享内存区对象,出错为-1
key 的值可以是ftok的返回值,也可以是IPC_PRIVATE.
ftok() 是非亲缘进程间
IPC_PRIVATE 是亲缘进程间的
size以字节为单位指定内存区的大小。当实际操作为创建一个新的共享内存区时,必须指定一个不为0的size值。如果实际操作为访问一个已存在的共享内存区,那么size应为0.
oflag是读写权限值的集合,还可以是IPC_CREAT或IPC_CREAT|IPC_EXCL
void *shmat(int shmid, const void*shmaddr, int flag); 返回:成功为映射区的起始地址,出错为-1
shmid是shmget返回的标识符。
如果shmaddr是一个空指针,那么系统替调用者选择地址。这是推荐的方法。
如果shmaddr是一个非空指针,那么返回地址取决于调用者是否给flag参数指定了SHM_RND值:
如果没有指定SHM_RND,那么相应的共享内存区附接到由shmaddr参数指定的地址;
如果指定了SHM_RND,那么相应的共享内存区附接到由shmaddr参数指定的地址向下舍入一个SHMLBA常值。LBA代表“底端边界地址”。
int shmdt(const void* shmaddr); 返回:成功为0,出错为-1
当一个进程终止时,他当前附接着的所有共享内存区都自动断接掉。本函数调用并不是删除所指定的共享内存区。
int shmctl(int shmid,int cmd, struct shmid_ds* buff); 返回:成功为0,错误为-1
cmd有三个命令:
1、IPC_RMID 从系统中删除由shmid标识的共享内存区并拆除它。
2、 IPC_SET 给所指定的共享内存区设置其shmid_ds结构的以下三个成员:shm_perm.uid、shm_perm.gid和shm_perm.mode,它们的值来自buff参数指向的结构中的相应成员。shm_ctime的值也用当前时间替换。
3、IPC_STAT (通过buff参数)向调用者返回所指定共享内存区当前的shmid_ds结构。
例子:下面例子为一个往共享内存里写入内容,另一个读取。
写入:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
int main(int argc,char* argv[]){
key_t key = ftok(argv[1],1);
if(-1 == key){
perror("ftok err");
return 1;
}
int shmid = shmget(key,0,O_RDWR);
if(-1 == shmid){
perror("shmget err");
return 1;
}
void* buf = shmat(shmid,NULL,0);
if((void*)-1 == buf){
perror("shmat err");
return 1;
}
strcpy(buf,"hello shmat\n");
shmdt(0);
return 0;
}
读取:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
int main(int argc,char* argv[]){
key_t key = ftok(argv[1],1);
if(-1 == key){
perror("ftok err");
return 1;
}
int shmid = shmget(key,0,O_RDONLY);
if(-1 == shmid){
perror("shmget err");
return 1;
}
void* buf = shmat(shmid,NULL,SHM_RDONLY);
printf("%s\n",buf);
shmdt(NULL);
printf("shmid:%d\n",shmid);
return 0;
}
- UNIX共享内存总结
- 共享内存实践总结
- linux 共享内存 总结
- UNIX共享内存总结
- 总结 共享内存
- UNIX共享内存总结
- UNIX共享内存总结
- CUDA总结:共享内存
- 共享内存总结
- unix 编程 共享内存总结
- Linux进程通信总结(三) --共享内存
- VC++6.0共享内存技术总结
- 共享内存总结以及实现代码
- linux基础总结(四)-------共享内存
- 【共享内存】共享内存
- 共享内存
- 共享内存
- 共享内存
- 利用JDBC连接池封装类自动根据mysql数据库生成对应的model类
- Oracle 12c多租户架构及优缺点
- webSql简单探究
- HDOJ5627 Clarke and MST (并查集)
- 判断是否为Ajax请求
- 共享内存总结
- 调用短信接口和页面延迟加载
- hadoop第一个例子wordcount学习
- 阿里云linux服务器挂载数据盘
- malloc原理和内存碎片
- VPN 路由泄露:外网IP和VPN IP互访
- Spring----AOP面向切面编程例子解析(附源码)
- Android用UncaughtExceptionHandler捕获全局异常
- 【MongoDB】简介及安装教程