pthread之线程堆栈

先来讲说线程内存相关的东西,主要有下面几条:

  1. 进程中的所有的线程共享相同的地址空间。
  2. 任何声明为static/extern 的变量或者堆变量可以被进程内所有的线程读写。
  3. 一个线程真正拥有的唯一私有储存是处理器寄存器。
  4. 线程栈可以通过暴露栈地址的方式与其它线程进行共享。

     有大数据量处理的应用中,有时我们有必要在栈空间分配一个大的 内存块或者要分配很多小的内存块,但是线程的栈空间的最大值在线程创建的时候就已经定下来 了,如果栈的大小超过个了个值,系统将访问未授权的内存块,毫无疑问,再来的肯定是一个段错误。可是没办法,你还是不得不分配这些内存,于是你开会为分配 一个整数值而动用malloc 这种超级耗时的操作。当然,在你的需求可以评估的情况下,你的需求 还是可以通过修改线程的栈空间的大小来改变的。

下面的我们用pthread_attr_getstacksizepthread_attr_setstacksize 的方法来查看和设置线程的栈空间。
注意:
     
下面的测试代码在我自己的机子上(ubuntu6.06,ubuntu6.10,redhat 9, gentoo) 通过了测试,但是很奇怪的是在我同事的机子上,无论是改变环境,还是想其它方法都不能正常的运行 。在网上查了一下,很多人也存在同样的问题,至今不知道为何。

linux
线程的实现方式决定了对进程的限制同样加在了线程身上:)所以,有问题,请参见<pthread 之 线程栈空间(2 )(进行栈)

直接看代码吧,只有一个C 文件(thread_attr.c)

#include <limits.h>
#include <pthread.h>
#include "errors.h"


//
线程体,在栈中分配一个大小为15M 的 空间,并进行读写
void *thread_routine (void *arg)
{
    printf ("The thread is here/n");
        //
栈大小为16M , 如果直接分配16M 的栈空间,会出现段错误 ,因为栈中还有其它的
        //
变量要放署
        char p[1024*1024*15];
        int i=1024*1024*15;

        //
确定内存分配的确成功了
        while(i--)
        {
               p[i] = 3;     
        }

        printf( "Get 15M Memory!!!/n" );
       
        //
分配更多的内存( 如 果分配1024*1020*512 的话就会出现段错误)
        char p2[ 1024 * 1020 + 256 ];
        memset( p2, 0, sizeof( char ) * ( 1024 * 1020 + 256 ) );
        printf( "Get More Memory!!!/n" );
    return NULL;
}

int main (int argc, char *argv[])
{
    pthread_t thread_id;
    pthread_attr_t thread_attr;
    size_t stack_size;
    int status;

    status = pthread_attr_init (&thread_attr);
    if (status != 0)
        err_abort (status, "Create attr");

    status = pthread_attr_setdetachstate (
        &thread_attr, PTHREAD_CREATE_DETACHED);

    if (status != 0)
        err_abort (status, "Set detach");
        //
通常出现的问题之一,下面的宏没有定义
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
        //
得到当前的线程栈大小
    status = pthread_attr_getstacksize (&thread_attr, &stack_size);
    if (status != 0)
        err_abort (status, "Get stack size");
    printf ("Default stack size is %u; minimum is %u/n",
        stack_size, PTHREAD_STACK_MIN);

        //
设置当前的线程的大小
    status = pthread_attr_setstacksize (
        &thread_attr, PTHREAD_STACK_MIN*1024);
    if (status != 0)
        err_abort (status, "Set stack size");
       
        //
得到当前的线程栈的大小
    status = pthread_attr_getstacksize (&thread_attr, &stack_size);
    if (status != 0)
        err_abort (status, "Get stack size");
    printf ("Default stack size is %u; minimum is %u/n",
        stack_size, PTHREAD_STACK_MIN);
#endif
        int i = 5;
        //
分配5 个具有上 面的属性的线程体
        while(i--)
        {
               status = pthread_create (
                       &thread_id, &thread_attr, thread_routine, NULL);
               if (status != 0)
                       err_abort (status, "Create thread");
        }

    getchar();
    printf ("Main exiting/n");
    pthread_exit (NULL);
    return 0;
}

