最近项目上有这样一个需求:
主程序维持了一个链表,针对这个链表写了一个相应的dump函数,但是dump()只能在程序中的固定位置调用,也就是说如果需要在某一处查看内存中链表情况,就需要在源代码的相应地方加上dump()函数.
这样做,
第一不是很灵活,调试程序的时候,得修改源代码加上dump()函数,而且,久而久之源代码中调用dump()的地方会越来越多,而且有的已经用不上了,一一注释掉吧?很麻烦,而且以后说不定又想用呢.
第二,不能做到实时的查看.
所以,就想到了,可以做一个小工具来查看主程序内存中的链表情况.
这就用到了进程间通信,稍微读过APUE的人就会知道进程间通信有若干中方法,本文就共享内存这种方法来实现这个小工具.
简单介绍一下:
master.c是主程序,主程序共享了一块内存,这块内存中保存了10个people结构
typedef struct
{
char name[10];
int age;
}people;
/*
* =====================================================================================
*
* Filename: master.c
*
* Description:
*
* Version: 1.0
* Created: 04/08/2010 10:14:43 PM
* Revision: none
* Compiler: gcc
*
* Author: LeiuX (xulei), xulei@pact518.hit.edu.cn
* Company: HIT
*
* =====================================================================================
*/
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
typedef struct
{
char name[10];
int age;
}people;
int main()
{
int fd;
people* pmap = NULL;
char temp[2]={0,};
int i;
fd=open("/tmp/sharefile",O_CREAT|O_RDWR|O_TRUNC,00777);
lseek(fd,sizeof(people)*10,SEEK_SET);
write(fd,"",1);
pmap=(people*) mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
temp[0] = 'a';
for(i=0;i<10;i++)
{
temp[0] += 1;
memcpy((*(pmap+i)).name, temp,2);
(*(pmap+i)).age=20+i;
}
sleep(10);
printf("munmap\n");
munmap(pmap,sizeof(people)*10 );
printf("munmap ok\n" );
return 0;
}
|
tool.c就是所谓的内存查看工具程序,它读取主程序中的10个people结构.
/*
* =====================================================================================
*
* Filename: tool.c
*
* Description:
*
* Version: 1.0
* Created: 04/08/2010 10:27:26 PM
* Revision: none
* Compiler: gcc
*
* Author: LeiuX (xulei), xulei@pact518.hit.edu.cn
* Company: HIT
*
* =====================================================================================
*/
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct
{
char name[10];
int age;
}people;
int main()
{
int fd;
people *pmap;
int i;
fd=open("/tmp/sharefile",O_RDWR,00777);
pmap = (people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
for(i=0;i<10;i++)
{
printf( "name: %s age %d;\n",(*(pmap+i)).name, (*(pmap+i)).age );
}
munmap( pmap,sizeof(people)*10 );
return 0;
}
|
运行结果:
~$ gcc -g -o master master.c
~$ ./master
munmap
munmap ok
$ gcc -g -o tool tool.c
~$ ./tool
name: b age 20;
name: c age 21;
name: d age 22;
name: e age 23;
name: f age 24;
name: g age 25;
name: h age 26;
name: i age 27;
name: j age 28;
name: k age 29;
在主程序没结束前,每运行一次./tool,就可以得到这块共享内存的内容,可见共享内存这种方式可以基本达到前面所说的需求.
为什么说是基本达到呢,因为这种方法对这种需求(内存查看工具)来说,有几个缺陷:
第一,共享内存的大小需要事先定好,不能动态的改变.如果主程序中定义了10个people结构大小的共享内存,那么最多就可以存10个peopel的信息.如果需要扩充,那只能修改源代码了.
第二,共享内存的内容如需要变化,比较麻烦.如果仅更改或添加个人信息还行,但是如果要删除某个人的信息,就相对麻烦一些了,毕竟我们可以把共享内存看作一个数组,对数组中的数据进行删除是一件既麻烦又低效的事情.
第三,如果主程序里的people是通过链表存储的,而且每一个people结构都是动态申请的,那就用不上共享内存了.实在想用共享内存也行,可以把链表的内容dump一份到共享内存中.但这样就存储了两份,比较浪费空间.这种情况下,共享内存看起来就有点儿鸡肋了.换用其他进程间通信的方法吧,比如消息队列.
reference:
Linux环境进程间通信(五): 共享内存(上)
http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html用mmap()共享内存
阅读(2364) | 评论(0) | 转发(0) |