LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1769|回复: 12

mmap如何为进程增加额外的地址空间?

[复制链接]
发表于 2008-8-11 19:22:30 | 显示全部楼层 |阅读模式
以前没有用过mmap, 查了网上很多资料,都是关于如何使用mmap来映射文件达到进程间共享内存的。
我想请问一下,如何使用mmap为进程增加额外的地址空间,我想用增加出来的地址空间作为将要启动的线程的栈的起始地址。我的程序中有4个线程比,经常出现再启动了一个线程mythread后,有些地址无法访问的问题,然后程序就core dump了,如果不启动mythread这个线程,程序就不会有问题。但是如果仅仅运行mythread线程,也不会有问题。 我想可能是下面的原因:


With a process, the amount of virtual address space is fixed. Since there is only one stack, its size usually isn't a problem. With threads, however, the same amount of virtual address space must be shared by all the thread stacks. You might have to reduce your default thread stack size if your application uses so many threads that the cumulative size of their stacks exceeds the available virtual address space. On the other hand, if your threads call functions that allocate large automatic variables or call functions many stack frames deep, you might need more than the default stack size.

故请教,麻烦大家提提建议,谢谢!
发表于 2008-8-12 09:33:26 | 显示全部楼层
你解决问题的思路蛮特别的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-8-12 09:53:18 | 显示全部楼层
楼上能否指点一下?
回复 支持 反对

使用道具 举报

发表于 2008-8-12 15:34:30 | 显示全部楼层
coredump不一定是栈的问题吧
你也没有细说你的几个thread是怎么工作的,各自用到多大的栈
再说C里栈一般不是以地址形式访问的吧
回复 支持 反对

使用道具 举报

发表于 2008-8-12 15:42:51 | 显示全部楼层
如果在linux用mmap方式增加空间,mmap大袋一个磁盘(flash)中的文件,影射后也占用系统内存空间,当内存不够的时候再换页出去。

这和直接在堆上开辟内存的性能开销是一样的。

按照future_god 的问题描述,我感觉似乎不是栈不能访问的问题。

另外楼主的英文描述是和来历?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-8-12 19:17:25 | 显示全部楼层
谢谢两位的关注。
英文的出处是
Advanced Programming in the UNIX® Environment: Second Edition
By W. Richard Stevens, Stephen A. Rago
Chapter 12. Thread Control
12.3. Thread Attributes
在讲述

  1. #include <pthread.h>

  2. int pthread_attr_getstack(const pthread_attr_t
  3. *restrict attr,
  4.                           void **restrict stackaddr,
  5.                           size_t *restrict stacksize);

  6. int pthread_attr_setstack(const pthread_attr_t *attr,
  7.                           void *stackaddr, size_t
  8. *stacksize);




  9. Both return: 0 if OK, error number on failure


复制代码

的时候提到的。

我用mmap的方法在PC上执行是OK的。
可以把线程启动起来,munmap也没有问题。
不过在我的板子(arm board)上就有问题了,线程可以跑完,不过在munmap的时候就有问题了,程序一样core dump.
所以放弃了这样的方法。于是将两部分分成独立的进程,使用消息队列进行通信。搞定,不会再core dump。 :Coffee:
PC上的线程栈大小默认2M
板子上栈大小默认2M-4096, 为什么是这个大小不清楚。
PTHREAD_STACK_MIN 是 16384。

我去linux下面把mmap请求空间,启动线程的程序贴上来。

rebooting...

:Coffee:
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-8-12 19:40:40 | 显示全部楼层

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/mman.h>
  5. #include <pthread.h>
  6. #include <limits.h>

  7. void thread_fun()
  8. {
  9.     int i = 0;
  10.     for(i=0; i < 5; i++)
  11.     {
  12.         printf("hello\n");
  13.         sleep(1);
  14.     }
  15. }


  16. int main(int argc, char *argv[])
  17. {
  18.     int ret = 0;
  19.     pthread_t tid;
  20.     pthread_attr_t attr;
  21.     void *stack_addr;
  22.     size_t stack_size = PTHREAD_STACK_MIN * 4;

  23.     ret = pthread_attr_init(&attr);
  24.     if(ret!=0)
  25.     {
  26.         printf("error line :%d, ret is %d.\n", __LINE__, ret);
  27.         return -1;
  28.     }

  29.     ret = pthread_attr_getstacksize(&attr, &stack_size);
  30.     if(ret!=0)
  31.     {
  32.         printf("error line :%d, ret is %d.\n", __LINE__, ret);
  33.         return -1;
  34.     }
  35.     printf("stack size is %d.\n", stack_size);

  36.     stack_addr = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0 );
  37.     if(stack_addr!=NULL)
  38.     {
  39.         printf("stack is %p.\n", stack_addr);
  40.     }
  41.     else if(stack_addr == MAP_FAILED)
  42.     {
  43.         printf("map failed.\n");
  44.         return -1;
  45.     }

  46.     ret = pthread_attr_setstack(&attr, stack_addr, stack_size);
  47.     if(ret!=0)
  48.     {
  49.         printf("error line :%d, ret is %d.\n", __LINE__, ret);
  50.         return -1;
  51.     }

  52.     ret = pthread_create(&tid, &attr, (void*) thread_fun, NULL);
  53.     if(ret!=0)
  54.     {
  55.         printf("error line :%d, ret is %d.\n", __LINE__, ret);
  56.         return -1;
  57.     }
  58.    

  59.     ret = pthread_join(tid, NULL);
  60.     if(ret!=0)
  61.     {
  62.         printf("error line :%d, ret is %d.\n", __LINE__, ret);
  63.         return -1;
  64.     }

  65.     ret = munmap(stack_addr, stack_size);
  66.     if(ret!=0)
  67.     {
  68.         printf("error line :%d, ret is %d.\n", __LINE__, ret);
  69.         return -1;
  70.     }
  71.     return 0;
  72. }
复制代码


不过这样的方法不知道常用不常用,本人见识比较浅,还请大家提提意见。
回复 支持 反对

使用道具 举报

发表于 2008-8-13 09:21:43 | 显示全部楼层
3G的虚拟地址空间还不够大吗?况且mmap出来的地址也在3G空间之内,有必要吗?
回复 支持 反对

使用道具 举报

发表于 2008-8-13 09:52:48 | 显示全部楼层
嗯,用的是匿名影射的方式。
回复 支持 反对

使用道具 举报

发表于 2008-8-13 09:55:44 | 显示全部楼层
但是看不出来这样对增加内存有何种的好处,用mmap映射一个文件却可以完成IPC的工作,但那就是不是匿名映射的方式了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表