man 7 shm_overview

shm_overview - Overview of POSIX shared memory.

同样,SystemV实现的共享内存是旧的机制,但应用广泛;Posix标准提供了新的统一接口。

共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段)。如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映射到自己私有的地址空间中。如果一个进程更新了段中数据,那么其他进程立即回看到更新。由一个进程创建的段也可以由另一个进程读写。共享内存这一名称表达出是由多个进程分享对段及其保存的数据的访问权这一含义。共享内存很像内存映射文件。

Posix API:

shm_open, ftruncate, mmap, munmap, shm_unlink, close, fstat, fchown, fchmod.

System V API:

shmget,shmat,shmdt

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int shmget(key_t key, int size, int flags);

flags可以是一个或多个IPC_CREAT、IPC_EXCL和一组权限位(模式)按位“或”的结果。权限位以八进制表示。IPC_EXCL确保如果段已经存在,执行失败,而不是返回一个已经存在的段的标示符。IPC_CREAT指出如果没有和key关联的段就应该创建一个新段。key既可以是IPC_PRIVATE也可以是ftok函数返回的一个关键字。参数size指定段的大小,但它以PAGE_SIZE的值为界,这个值是某种处理器本身页的大小(intel是4KB)。shmget成功返回段标识符,出错返回-1。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h> #define BUFSZ 4096 int main(void)
{
int shmid; if((shmid = shmget(IPC_PRIVATE, BUFSZ, )) < )
{
perror("shmget");
exit(EXIT_FAILURE);
} printf("segment created: %d\n", shmid); system("ipcs -m\n"); exit(EXIT_SUCCESS);
}
~$./a.out
segment created: ------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 yuxi
0x00000000 yuxi
0x00000000 yuxi

shmget只是创建了共享内存区,进程要把它映射到自己的地址空间才能使用它,调用shmat完成。

#include <sys/types.h>

#include <sys/shm.h>

void *shmat(int shmid, const char *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

在函数shmat中,如果shmaddr为NULL,则内核会把段映射到调用进程的地址空间中它所选定的位置。假如shmaddr不为NULL,并且shmflg指定SHM_RND,则attach发生在附近的最小倍数SHMLBA。否则shmaddr必须是页对齐的地址。一般总是把shmaddr设置为0。flags可以为SHM_RDONLY,这意味着被附加的段是只读的。否则,被附加的段默认是可读写的。如果shmat调用成功,则返回附加了段的地址。否则,它返回-1并且设置errno变量。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h> int main(int argc, char *argv[])
{
int shmid;
char *shmbuf; if(argc != )
{
puts("USAGE: atshm <identifier>");
exit(EXIT_FAILURE);
}
shmid = atoi(argv[]); if((shmbuf = shmat(shmid, , )) < (char *))
{
perror("shmat");
exit(EXIT_FAILURE);
}
printf("segment attached at %p\n", shmbuf); system("ipcs -m"); if((shmdt(shmbuf)) < )
{
perror("shmdt");
exit(EXIT_FAILURE);
} puts("segment detached"); system("ipcs -m"); exit(EXIT_SUCCESS);
}
~$./a.out
segment attached at 0xb7709000 ------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 yuxi
0x00000000 yuxi
0x00000000 yuxi segment detached ------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 yuxi
0x00000000 yuxi
0x00000000 yuxi

使用举例:

include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <fcntl.h>
#include <ctype.h> #define BUFSZ 4096 int main(int argc, char **argv)
{
int shmid;
char *shmbuf;
int fd;
int i; if(argc != )
{
puts("USAGE: opshm <identifier>");
exit(EXIT_FAILURE);
}
shmid = atoi(argv[]); if((shmbuf = shmat(shmid, , )) < (char *))
{
perror("shmat");
exit(EXIT_FAILURE);
} if((shmbuf = malloc(sizeof(char) * BUFSZ)) < (char *))
{
perror("malloc");
exit(EXIT_FAILURE);
} for(i = ; i < BUFSZ; ++i)
{
shmbuf[i] = rand();
} fd = open("opshm.out", O_CREAT | O_WRONLY, );
write(fd, shmbuf, BUFSZ); free(shmbuf); exit(EXIT_SUCCESS);
}

创建shm举例

void *init_shm(void)
{
key_t key;
int shmid;
void *addr = NULL; key = ftok(SHM_PATH, SHM_PROJ);
if(key == -)
{
perror("ftok()");
return NULL;
} shmid = shmget(key, sizeof(struct shm_block), IPC_CREAT | );
if(shmid == -)
{
perror("shmget: ");
return NULL;
}
addr = shmat(shmid, , );
if (addr == (void *)-)
{
perror("shmat()");
return NULL;
} return addr;
}

通过命令ipcs -m可以查看共享内存信息。

注:大部分内容来自《GNU/LINUX编程指南》

最新文章

  1. Angularjs promise对象解析
  2. js实现图片无缝连接
  3. NOIP 2005 过河
  4. Azure IaaS for IT Pros Online Event 总结
  5. [wikioi]线段覆盖
  6. hadoop2.2编程:从default mapreduce program 来理解mapreduce
  7. 【5】JAVA---地址App小软件(DeletePanel.class)(表现层)
  8. Confluence简介
  9. jmeter通过BeanShell 脚本,实现对http请求参数的加密
  10. C#基本功之委托和事件
  11. pandas列合并为一行
  12. eclipse导入java工程
  13. [Ubuntu]pkg-config和ldconfig
  14. js学习之路2: JavaScript 变量
  15. (五)Cluster Health
  16. 20172328 2018-2019《Java软件结构与数据结构》第九周学习总结
  17. 20175212童皓桢 《Java程序设计》第一周学习
  18. 服务端线程模型-NIO服务模型
  19. 使用脚本与orm模型交互对数据库操作
  20. 「THUWC 2017」在美妙的数学王国中畅游

热门文章

  1. C#.net开发 List与DataTable相互转换 【转】
  2. Xshell连接mysql数据库乱码问题解决思路总结
  3. Hibernate关系映射(二) 基于外键的双向一对一
  4. Unity AssetServer小笔记
  5. Linux 添加开机启动项的三种方法
  6. CSS3图片折角效果
  7. 多校第九场Arithmetic Sequence题解
  8. ASDASASD
  9. django 查询集 API
  10. freeswitch 音 视频 支持的编码