如何查看tomcat内存分配shmget分配的内存地址

扫一扫体验手机阅读
进程间通信---共享内存(shmget)
(国防科大的仁兄)本人在自己理解的基础上一步一步去深入#include &sys/types.h&#include &sys/ipc.h&#include &sys/shm.h&#include &stdio.h&#include &stdlib.h&int main(){&&&&char *&&struct shmid_&&&&if((shmid=shmget(IPC_PRIVATE,))&0)&&&&{perror("shmget");exit(1);}&&else printf("created shared-memory: %d\n",shmid);&&system("ipcs -m");&&&&&&if((shmadd=shmat(shmid,0,0))&(char *)0)&&&&{ perror("shmat");exit(1); }&&else printf("attached shared-memory\n");&&system("ipcs -m");&&&&if((shmdt(shmadd))&0) //禁止本进程再使用该共享内存区&&&&{perror("shmdt");exit(1);}&&else printf("deleted shared-memory\n");&&system("ipcs -m");&&if(shmctl(shmid,IPC_RMID,&shmbuf)&0)&&&&{perror("shmctl");exit(1);}&&system("ipcs -m");&&&&return 0;}shmgetint shmget(key_t key, size_t size, int flag);key: 标识符的规则size:共享存储段的字节数flag:读写的权限返回值:成功返回共享存储的id,失败返回-1shmatvoid *shmat(int shmid, const void *addr, int flag);shmid:共享存储的idaddr:一般为0,表示连接到由内核选择的第一个可用地址上,否则,如果flag没有指定SHM_RND,则连接到addr所指定的地址上,如果flag为SHM_RND,则地址取整flag:如前所述,一般为0返回值:如果成功,返回共享存储段地址,出错返回-1shmdtint shmdt(void *addr);addr:共享存储段的地址,以前调用shmat时的返回值shmdt将使相关shmid_ds结构中的shm_nattch计数器值减1shmctlint shmctl(int shmid,int cmd,struct shmid_ds *buf)shmid:共享存储段的idcmd:一些命令,有:IPC_STAT,IPC_RMID,SHM_LOCK,SHM_UNLOCK程序说明:结合我一些函数的说明,这个程序应该就很容易懂了,另外需要补充的是,查看共享内存段的命令式:ipcs -m,删除共享内存段的命令是:ipcrm -m shmid,请注意,共享内存不会随着程序结束而自动消除,要么调用shmctl删除,要么自己用手敲命令去删除,否则永远留在系统中另看ipc_write.c#include &sys/ipc.h&#include &sys/shm.h&#include &sys/types.h&#include &unistd.h&typedef struct{&&&&&&&&&&}int main(int argc,char **argv){&&&& int shm_id,i;&&&& key_&&&& char temp_&&&& people *p_&&&& shm_id=shmget(IPC_PRIVATE,4096,IPC_CREAT);&&&& if(shm_id&0)&&&&&&&&{perror("shmget error");}&&&& p_map=(people*)shmat(shm_id,NULL,0);&&&& temp_char='a';&&&& for(i=0;i&10;i++)&&&& {&&&&&&&&(*(p_map+i)).name=temp_&&&&&&&&(*(p_map+i)).age=20+i;&&&& &&&&&&&&temp_char+=1;&&&& }&&&& if(shmdt(p_map)&0)&&&&perror("detach error");&&&& &&&& return 0;}ipc_read.c#include &sys/ipc.h&#include &sys/shm.h&#include &sys/types.h&#include &unistd.h&typedef struct{&&&&&&&&&&}int main(int argc,char **argv){&&&& int shm_id,i;&&&& key_&&&& people *p_&&&& struct shmid_&&&& shm_id=393216;//393216是ipcs -m查看到的shmid&&&& p_map=(people*)shmat(shm_id,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)&0)&& & & & &perror("shmdt error");&&&& if(shmctl(shm_id,IPC_RMID,&shmbuf)&0)&& & & & &perror("shmctl error");&&&& &&&&return 0;}ipc_write.c实现向共享内存里面写,ipc_read.c实现从共享内存里面读不过在ipc_write.c的shmget的第一个参数是IPC_PRIVATE,所以分配的key的值是由系统产生的,并且没有任何标志独特性的key_t的值。那么ipc_read.c是如何知道shm_id的呢?我这个是自己手工查ipcs -m得来的,那么编程中如何实现呢?1.建立具有非常鲜明特征,独特的key值2.通过信号量,消息队列或者管道(FIFO)传输这个shm_idshm_id也有人用,不过稍微麻烦一点,下面介绍用第一种方法shm_ftok_write.c#include &sys/ipc.h&#include &sys/shm.h&#include &sys/types.h&#include &unistd.h&typedef struct{&&&&&&&&&&}int main(int argc,char **argv){&&&& int shm_id,i;&&&& key_&&&& char temp_&&&& people *p_&&&& 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");}&&&& p_map=(people*)shmat(shm_id,NULL,0);&&&& temp_char='a';&&&& for(i=0;i&10;i++)&&&& {&&&&&&&&(*(p_map+i)).name=temp_&&&&&&&&temp_char+=1;&&&&&&&&(*(p_map+i)).age=20+i;&&&& }&&&& if(shmdt(p_map)==-1)&&&&perror("detach error");&&&& &&&& return 0;}ipc_ftok_read.c#include &sys/ipc.h&#include &sys/shm.h&#include &sys/types.h&#include &unistd.h&typedef struct{&&&&&&&&&&}int main(int argc,char **argv){&&&& int shm_id,i;&&&& key_&&&& people *p_&&&& 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");}&&&& p_map=(people*)shmat(shm_id,NULL,0);&&&& p_map=(people*)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;}这里用的是独特鲜明的key值执行程序之前,先创建"/dev/shm/myshm1"文件最好是写成自己的执行文件的目录,如"/home/nsl/myprogram/ipc_ftok_write"这样就不会存在文件不存在的情况了ftokkey_t ftok( char * fname, int id )frame:文件的全路径,要求文件存在且进程可访问id:第几个共享内存返回值:返回key值注明:系统V共享内存与mmap相比,就是系统V共享内存从来不把数据真正写到磁盘文件中去,而mmap机制在munmap的时候将数据写到磁盘文件发现原来系统V共享内存也需要文件的支撑当然,共享内存没有这么容易,还有大量的同步要做再补充点共享内存的派系知识:
UNIX进程间通信方式包括:管道、FIFO、信号。
System V进程间通信方式包括:System V消息队列、System V信号灯、System V共享内存。
POSIX进程间通信包括:posix消息队列、posix信号灯、posix共享内存。个人觉得,mmap是posix共享内存&& & & & shmget是System V共享内存
<span type="1" blog_id="199808" userid='
64篇文章,13W+人气,0粉丝
大数据时代的微服务之路
¥51.00435人订阅
<span type="1" blog_id="199808" userid='下面将讲解进程间通信的另一种方式,使用共享内存。
一、什么是共享内存
顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc()分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问,例如前面说到的信号量。有关信号量的更多内容,可以查阅另一篇文章:
二、共享内存的使得
与信号量一样,在Linux中也提供了一组函数接口用于使用共享内存,而且使用共享共存的接口还与信号量的非常相似,而且比使用信号量的接口来得简单。它们声明在头文件 sys/shm.h 中。
1、shmget()函数
该函数用来创建共享内存,它的原型为:
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、shmat()函数 & &-- at:attach
第一次创建完共享内存时,它还不能被任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。它的原型如下:
void *shmat(int shm_id, const void *shm_addr, int shmflg);
第一个参数,shm_id是由shmget()函数返回的共享内存标识。
第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
第三个参数,shm_flg是一组标志位,通常为0。
调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.
3、shmdt()函数 & &-- dt:detach
该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。它的原型如下:
int shmdt(const void *shmaddr);
参数shmaddr是shmat()函数返回的地址指针,调用成功时返回0,失败时返回-1.
4、shmctl()函数 & &-- ctl:control
与信号量的semctl()函数一样,用来控制共享内存,它的原型如下:
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:删除共享内存段
第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。
shmid_ds结构 至少包括以下成员:
struct shmid_ds
uid_t shm_perm.
uid_t shm_perm.
mode_t shm_perm.
三、使用共享内存进行进程间通信
说了这么多,又到了实战的时候了。下面就以两个不相关的进程来说明进程间如何通过共享内存来进行通信。其中一个文件shmread.c创建共享内存,并读取其中的信息,另一个文件shmwrite.c向共享内存中写入数据。为了方便操作和数据结构的统一,为这两个文件定义了相同的数据结构,定义在文件shmdata.c中。结构shared_use_st中的written作为一个可读或可写的标志,非0:表示可读,0:表示可写,text则是内存中的文件。
shmdata.h的源代码如下:
#ifndef _SHMDATA_H_HEADER
#define _SHMDATA_H_HEADER
#define TEXT_SZ 2048
struct shared_use_st
// 作为一个标志,非0:表示可读,0:表示可写
char text[TEXT_SZ]; // 记录写入 和 读取 的文本
源文件shmread.c的源代码如下:
#include &stddef.h&
#include &sys/shm.h&
#include &stdio.h&
#include &stdlib.h&
#include &unistd.h&
#include &string.h&
#include "shmdata.h"
int main(int argc, char **argv)
void *shm = NULL;
struct shared_use_st * // 指向shm
// 共享内存标识符
// 创建共享内存
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);
if (shmid == -1)
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
// 将共享内存连接到当前进程的地址空间
shm = shmat(shmid, 0, 0);
if (shm == (void *)-1)
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
printf("\nMemory attached at %X\n", (int)shm);
// 设置共享内存
shared = (struct shared_use_st*) // 注意:shm有点类似通过 malloc() 获取到的内存,所以这里需要做个 类型强制转换
shared-&written = 0;
while (1) // 读取共享内存中的数据
// 没有进程向内存写数据,有数据可读取
if (shared-&written == 1)
printf("You wrote: %s", shared-&text);
// 读取完数据,设置written使共享内存段可写
shared-&written = 0;
// 输入了 end,退出循环(程序)
if (strncmp(shared-&text, "end", 3) == 0)
else // 有其他进程在写数据,不能读取数据
// 把共享内存从当前进程中分离
if (shmdt(shm) == -1)
fprintf(stderr, "shmdt failed\n");
exit(EXIT_FAILURE);
// 删除共享内存
if (shmctl(shmid, IPC_RMID, 0) == -1)
fprintf(stderr, "shmctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
源文件shmwrite.c的源代码如下:
#include &unistd.h&
#include &stdlib.h&
#include &stdio.h&
#include &string.h&
#include &sys/shm.h&
#include "shmdata.h"
int main(int argc, char **argv)
void *shm = NULL;
struct shared_use_st *shared = NULL;
char buffer[BUFSIZ + 1]; // 用于保存输入的文本
// 创建共享内存
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);
if (shmid == -1)
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
// 将共享内存连接到当前的进程地址空间
shm = shmat(shmid, (void *)0, 0);
if (shm == (void *)-1)
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
printf("Memory attched at %X\n", (int)shm);
// 设置共享内存
shared = (struct shared_use_st *)
while (1) // 向共享内存中写数据
// 数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本
while (shared-&written == 1)
printf("Waiting...\n");
// 向共享内存中写入数据
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
strncpy(shared-&text, buffer, TEXT_SZ);
// 写完数据,设置written使共享内存段可读
shared-&written = 1;
// 输入了end,退出循环(程序)
if (strncmp(buffer, "end", 3) == 0)
// 把共享内存从当前进程中分离
if (shmdt(shm) == -1)
fprintf(stderr, "shmdt failed\n");
exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
再来看看运行的结果:
1、程序shmread创建共享内存,然后将它连接到自己的地址空间。在共享内存的开始处使用了一个结构struct_use_st。该结构中有个标志written,当共享内存中有其他进程向它写入数据时,共享内存中的written被设置为0,程序等待。当它不为0时,表示没有进程对共享内存写入数据,程序就从共享内存中读取数据并输出,然后重置设置共享内存中的written为0,即让其可被shmwrite进程写入数据。
2、程序shmwrite取得共享内存并连接到自己的地址空间中。检查共享内存中的written,是否为0,若不是,表示共享内存中的数据还没有被完,则等待其他进程读取完成,并提示用户等待。若共享内存的written为0,表示没有其他进程对共享内存进行读取,则提示用户输入文本,并再次设置共享内存中的written为1,表示写完成,其他进程可对共享内存进行读操作。
四、关于前面的例子的安全性讨论
这个程序是不安全的,当有多个程序同时向共享内存中读写数据时,问题就会出现。可能你会认为,可以改变一下written的使用方式,例如,只有当written为0时进程才可以向共享内存写入数据,而当一个进程只有在written不为0时才能对其进行读取,同时把written进行加1操作,读取完后进行减1操作。这就有点像文件锁中的读写锁的功能。咋看之下,它似乎能行得通。但是这都不是原子操作,所以这种做法是行不能的。试想当written为0时,如果有两个进程同时访问共享内存,它们就会发现written为0,于是两个进程都对其进行写操作,显然不行。当written为1时,有两个进程同时对共享内存进行读操作时也是如些,当这两个进程都读取完是,written就变成了-1.
要想让程序安全地执行,就要有一种进程同步的进制,保证在进入临界区的操作是原子操作。例如,可以使用前面所讲的信号量来进行进程的同步。因为信号量的操作都是原子性的。
五、使用共享内存的优缺点
1、优点:我们可以看到使用共享内存进行进程间的通信真的是非常方便,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定的父子关系。
2、缺点:共享内存没有提供同步的机制,这使得我们在使用共享内存进行进程间通信时,往往要借助其他的手段来进行进程间的同步工作。
《Linux高性能服务器编程》
《UNIX网络编程_卷2_进程间通信》
阅读(...) 评论()system V 共享内存
shmctl 用法解释
基本用法看man文档
1. shmget,shmflg指定IPC_EXCL位
如果key对应的共享内存已经存在,则返回-1,并且置errno为EEXIST错误;此时需要重新shmget一下并且shmflg不置IPC_EXCL位
否则如果key对应的共享内存不存在:
如果size大于已存在共享内存容量,则返回-1并置errno为EINVAL,此时需要删除旧共享内存并重新申请(申请时序先shmget 一下,参数size置1, 目的是获取旧共享内存的shmid,共shmctl删除使用)
如果size小于等于共享内存容量,分配成功(如果在这一步分配失败,则可通过error值确定原因)
2. shmctl。
shmctl删除共享内存时首先要获取共享内存id,方法见上。
a进程创建一块大小为8的共享内存,并进入死循环(目的是关联该共享内存,使下面的nattch不为0)
----- Shared Memory Segments --------
0x000214bc
c进程key与a进程相同,创建大小为1024共享内存,发现已存在共享内存(a进程创建)容量太小,则删除旧共享内存,并重新创建。
------ Shared Memory Segments --------
0x000214bc
可以看出a进程创建共享内存所用key值已经从0x000214bc 变成0x,并且status变成dest状态,这是由于c进程的shmctl在删除旧共享内存时,内核发现该共享内存的nattch为1(也就是有进程关联在该共享内存上,此处为a进程,因为死循环),内核就会置key为IPC_PRIVATE并置status为dest,这就保证该共享内存成为唯一的,dest状态会保证在关联进程(此处为a进程)终止时,该共享内存会被内核删除回收,而c进程创建的共享内存的key值依然是0x000214bc
3. key值为IPC_PRIVATE
IPC_PRIVATE会保证创建唯一的共享内存,多个进程都可以用IPC_PRIVATE创建自己特有的共享内存。
测试如下图
------ Shared Memory Segments --------
0x000214bc
没有更多推荐了,51CTO旗下网站
14.2.1 共享内存的系统调用
《精通UNIX下C语言编程与项目实践》本书共分为6个部分,详尽而细致地介绍了UNIX环境下的编程概念、文件系统设计、进程与线程设计、信号量处理、进程间通信处理、网络编程及数据库编程等多方面的内容。本节为大家介绍共享内存的系统调用。
作者:朱云翔/胡平来源:电子工业出版社| 15:28
14.2.1 共享内存的系统调用
共享内存的基本系统调用包括创建共享内存、映射共享内存和释放共享内存映射三种,分别由函数shmget、函数shmat和函数shmdt完成。
1. 共享内存的创建
在Unix中,可以使用函数shmget来创建或获取共享内存,它的原型如下:
#include& &sys/shm.h&int shmget (key_t key, size_t size, int shmflg);
函数shmget创建一个新的共享内存,或者访问一个已经存在的共享内存。参数key是共享内存的关键字。size指定了该共享内存的字节大小。参数shmflg的含义与消息队列函数msgget中参数msgflg的含义相类似。它的低9位决定了共享内存属主、属组和其它用户的访问权限,取值与表6-4的文件权限参数类似,但执行权限无意义。它的其它位指定了共享内存的创建方式,其取值与含义如表14-1所示:
表14-1 消息队列创建方式参数
与消息队列类似,当参数key的取值为IPC_PRIVATE时,将创建关键字为0的共享内存,Unix内核可以同时存在多个关键字为0的共享内存。
函数shmget调用成功时,返回共享内存的标识符,否则返回-1。
例1. 创建关键字为0x1234,访问权限为0666,占用空间10K的共享内存,如果已存在则返回其标识号。
shmid = shmget(0x4, 0666|IPC_CREAT);例2. 创建关键字为0x1234,访问权限为0666,占用空间10K的共享内存,如果已存在则报错。
shmid = shmget(0x4, 0666|IPC_CREAT|IPC_EXCL);
2. 共享内存的映射
与消息队列和信号量不同,共享内存在获取标识号后,仍需调用函数shmat将共享内存段映射到进程地址空间后才可以访问。函数shmat的原型如下:
#include& &sys/shm.h&void *shmat(int shmid, const void *shmaddr, int shmflg);
函数shmat将标识号为shmid共享内存映射到调用进程的地址空间中,映射的地址由参数shmaddr和shmflg共同确定,其规则为:
(1) 如果参数shmaddr取值为NULL,系统将自动确定共享内存链接到进程空间的首地址。
(2) 如果参数shmaddr取值不为NULL且参数shmflg没有指定SHM_RND标志,系统将使用地址shmaddr链接共享内存。
(3) 如果参数shmaddr取值不为NULL且参数shmflg指定了SHM_RND标志位,系统将地址shmaddr对齐后链接共享内存。其中选项SHM_RND的意思是取整对齐,常数SHMLBA代表了低边界地址的倍数,公式"shmaddr - (shmaddr % SHMLBA)"的含义是将地址shmaddr移动到低边界地址的整数倍上。
以上规则可归纳如表14-2所示:
表14-2 共享内存地址映射规则
【实践经验】在绝大多数情况下,我们指定参数shmaddr值为NULL,以便系统自动选择映射地址。
除了SHM_RND标志,参数shmflg还可以设置SHM_RDONLY标志位,此时共享内存将以只读的方式映射到内存地址中。
函数shmat调用成功时返回共享内存映射空间的起始地址,否则返回-1并置errno错误信息。
例1. 将创建关键字为0x1234,占用空间10K的共享内存,链接到进程中。
char *shmid = shmget(0x4, 0666|IPC_CREAT);pmat = shmat(shmid, 0, 0);
指针pmat指向共享内存映射空间的首地址。
3. 共享内存的释放
当进程不再需要共享内存时,可以使用函数shmdt释放共享内存映射,其原型如下:
#include& &sys/shm.h&int shmdt(const void *shmaddr);
函数shmdt释放进程在地址shmaddr处映射的共享内存,参数shmaddr必须为函数shmget的返回值。本函数调用成功时返回0,否则返回-1。
共享内存中有一个映射链接数,进程调用shmat成功时该链接数值自动增加1。调用函数shmdt并不能删除共享内存,它仅仅删除共享内存在进程中的一个链接,并将该共享内存映射数减1。
共享内存可以被进程映射多次,每次映射的首地址是不一样的。进程结束时,系统将自动检查进程中映射的共享内存并释放该映射。
【实践经验】虽然系统会自动释放共享内存在进程中的链接,但显式的调用shmdt释放内存映射是一个良好的编程习惯。
例1. 释放进程中地址paddr处的共享内存映射。
char *…………………………ret = shmdt(paddr);【责任编辑: TEL:(010)】&&&&&&
大家都在看猜你喜欢
热点热点头条头条热点
24H热文一周话题本月最赞
讲师:119874人学习过
讲师:218793人学习过
讲师:172108人学习过
精选博文论坛热帖下载排行
本书深入细致地介绍了用于构建网络的最重要的硬件设备――交换机、路由器、安全设备和无线设备,涵盖了原理、参数、分类、适用、规划、接口...
订阅51CTO邮刊博客分类:
共享内存(Shared Memory)
共享内存,简单的说就是被多个进程共享的内存。它在各种进程通信方法中是最快的,因为它是将信息直接映射到内存中,
省去了其它 IPC方法的中间步骤。
1.shmid_ds
共享内存也有一个给系统内存用来保存相关信息的机构,就是shmid_ds。
struct shmid_ds{
struct ipc_perm shm_
//operation
//size of segment
_kernel_time_t shm_
//last attach time
_kernel_time_t shm_
//last detach time
_kernel_time_t shm_
//last change time
_kernel_ipc_pid_t shm_
//pid of creator
_kernel_ipc_pid_t shm_lpid
//pid of last operator
unsigned short
//no. of current attaches
unsigned short
//compatibility
*shm_unused2; //ditto - used by DIPC
*shm_unused3; //unused
其中:
shm_perm&&& 成员储存了共享内存对象的存取权限及其它一些信息。
shm_segsz&& 成员定义了共享的内存大小(以字节为单位)。
shm_atime&& 成员保存了最近一次进程连接共享内存的时间。
shm_dtime&& 成员保存了最近一次进程断开与共享内存的连接的时间。
shm_ctime&& 成员保存了最近一次 shmid_ds 结构内容改变的时
shm_cpid&&&& 成员保存了创建共享内存的进程的 pid。
shm_lpid&&&&& 成员保存了最近一次连接共享内存的进程的 pid。
shm_nattch& 成员保存了与共享内存连接的进程数目。
剩下的三个成员被内核保留使用,这里就不介绍了。
有关的函数
1、sys_shmget()函数
使用shmget()函数来创建新的获取得已有的共享内存。
系统调用:shmget()
函数声明:int shmget(key_t key,int size,int shmflg);
&&& 返回值:shared memory segment identigier on success
&&&&&&&&&&&&&&&& -1 on error: errno =
shmget()函数的第一个参数key 是共享内存的关键字;第二个参数 size 是创建的共享内存的大小,以字节为单位。第三个参
数 shmflg 是控制函数行为的标志量,其取值的含义和作用和 msgget()及semget()函数的对应参数都是相同的.
int open_shm(key_t keyval, int segsize)
if(shmid=shmget(keyval, segsize,IPC_CREAT|0660))==-1)
return(-1);
return(shmid);
2、shmat()函数
当一个进程使用 shmget()函数得到了共享内存的标识符之后,就可以使用shmat()函数来将共享内存映射到进程自己的内
存空间内。
系统调用:shmat()
函数声明: int shmat(int shmid, char *shmaddr, int shmflg);
&&& 返回值: address at which segment was attached to the process, or
&&&&&&&&&&&&&&&& -1 on error: errno =
第一个参数是共享内存的标识符。
第二个参数 shmaddr 指定了共享内存映射的地址。因为这样必须要预先分配内存,十分不便,所以我们在使用时常常将这
个参数置零,这样系统会自动为映射分配一块未使用的内存。如果指定了地址,可以给第三个参数 shmflg 指定SHM_RND
标志来强迫将内存大小设定为页面的尺寸。
如果指定了 SHM_RDONLY参数,共享内存将被映射成只读。
映射成功后,函数返回指向映射内存的指针。
下面的这段代码演示了 shmat()函数的使用:
char *attach_segment( int shmid )
return(shmat(shmid, 0, 0));
}得到了映射内存的指针之后,我们就可以像读写普通内存一样对共享内存进行读写了。
3、shmctl()函数
和前两个 IPC 对象一样,共享内存也有一个直接对其进行操作的函数,就是 shmctl()函数。
系统调用: shmctl()
函数声明:int shmctl(int shmqid, int cmd, struct shmid_ds *buf);
&&& 返回值:0 on success
-1 on error: errno =
这个函数和 msgget()函数十分相似,用法也相同。它支持的操作有:
IPC_STAT&& 获得共享内存的信息。
IPC_SET&& 设定共享内存的信息。
IPC_RMID&& 删除共享内存。
需要说明的是,当执行 IPC_RMID 操作时,系统并不是立即将其删除,而只是将其标为待删,然后等待与其连接的进程断开连接。只有当所有的连接都断开以后系统才执行真正的删除操作。当然,如果执行 IPC_RMID 的时候没有任何的连接,删除将是立即的。
4、shmdt()函数
当一个进程不再需要某个共享内存的映射时,就应该使用 shmdt()函数断开映射。
系统调用: shmdt()
函数声明: int shmdt ( char *shmaddr );
&&& 返回值: -1 on error: errno = EINVAL (Invalid attach address passed)
shmdt()函数唯一的参数是共享内存映射的指针。
共享内存应用举例——shmtool,交互式的共享内存使用工具
shmtool.c
#include &sys/types.h&
#include &sys/ipc.h&
#include &sys/shm.h&
#define SEGSIZE 100
writeshm(int shmid, char *segptr, char *text)
strcpy(segptr, text);
printf("Done..\n");
readshm(int shmid, char *segptr)
printf("segptr: %s\n", segptr);
removeshm(int shmid)
shmctl(shmid, IPC_RMID, 0);
printf("Shared memory segment marked for deletion\n");
changemode(int shmid, char *mode)
struct shmid_
/*Get current values for internal data structure */
shmctl(shmid, IPC_STAT, &myshmds);
/* Display old permissions */
printf("Old permissions were:%o\n", myshmds.shm_perm.mode);
/*Convert and load the mode */
sscanf(mode, "%o", &myshmds.shm_perm.mode);
/* Update the mode */
shmctl(shmid, IPC_SET, &myshmds);
printf("New permissions are: %o", myshmds.shm_perm.mode);
fprintf(stderr, "shmtool - A utility for tinkering with shared memory\n");
fprintf(stderr, "\nUSAGE:
shmtool (w)rite &text&\n");
fprintf(stderr, "
(r)ead\n");
fprintf(stderr, "
(d)elete\n");
fprintf(stderr, "
(m)ode change &octal mode&\n");
main(int argc, char *argv[])
if(argc==1) usage();
/*Create unique key via call to ftok() */
key =ftok(".", 'S');
/*Open the shared memory segment -create if necessary */
if((shmid =shmget(key, SEGSIZE, IPC_CREAT|IPC_EXCL|0666))==-1)
printf("Shared memory segment exists - opening as client\n");
/* Segment probably already exists - try as client */
if((shmid = shmget(key, SEGSIZE, 0))==-1)
perror("shmget");
printf("Creating new shared memory segment\n");
/* Attach (map) the shared memory segment into the current process */
if((segptr= shmat(shmid,0,0))==-1)
perror("shmat");
switch(tolower(argv[1][0]))
writeshm(shmid, segptr, argv[2]);
readshm(shmid, segptr);
removeshm(shmid);
changemode(shmid, argv[2]);
default: usage();
/home/l/g/tomotoboy/ipc/shm &shmtool r
Shared memory segment exists - opening as client
segptr: test
/home/l/g/tomotoboy/ipc/shm &shmtool w "hello:this is a test"
Shared memory segment exists - opening as client
/home/l/g/tomotoboy/ipc/shm &shmtool r
Shared memory segment exists - opening as client
segptr: hello:this is a test
/home/l/g/tomotoboy/ipc/shm &shmtool d
Shared memory segment exists - opening as client
Shared memory segment marked for deletion
/home/l/g/tomotoboy/ipc/shm &shmtool r
Creating new shared memory segment
浏览: 125955 次
来自: 成都
简单明了,非常不错
jdk api文档里面的描述...
图不错,收藏之。
图中Thread.wait()改用Objec ...
因为你的$VALUE值是“sed.txt”,并不是这个文件的内 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 查看tomcat内存分配 的文章

 

随机推荐