看看执 行过程:
dongq@DongQ_Lap ~/workspace/test/pthread_attr $ make
cc -pthread -g -DDEBUG -lrt  -o thread_attr thread_attr.c
dongq@DongQ_Lap ~/workspace/test/pthread_attr $ ./thread_attr
Default stack size is 8388608; minimum is 16384         //
默认的栈大小为8M
Default stack size is 16777216; minimum is 16384      // 设置后的结果为16M
The thread is here
The thread is here
The thread is here
The thread is here
The thread is here
Get 15M Memory!!!
Get More Memory!!!
Get 15M Memory!!!
Get More Memory!!!
Get 15M Memory!!!
Get 15M Memory!!!
Get More Memory!!!
Get More Memory!!!
Get 15M Memory!!!
Get More Memory!!!

Main exitings

 

 

pthread 之线程堆栈 (2)-- 进程栈分析

 

前两天写了pthread 中 的线程栈的改变,觉得有必要将进程的栈空间的问题拿出来让大家看看:)

用下面的命令来看linux 下面的对系统的一些限制:
dongq@DongQ_Lap ~/workspace/test/pthread_attr $ ulimit -a

core file size           (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 16365
max locked memory       (kbytes, -l) 32
max memory size          (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8196

cpu time               (seconds, -t) unlimited
max user processes              (-u) 16365
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited



通过上面的命令, 我们可以清楚的看到一个进程在正常的情况下,最大的栈空间为8M
那么8M 我们够用吗?当你分配大量的static 或 者auto 变量的时候,一般都是放在栈空间的。如果分配一个大于8M 的 数组,会发生什么呢?
先来看看测试代码:

int main()
{

       int i = 1024 * 1024 * 8;
       char p[ i ];
       memset( p, 0, sizeof( char ) * i );


        while( i-- )
        {
               p[ i ] = i;
        }

        return 0;
}
上面的代码直接分配一个大小为8M 的 数组,编译后运行,出现段错误!!
很奇怪吗?不是说可以分配8M 吗?怎么不行?当然不行,因为在分配p 时,栈中已经放有其它的变量,最明显的就是int i;
这样子的话,栈中就没有足够的空间给变量p 分配,从而出现段错误。下面用gdb 进行调试:
DongQ_Lap pthread_attr # gdb process_stack

GNU gdb 6.5
(gdb) b main
Breakpoint 1 at 0x8048392: file process_stack.c, line 13.
(gdb) r > /home/dongq/tmp/gdb.txt
Starting program: /home/dongq/workspace/test/pthread_attr/process_stack > /home/dongq/tmp/gdb.txt
[Thread debugging using libthread_db enabled]
[New Thread -1209533760 (LWP 10947)]
[Switching to Thread -1209533760 (LWP 10947)]

Breakpoint 1, main () at process_stack.c:13
13      {
(gdb) s
15              int i = 1024 * 1024 * 8;
(gdb) s
16              char p[ i ];
(gdb) s
17              memset( p, 0, sizeof( char ) * i );
(gdb) p p
$1 = 0xbf6c3470 <Address 0xbf6c3470 out of bounds>

(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x080483d4 in main () at process_stack.c:17
17              memset( p, 0, sizeof( char ) * i );
(gdb) bt
#0  0x080483d4 in main () at process_stack.c:17
(gdb) quit

看到了 吗?char p[i] 这句执行后的结果是out of bounds!! 也就是内存没有分配成功。(在linux 程序运行的地址空间为0x8048000-0xbfffffff)
用下面的命令改变进程栈空间:
ulimit -s 16392
重新改变程序的栈空间, 很奇怪的是,有时普通用户可以操作,有时却出现:
dongq@DongQ_Lap ~/workspace/test/pthread_attr $ ulimit -s 16384
bash: ulimit: stack size: cannot modify limit: Operation not permitted

改用超级权限即可成功修改,改完之后,limit -a 得到的结果中应该有下面的一 行就表示成功了:

stack size (kbytes, -s) 16392

再运行上面的程序就可以正常的运行 了,当然,你还可以分配更大的数组:)

 

==================

相关链接:

POSIX thread (pthread) 多线程编程简介

pthread之线程堆栈

Linux下pthread线程库介绍

Pthread 介绍

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值