搜索
bottom↓
回复: 15

RTT中的线程初始化,创建的问题

[复制链接]

出0入0汤圆

发表于 2014-9-15 23:08:38 | 显示全部楼层 |阅读模式
本帖最后由 li.wen 于 2014-9-16 11:16 编辑

rt_thread_init() 针对线程做静态初始化,其中有两个参数是线程栈的设置:stack_start 和 stack_size

问题1:静态线程栈有啥用处呢?如果按说明上提到的,都是全局的或者编译时就分配好的,那么就和我们在一个子函数上定义一些局部变量或者全局变量一个概念
难道这块空间可以用来做线程内变量空间的动态分配?

问题2: 同问题1的道理, rt_thread_create() 在动态内存堆里面分配出线程栈空间,是否意味着在这个线程里rt_malloc等分配的空间会在这个栈空间里面?

盼大牛回答,先谢过了。

------------------------------------------ 修订 看了大家的回复,可能大家误解了,补充一下问题描述:

在RTT2.0中,STM CortexM3那个例子的Application.c的led thread建立的时候创建了一个512字节的stack(led_stack[512])。是采用rt_thread_init()来创建线程的。
    result = rt_thread_init(&led_thread,
                            "led",
                            led_thread_entry,
                            RT_NULL,
                            (rt_uint8_t*)&led_stack[0],
                            sizeof(led_stack),
                            20,
                            5);
    if (result == RT_EOK)
    {
        rt_thread_startup(&led_thread);
    }

现在,我在如下的线程中创建了一个 unsigned int count.
我就问:这个count占用的空间是在stack里面的,还是另外分配的,如果是另外分配的静态空间,那这个512字节的stack有啥用处呢?
即使我后面采用rt_malloc; 也是在总的系统heap里面分配啊,不关这个512字节啥事啊
static void led_thread_entry(void* parameter)
{
    unsigned int count=0;

    rt_hw_led_init();

    while (1)
    {
        rt_hw_led_toggle(1);
        rt_hw_led_toggle(2);
        rt_thread_delay( RT_TICK_PER_SECOND/4 );
    }
}

出0入0汤圆

发表于 2014-9-15 23:25:10 | 显示全部楼层
建议楼主找本编译原理的书看看

出0入0汤圆

 楼主| 发表于 2014-9-15 23:33:26 | 显示全部楼层
lixun00 发表于 2014-9-15 23:25
建议楼主找本编译原理的书看看

是不是和线程管理,切换,调度有关系?感觉不大可能啊,
RTT2.0的例子里面,点亮一个LED的静态线程就分配了512字节,感觉没必要啊
这块和编译原理有啥关系呢?

出0入0汤圆

发表于 2014-9-16 00:09:50 | 显示全部楼层
int的参数有stack_start,这个地址一般是个数组地址,由编译器分配空间。
create时只有size,其空间使用rt_malloc分配。
stack(栈)是用来放局部变量的。

两种方式建立的线程(包含create时),rt_malloc都是从heap(堆)中分配内存的。

出0入0汤圆

发表于 2014-9-16 03:09:18 来自手机 | 显示全部楼层
用Heap得小心,在有的编译器尚malloc过后定义的数组变量名字a和全局名字a是可以重名的。变量

出0入0汤圆

发表于 2014-9-16 08:43:43 | 显示全部楼层
li.wen 发表于 2014-9-15 23:33
是不是和线程管理,切换,调度有关系?感觉不大可能啊,
RTT2.0的例子里面,点亮一个LED的静态线程就分配 ...

这只是个例子,用来说明,实际工程不是这样的,

出0入0汤圆

发表于 2014-9-16 08:51:58 | 显示全部楼层
我自己的理解啊,
区别裸机程序和带操作系统的,
裸机下面如果没有外加一些机制,可以使用全部处在空闲的物理存储空间,

操作系统下面,内存这块是有管理员的,静态分配堆栈空间,这是在初始化的时候操作系统分配的,
就好比给你一块空间,让你在这里发挥,但是不能越过,越过的时候,操作系统会不愿意,
就像你说的:难道这块空间可以用来做线程内变量空间的动态分配。
这只是一部分,现成在切换的时候,要进行上下文切换,当前线程如果被切换了,要进行保存相关物理寄存器中的值,保存到哪,就是保存到堆栈中,

动态分配,在运行中,程序的堆栈空间伸缩性比较好,但是也增加了复杂度,如果线程想动态申请内存,操作系统得看是否还有的申请,才会批准,

两种方法各有利弊,如果朴素一点讲,静态比较快,动态还需要cpu做一些额外的工作,

只是个人的理解,欢迎批评,

出0入0汤圆

 楼主| 发表于 2014-9-16 11:02:14 | 显示全部楼层
可能大家误解了,我就想问一个问题
在RTT2.0中,STM CortexM3那个例子的Application.c的led thread建立的时候创建了一个512字节的stack(led_stack[512])。是采用rt_thread_init()来创建线程的。
    result = rt_thread_init(&led_thread,
                            "led",
                            led_thread_entry,
                            RT_NULL,
                            (rt_uint8_t*)&led_stack[0],
                            sizeof(led_stack),
                            20,
                            5);
    if (result == RT_EOK)
    {
        rt_thread_startup(&led_thread);
    }

