日期:2014-05-16  浏览次数:20948 次

关于linux shmat 地址奇怪问题,请熟悉共享内存的高手指点一下
以前在as4,rh9上用shmat返回的地址每次都是一样的,因此共享内存里最前面定义大量的指针数组直接指向共享内存各个部分地址,
可是现在换centos 4,发现每次shmat取的地址都不一样了,导致数组指向的地址都无效了???,怎么解决

我试过将不一样的地址重新偏移是可以得到正确的结果,但这样太麻烦了,怎么样能保证shmat每次取的地址都一致呢,或者 有什么更好的方法

不知道大家明白我的意思没

------解决方案--------------------
貌似这两种方式都可以实现:
1、一楼的方式
2、二楼的方式,选择未用的堆地址空间,shmaddr 参数 PAGE 对齐或设置 SHM_RND

一般都用第一种方式;没人愿意采用第二种方式,可能会出现一些移植问题...

------解决方案--------------------
没有用过你说的系统。

C/C++ code


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>

typedef struct test
{
  char a[256];
  char *b;
  char c[256];
} test;


#define SHM_CREATE 1
#define SHM_LOAD 0
#define SHM_FILE "/var/test.shm"
#define SHM_SIZE 8000

char *
init_shm (const int flag, char *pathname, const unsigned long size, int shmid)
{
  char *ret = NULL;
  int shm_id = 0;
  key_t key = ftok (pathname, 'R');
  if (SHM_CREATE == flag)    // 新建 
    {
      shm_id = shmget (key, size, IPC_CREAT | IPC_EXCL | 0600);
      if (-1 == shm_id)
    {
      shm_id = shmget (key, size, 0);
      if (-1 == shm_id)
        {
          perror ("init_shm shmget create");
          return NULL;
        }
    }
      printf("shm_id = %d\n", shm_id);
      if ((ret = shmat (shm_id, (char *) 0xb7f17000, 0)) == (void *)-1) {
    perror("shmat");
    exit(1);
      }
      memset (ret, 0, size);
    }
  else
    {/*
      shm_id = shmget (key, size, 0);
      if (shm_id == -1)
    {
      perror ("init_shm shmget load");
      return NULL;
    }
     */
      ret = shmat (shmid, (char *)0xb7f17000, 0);
    }
  return ret;
}

int
main (int argc, char **argv)
{
  int shmid;
  char *arg = argv[1];

  if (argc != 3) {
    printf("Usage: %s cmd shmid\n", argv[0]);
    exit(1);
  }

  if (*arg == 'c')
    {
      system ("touch " SHM_FILE);    // create shm file 
      printf("SHM_FILE' size = %d\n", SHM_SIZE);
      test *t = (struct test *) init_shm (SHM_CREATE, SHM_FILE, SHM_SIZE, shmid);
      t->b = t->c;

      if (t)
    {
      printf("t->a size = %d\n", sizeof(t->a));
      //t->b =(char *) t + sizeof(t->a);
      printf ("addr = 0x%08x/0x%08x\n", (unsigned int)t->b, (unsigned int)t);
      strcpy (t->a, "AAAA");
      strcpy (t->b, "111");
      printf ("a=%s,b=%s\n", t->a, t->b);
    }
    }
  else if (*arg == 'l')
    {
      shmid = atoi(argv[2]);
      test *t = (struct test *) init_shm (SHM_LOAD, SHM_FILE, SHM_SIZE, shmid);
      printf ("addr = 0x%08x/0x%08x\n",(unsigned int)t->b, (unsigned int)t);
      //t->b = (char *)t + sizeof(struct test); // 重新定位b的位置 
      if (t)
    {
      printf ("a=%s,b=%s\n", t->a, t->b);
    }
    }
  return 0;
}