首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 关于linux线程堆栈的问题
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kornrock
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-08-09 11:32:39 楼主
    Linux线程有独立的堆栈吗,还是和其它线程共享父进程堆栈呢?
    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-18 17:42:571楼 得分:0
    共享父进程的堆栈。


    线程就是在运行的进程的子函数,子函数是共享main的堆栈的。

    只有进程才有自己的运行环境


    不知说的对不。^_^
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wlabing
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-18 18:50:212楼 得分:0
    linux下的线程应该都是共享进程的资源.
    你可以做一个测试嘛,设置一个变量,用malloc为它开辟内存并赋值,然后在main函数中创建一个线程并修改它的值,等到线程终止后,在main函数中再输出该变量的值,若该变量的值发生了变化说明就是共享堆栈,若没变那就是独立的.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 17:07:163楼 得分:0
    楼上正解,学习。^_^
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tb01412
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-22 10:11:274楼 得分:0
    linux下的线程应该都是共享进程的资源.
    你可以做一个测试嘛,设置一个变量,用malloc为它开辟内存并赋值,然后在main函数中创建一个线程并修改它的值,等到线程终止后,在main函数中再输出该变量的值,若该变量的值发生了变化说明就是共享堆栈,若没变那就是独立的.
    ===============================================
    以个人对LINUX系统的了解,这种方法不可取,为什么呢?以个人经验来推测一下:
    线程间资源是共享的,也就是说在主线程中malloc的空间,辅助线程访问时,内核实现就是采用了共享内存的方式,也就是对该内存页进行了一次共享计数加1的方式(具体实现是通过缺页中断处理例程中加上了共享计数),当辅助线程退出时,该页共享计数减1,所以在主线程中再次访问这个内存页时,其被修改的内存中的数值依然不会被恢复回去,这就是LINUX内存管理与进程管理机制所决定的,有兴趣的可以照这位兄弟的方法去实践一下,结果应该是我所说的
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 15:44:095楼 得分:0
    /* example.c*/
    #include <stdio.h>
    #include <pthread.h>
    void thread(char * k)
    {
    int i;
    char * ss;
    ss = k;

    //strcpy(ss,"xyz");
    /*for(i=0;i <3;i++)
    {
    //printf("This is a pthread.\n");
    //printf("in pthread s is %s\n",ss);
    (*ss)++;
    printf("now %d ss is %c\n",i,ss);
    ss++;
    printf("now %d ss 2 is %c\n",i,ss);

    }
    ss = k;
    */
    ss = (char *) calloc(sizeof(char),4);
    strcpy(ss,"abc");
    k = ss;
    printf("in pthread ss is %s\n",ss);
                    printf("This is a pthread.\n");
                    printf("in pthread k is %s\n",k);


    }

    int main(void)
    {
    pthread_t id;
    int i,ret;
    char * s;
    //s = (char *) calloc(sizeof(char),4);
    //strcpy(s,"abc");
    //s[4] = '\0'
    printf("in main s is %s \n",s);
    ret=pthread_create(&id,NULL,(void *) thread,s);
    if(ret!=0){
    printf ("Create pthread error!\n");
    exit (1);
    }
    //for(i=0;i <3;i++)
    printf("This is the main process.\n");
    pthread_join(id,NULL);
    printf("at the end s is %s \n",s);
    return (0);

    }


    写了个程序验证这个问题,但是遇到c语言问题,大家帮忙看看。


    这个的输出结果中如果注释掉k = ss;那么输出的k和main中的是一样的,要是不注释掉的话输出结果k是abc。

    请问我错在哪里?

    而通过main初始化一段内存通过s传过来是没问题的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wlabing
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-23 09:19:506楼 得分:0
    这是从 < <unix环境高级编程>>中摘出来的一段话,描述了线程共享进程的哪些内容.
    A thread consists of the information necessary to represent an execution context within a process. This includes a thread ID that identifies the thread within a process, a set of register values, a stack, a scheduling priority and policy, a signal mask, an errno variable (recall Section 1.7), and thread-specific data (Section 12.6). Everything within a process is sharable among the threads in a process, including the text of the executable program, the program's global and heap memory, the stacks, and the file descriptors.

    这是我自己写的测试代码
    /*thr_test1.c*/
    #include <sys/types.h>
    #include <pthread.h>
    #include <string.h>
    #include <malloc.h>

    void *thr_callback(void *arg)
    {
            strncpy(arg,"new value",20);
            return ((void *)0);
    }

    int main()
    {
            pthread_t tid;
            void *retval;
            char str1[21]; /*存放在栈中*/
            char *str2;

            str2=(char *)malloc(51); /*存放在堆中*/
            memset(str1,0,21);
            memset(str2,0,51);
            strncpy(str1,"Hello world!",20);
            strncpy(str2,"this is str2",50);
            printf("before modify: str1 is '%s'\n",str1);
            printf("before modify: str2 is '%s'\n",str2);
            if(pthread_create(&tid,NULL,thr_callback,str1)!=0)
            {
                    perror("pthread_create");
                    exit(1);
            }
            pthread_join(tid,&retval);
            printf("after modify: str1 is '%s'\n",str1);
            printf("return value of thread is %d \n",(int)retval);

            if(pthread_create(&tid,NULL,thr_callback,str2)!=0)
            {
                    perror("pthread_create");
                    exit(1);
            }
            pthread_join(tid,&retval);
            printf("after modify: str2 is '%s'\n",str2);
            printf("return value of thread is %d \n",(int)retval);
            exit(0);
    }

    pds@FSSR:~> gcc -o thr_test1 thr_test1.c -lpthread
    pds@FSSR:~> ./thr_test1
    before modify: str1 is 'Hello world!'
    before modify: str2 is 'this is str2'
    after modify: str1 is 'new value'
    return value of thread is 0
    after modify: str2 is 'new value'
    return value of thread is 0

    存放在堆栈中的变量str1和str2的值都发生了改变,也证明了书上所写的那样.
    由于线程共用进程的资源,所以编程时还要考虑线程同步问题.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-23 12:15:057楼 得分:0
    这个不能证明什么,你的栈和堆都在主函数中定义分配的。你传给线程的也是在主函数中已分配的内存。在线程结束,这些并不会被释放。要证明也要在线程中定义堆栈才是。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-23 12:16:578楼 得分:0
    这个是我写的去验证这个问题的程序,但是好像有错误,不知错在哪,大家帮忙看看。本人初学,有不到之处,请见谅。

    /* example.c*/
    #include <stdio.h>
    #include <pthread.h>
    void thread(char * k)
    {
    int i;
    char * ss;
    ss = k;

    ss = (char *) calloc(sizeof(char),4);
    strcpy(ss,"abc");
    k = ss;
    printf("in pthread ss is %s\n",ss);
                    printf("This is a pthread.\n");
                    printf("in pthread k is %s\n",k);


    }

    int main(void)
    {
    pthread_t id;
    int i,ret;
    char * s;

    printf("in main s is %s \n",s);
    ret=pthread_create(&id,NULL,(void *) thread,s);
    if(ret!=0){
    printf ("Create pthread error!\n");
    exit (1);
    }

    printf("This is the main process.\n");
    pthread_join(id,NULL);
    printf("at the end s is %s \n",s);
    return (0);

    }


    写了个程序验证这个问题,但是遇到c语言问题,大家帮忙看看。


    这个的输出结果中如果注释掉k = ss;那么输出的k和main中的是一样的,要是不注释掉的话输出结果k是abc。

    请问我错在哪里?

    而通过main初始化一段内存通过s传过来是没问题的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • pottichu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-23 13:08:569楼 得分:0
    heap 是共享的.
    stack 不共享.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-24 00:39:2110楼 得分:0
    我先去验证下再说。^_^
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-25 17:12:0311楼 得分:0
    #include <stdio.h>
    #include <pthread.h>


    typedef struct pthreadarg
    {
    int stack;
    char * heap;
    }ptharg;

    void thread1(ptharg *parg1)
    {
    int i;

    printf("This is a pthread1.\n");

                   
    parg1->stack = 3;
    parg1->heap = "def";               
    printf("stack in thread1 is %d\n",parg1->stack);
    printf(" heap in thread1 is %s\n",parg1->heap);


    }
    void thread2(ptharg * parg2)
    {
    int i;

    printf("This is a pthread2.\n");

    printf("stack in thread2 is %d\n",parg2->stack);
    printf(" heap in thread2 is %s\n",parg2->heap);
                   


    }

    int main(void)
    {
    pthread_t id1,id2;
    int i,ret1,ret2;

    ptharg parg1,parg2;

    parg1.stack = 1;
    //parg2.stack = 2;
    parg1.heap = (char *)malloc(4);
    //parg2.heap = parg1.heap;

    strcpy(parg1.heap,"ptm");


    ret1=pthread_create(&id1,NULL,(void *) thread1,&parg1);
    if(ret1!=0){
    printf ("Create pthread1 error!\n");
    exit (1);
    }

    ret2=pthread_create(&id2,NULL,(void *) thread2,&parg1);
    if(ret2!=0){
    printf ("Create pthread2 error!\n");
    exit (1);


    printf("This is the main process.\n");
    pthread_join(id1,NULL);
    printf("the pthread1 is end.\n");
    pthread_join(id2,NULL);
    printf("the pthread2 is end.\n"); 
    printf("stack in main is %d\n",parg1.stack);
    printf(" heap in main is %s\n",parg1.heap);
    return (0);

    }


    以上为验证程序,但是不注释掉

    //parg2.stack = 2;
    //parg2.heap = parg1.heap;

    把parg2付给线程2时得到的结果和注释掉都用parg1赋值时的结果不同

    注释掉时:
    This is a pthread1.
    stack in thread1 is 3
    heap in thread1 is def
    This is a pthread2.
    stack in thread2 is 3
    heap in thread2 is def
    This is the main process.
    the pthread1 is end.
    the pthread2 is end.
    stack in main is 3

    不注释掉时:
    This is a pthread1.
    stack in thread1 is 3
    heap in thread1 is def
    This is a pthread2.
    stack in thread2 is 2
    heap in thread2 is ptm
    This is the main process.
    the pthread1 is end.
    the pthread2 is end.
    stack in thread2 is 3
    heap in thread2 is ptm


    为什么是这样?高人解释下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • flyingship23
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-25 18:46:0712楼 得分:0
    每个线程有自己的独立栈空间
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fierygnu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 16

      3

    发表于:2008-08-26 08:46:5313楼 得分:0
    栈共享就乱了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wangchipop
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 09:30:3314楼 得分:0
    “每个线程都拥有一个独立的程序计数器,进程栈和一组进程寄存器。”这是从书上抄的原话。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tb01412
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-26 11:28:3315楼 得分:0
    为什么是这样?高人解释下
    ===================
    我晕,看来你C语言的功底不够,典型的指针问题,居然跟堆栈扯上关系,而且你也不明白LINUX内核进程与线程管理机制,看看我最上面关于LINUX内存管理的回复,仔细读读吧,现在跟你讲一下为什么出现这种情况:

    ptharg parg1,parg2;

    parg1.stack = 1;
    parg2.stack = 2;
    parg1.heap = (char *)malloc(4);
    parg2.heap = parg1.heap;
    strcpy(parg1.heap,"ptm");

    1.执行了这些语句之后,parg1.heap指向的在main中分配的malloc之后的返回地址,假定为0xC2000000,parg2.heap的值也为0xC2000000,且0xC2000000地址内的值为ptm
    2.执行了parg1->stack = 3;parg1->heap = "def";之后,parg1->heap指向的静态字符串"def"的地址,这个地址就变成了假定为0xC3000000,注意了,此时parg2.heap的值依然还是0xC2000000,如果你还是不明白为什么的话,回去补一下C语言基础,所以就出现了后面的打印的信息了。。。。。。。。
    3.如果你把线程1中的parg1->heap = "def"改成strcpy(parg1->heap,"def"),你再试一下,结果跟是否注释那两行语句没有任何差别。


    “每个线程都拥有一个独立的程序计数器,进程栈和一组进程寄存器。”这是从书上抄的原话。
    =============================================
    你只知其一不知其二,这一句话是没错,你理解出了差错,是有独立的栈,但栈所指向的物理内存是与辅助线程共享的,一个线程退出时,释放内存空间,由于所指向的物理页被共享,只会让共享计数减一,而不会直接被释放,等待所有线程都退出时,其物理内存页的共享计数为0,因此所有被占用的物理页被释放,内存写时复制技术与内存页共享计数是LINUX进程、线程管理的核心所在,也是实现全局变量在各个线程中共享的原理,LINUX中正是由于内核中实现线程调度,再结合内存管理原理,就这样造就了这种“怪胎”。。。。。。。。。

    各位有兴趣的去看看LINUX内核设计与实现这本书中关于clone函数的实现(也就是进程、线程管理那部分),就会明白了。。。。。。。。。


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • blackbillow
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 16:05:0316楼 得分:0
    More than just the global variables are shared. All threads within a process share the following:
    Process instructions
    Most data
    Open files (e.g., descriptors)
    Signal handlers and signal dispositions
    Current working directory
    User and group IDs

    But each thread has its own
    Thread ID
    Set of registers, including program counter and stack pointer
    Stack (for local variables and return addresses)
    errno
    Signal mask
    Priority
    ---------
    UNIX Network Programming Volume 1
    By W. Richard Stevens
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unbutun
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 18:01:4817楼 得分:0
    引用 15 楼 tb01412 的回复:
    为什么是这样?高人解释下
    ===================
    我晕,看来你C语言的功底不够,典型的指针问题,居然跟堆栈扯上关系,而且你也不明白LINUX内核进程与线程管理机制,看看我最上面关于LINUX内存管理的回复,仔细读读吧,现在跟你讲一下为什么出现这种情况:

    ptharg parg1,parg2;

    parg1.stack = 1;
    parg2.stack = 2;
    parg1.heap = (char *)malloc(4);
    parg2.heap = parg1.heap;
    strcpy(parg…



    哦,受教了。谢谢。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tb01412
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-27 12:02:5318楼 得分:0
    你只知其一不知其二,这一句话是没错,你理解出了差错,是有独立的栈,但栈所指向的物理内存是与辅助线程共享的,一个线程退出时,释放内存空间,由于所指向的物理页被共享,只会让共享计数减一,而不会直接被释放,等待所有线程都退出时,其物理内存页的共享计数为0,因此所有被占用的物理页被释放,内存写时复制技术与内存页共享计数是LINUX进程、线程管理的核心所在,也是实现全局变量在各个线程中共享的原理,LINUX中正是由于内核中实现线程调度,再结合内存管理原理,就这样造就了这种“怪胎”。。。。。。。。。
    =============================================================================================================

    顺便纠正一下,我这说的栈是指"堆",也就是用malloc分配的空间,不是指局部变量存放的栈(本人说法存在问题,主要是受LZ所说的堆栈的影响,LZ所说的堆栈是指堆),而书上说的是指局部变量存放的栈,本人太大意了,没看清楚就发表了评论,不好意思.............
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • realdragon2
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-27 21:09:1619楼 得分:0
    这是从 < <unix环境高级编程>>中摘出来的一段话,描述了线程共享进程的哪些内容.
    A thread consists of the information necessary to represent an execution context within a process. This includes a thread ID that identifies the thread within a process, a set of register values, a stack, a scheduling priority and policy, a signal mask, an errno variable (recall Section 1.7), and thread-specific data (Section 12.6). Everything within a process is sharable among the threads in a process, including the text of the executable program, the program's global and heap memory, the stacks, and the file descriptors.
    ~~~~~~~~~~~~ 六楼的, 这个共享的stack是什么东东?~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • realdragon2
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-27 21:12:5220楼 得分:0
    虽然可以经常连着说"堆栈段", 但到了内存管理的问题上,应该让自己谨记: 内存中进程映像的栈区和堆区是不同的.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • realdragon2
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-27 21:16:1521楼 得分:0
    =============================================
    你只知其一不知其二,这一句话是没错,你理解出了差错,是有独立的栈,但栈所指向的物理内存是与辅助线程共享的,一个线程退出时,释放内存空间,由于所指
                                                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~这句话该怎么理解?~ 如果实际指向的物理空间是共享的话,那么线程之间不会干仗吗?~ 如果是在多核机器上运行,而多个线程又可以真正同时并发的话.
    向的物理页被共享,只会让共享计数减一,而不会直接被释放,等待所有线程都退出时,其物理内存页的共享计数为0,因此所有被占用的物理页被释放,内存写时复制技术与内存页共享计数是LINUX进程、线程管理的核心所在,也是实现全局变量在各个线程中共享的原理,LINUX中正是由于内核中实现线程调度,再结合内存管理原理,就这样造就了这种“怪胎”。。。。。。。。。

    各位有兴趣的去看看LINUX内核设计与实现这本书中关于clone函数的实现(也就是进程、线程管理那部分),就会明白了。。。。。。。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tb01412
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-08-28 10:31:4222楼 得分:0
    这句话该怎么理解?~ 如果实际指向的物理空间是共享的话,那么线程之间不会干仗吗?~ 如果是在多核机器上运行,而多个线程又可以真正同时并发的话.
    ============================================
    你说到实质上去了,的确是要干仗的,所以线程之间想要访问同一个全局变量空间的时候,就存在一个同步或者互斥的问题啊,这是写多线程应用程序必须要注意的问题啊,比如一个全局数组,一个线程在访问此区域时,就要定要锁住,不让其它线程去访问。。。。。。。。
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved