Chinaunix首页 | 论坛 | 博客
  • 博客访问: 259538
  • 博文数量: 74
  • 博客积分: 1470
  • 博客等级: 上尉
  • 技术积分: 793
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-25 21:01
文章分类

全部博文(74)

文章存档

2011年(1)

2010年(32)

2009年(32)

2008年(9)

我的朋友

分类: C/C++

2010-04-09 10:56:59


最近项目上有这样一个需求:
主程序维持了一个链表,针对这个链表写了一个相应的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()共享内存




阅读(2284) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~