现在,我在如下的线程中创建了一个 unsigned int count.
我就问:这个count占用的空间是在stack里面的,还是另外分配的,如果是另外分配的静态空间,那这个512字节的stack有啥用处呢?
static void led_thread_entry(void* parameter)
{
    unsigned int count=0;

    rt_hw_led_init();

    while (1)
    {
        rt_hw_led_toggle(1);
        rt_hw_led_toggle(2);
        rt_thread_delay( RT_TICK_PER_SECOND/4 );
    }
}

出0入0汤圆

发表于 2014-9-16 11:36:18 | 显示全部楼层
bli19 发表于 2014-9-16 03:09
用Heap得小心,在有的编译器尚malloc过后定义的数组变量名字a和全局名字a是可以重名的。变量 ...

愿闻其详

出0入0汤圆

 楼主| 发表于 2014-9-16 11:47:10 | 显示全部楼层
craigtao 发表于 2014-9-16 08:51
我自己的理解啊,
区别裸机程序和带操作系统的,
裸机下面如果没有外加一些机制,可以使用全部处在空闲的物 ...

可以这样理解对吧:如果线程内没有动态malloc的空间,栈就可以设置得非常小

出0入0汤圆

发表于 2014-9-16 11:52:05 | 显示全部楼层
li.wen 发表于 2014-9-16 11:47
可以这样理解对吧:如果线程内没有动态malloc的空间,栈就可以设置得非常小 ...

应该不是这样吧,主要是看任务

出0入0汤圆

发表于 2014-9-16 12:46:19 | 显示全部楼层
本帖最后由 aozima 于 2014-9-16 12:57 编辑

基础书要多看呀,另外,堆和栈这两个字不要写在一起呀,误导多少人。

ARM有16个寄存器,每个4字节,这样每个线程就至少要64字节呀。
像上面的count变量又要增加4字节。
那是不是68字节就够了?是的,可以这样简单理解。
但rt_thread_delay函数里面也要变量呀,以及编译器有时也自动保存一些,所以全要加上去呀。
一般编译器编译完成后会给出很个函数的最大栈深度,但有递归和函数指针时不可预测。

至于heap(堆),简单点可以理解为有个很大全局数组。
如   char heap[1024 * 1024 * 1024];

然后所有人调用malloc都是从这个数组里面分配的。

在RT-Thread中  finsh>>list_thread() 就可以看到线程到底用了多少。

出0入0汤圆

发表于 2014-9-16 13:10:47 | 显示全部楼层

:这用dev的mingw编译是可以通过的,而且不给警告。从语句上单独来看,定义了一个a的数组,为全局变量,又在main里malloc了a,于是在main里找不到数组a了,似乎是被覆盖了。
比如在main里输出a[1][1],会报错的, printf("%d\n",a[1][1]);会 subscripted value is neither array nor pointer,编译器全当这个数组不存在一样。
#include <stdio.h>
typedef char *  Charpointer;
void s(Charpointer temp);
char a[4][5] =
{
        11,12,13,14,15,
        21,22,23,24,25,
        31,32,33,34,35,
        41,42,43,44,45,
};
int main() {
   Charpointer a="sfs";
   a = (char *)malloc(sizeof(char));;
   
   s(a);
   printf("%d\n",*a);



   while(1);
   
}

void s(Charpointer temp) {

  *temp=99;


}

出0入0汤圆

发表于 2014-9-16 13:12:56 | 显示全部楼层
作用域呀,基础的基础呀。
像下面这种代码有些大项目得出现成百上千次,为嘛没出问题。
  1. int i;
  2. for(i=0;i<xx;i++)
复制代码

出0入0汤圆

发表于 2014-9-16 13:28:13 | 显示全部楼层
本帖最后由 bli19 于 2014-9-16 13:57 编辑
aozima 发表于 2014-9-16 13:12
作用域呀,基础的基础呀。
像下面这种代码有些大项目得出现成百上千次,为嘛没出问题。
...


所以说重名的话会比较麻烦。编译器不会理会这类重名。

---
不太理解这个编译器为何会允许这类重名?
能解释下为何上面的程序,不调用函数s(), 输出*a是-16(十进制)?
话说win32下查memory mapping很麻烦。。
加入继续malloc b,c,d,不做任何的赋值,会输出-40。这是一个默认的数值吗?
开头*a的-16似乎不是因为覆盖而产生的副作用。。

出0入0汤圆

 楼主| 发表于 2014-9-16 15:05:52 | 显示全部楼层
aozima 发表于 2014-9-16 12:46
基础书要多看呀,另外,堆和栈这两个字不要写在一起呀,误导多少人。

ARM有16个寄存器,每个4字节,这样每 ...

果真,把led_stack[512] 改成 led_stack[68]; 都不能正常工作了……。
实测至少led_stack[116]; 才能工作。STM32F105RCT6

想到以前的无操作系统写法:
while(1)
{
        thread1();
        thread2();
        thread3();
}
都没有栈空间这个说法的,定义静态局部变量啥都不用考虑。

回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-10 17:36

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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