djyos 发表于 2009-1-13 10:53:07

答疑:djyos每次事件都新开线程,不会低效吗?(兼谈内存管理)【恢复】

    连续几个网友在QQ上问了我一个共同的问题,就是:djyos为每次事件新开线程,开销会不会太大?

    我想,这个问题应该带有一定的共性,在此公开做答一下。

    同时,万分感谢认真阅读我的文档的网友,感谢您们抽出宝贵时间去了解、熟悉djyos,这是实际行动的支持,而不是仅仅对我5年坚持努力的感慨!

    首先,创建线程因为要调用malloc函数,需要花费有一定的开销,对实时系统来说是有影响,即使不是实时系统,每次事件都创建新线程也是不划算的。djyos对这种状况做了改进,方法是:

    1、紧急事件在登记事件类型的时候创建一个线程,但该线程并不投入运行(不启动),待事件发生并被调度器投入运行时,该线程立即分配给事件,当事件处理完毕以后,如果该事件使用的是该事件类型的最后一个线程,则线程不销毁,待再次发生事件时重复使用。而分配线程只需要一条赋值操作。

    2、无论是紧急事件还是普通事件,如果事件接踵发生,即前一条事件没处理完,后一天事件又发生,则前一条事件处理完毕后,线程并不销毁,而是把线程复位后直接转交给后续事件,重新启动线程后就可以处理后一条事件。转交事件也只需要一条赋值操作。

    3、如果是mark型事件(参见《都江堰操作系统与嵌入式系统设计》的第4.3.13节),则可以把接踵弹出的事件一次处理,无需新开线程。

    情况1和2,都需要在事件发生后,重启线程以处理事件,与传统的线程休眠等候事件发生的操作系统比,启动线程比直接的山下文切换来说,确实要慢一点点(多执行一次int_restore_asyn_signal调用),读者可以理解为:传统方法是汽车怠速等候,乘客上车以后立即开动车子,djyos的方法是汽车熄火等候,乘客上车后点火启动。而当今,CPU的运行速度很快,价格也低至几分钱每MIPS,人力资源成本却在上升,让CPU多干点,让程序员少干点吧!x86系列的CPU主频不断提高,你见到windows的运行速度有提高吗?

    4、djyos的内存管理算法也有巨大的改进,与传统用链表管理堆、使malloc函数调用执行时间不确定而且可能很长相比,djyos执行malloc的时间是确定而且速度很快。比如,在4G的寻址空间内,4k为一页,寻找一个空闲页,无论该空闲页的位置在哪里,无论存储器的当前使用情况如何,定位一个空闲页只需要:4次比较、4次乘法和4次加法。(详情参见《都江堰操作系统和嵌入式系统设计》di7章),然后再用稍长一些的时间来填充内存分配位图,即可完成内存分配。

    通常,堆内存管理被认为是非实时组件,但在djyos中,只要不出现无资源可分配的情况,djyos的堆内存管理是一个实时组件。

bluelucky 发表于 2009-1-15 11:14:04

动态申请内存可能会遇到申请失败,要求内存块的长度为2的整次幂,并且按容量对齐到堆内偏移量的边界,结合每个二进制数量级的容量单位使用一个树型阶级结构,这使得时间确定,然而加剧了内部碎片与外部碎片.比如,需要65字节的堆,就必须分配128字节。而且堆内偏移地址必须能被128整除,这样容易遇到申请失败

rainyss 发表于 2009-1-13 11:29:40

为什么要用这种方式来处理事件?好处是什么?几乎所有的操作系统里都是用回调过程&信号量来处理事件.

ggg12345 发表于 2010-2-10 20:20:16

学C语言这么久了,我还不是很明白系统如果控制内存的原理?

打个比方,一段执行代码放到了执行的空间或地址, 开始执行,执行过程在一些变量数组需要一些内存,如果不执行了,就要把内存释放出来。

我就很具体的来说,比如STM32,程序和内存是在同一编址空间。程序运行的时候自然就会用到内存,而用到哪个内存是不是编译器编译的时候就定义好的吧?那如何控制和释放呢

malloc这个函数的在汇编代码的原理是如何

djyos 发表于 2010-2-10 20:58:41

回复【1楼】rainyss
为什么要用这种方式来处理事件?好处是什么?几乎所有的操作系统里都是用回调过程&信号量来处理事件.
-----------------------------------------------------------------------

传统OS用回调和信号量来处理,是因为传统OS的调度对象是线程,而djyos的调度对象,则直接是事件。

回复【2楼】bluelucky
动态申请内存可能会遇到申请失败,要求内存块的长度为2的整次幂,并且按容量对齐到堆内偏移量的边界,结合每个二进制数量级的容量单位使用一个树型阶级结构,这使得时间确定,然而加剧了内部碎片与外部碎片.比如,需要65字节的堆,就必须分配128字节。而且堆内偏移地址必须能被128整除,这样容易遇到申请失败
-----------------------------------------------------------------------

djyos的内存管理是比较浪费内存,这是时间和空间的折中。

回复【3楼】ggg12345
学C语言这么久了,我还不是很明白系统如果控制内存的原理?
打个比方,一段执行代码放到了执行的空间或地址, 开始执行,执行过程在一些变量数组需要一些内存,如果不执行了,就要把内存释放出来。
我就很具体的来说,比如STM32,程序和内存是在同一编址空间。程序运行的时候自然就会用到内存,而用到哪个内存是不是编译器编译的时候就定义好的吧?那如何控制和释放呢
malloc这个函数的在汇编代码的原理是如何
-----------------------------------------------------------------------

这个问题比较深奥,我试着说一下吧,可能说不清楚。
对裸奔的情况来说,全局和静态变量是编译时分配好的。局部变量在栈区,执行时分配,分配方法是从SP的当前位置开始分配,分配数量是编译器定好了的。
对单进程的OS来说,情况稍微复杂些。全局和静态变量依然是编译时分配好的。不同的是栈,创建线程的时候,会分配一块内存作为该线程的栈,分配数量一般需要创建线程时指定。分配好后,SP指向该块内存,线程切换时SP也作为上下文的一部分保存。该线程的函数执行时需要局部变量,也是执行时分配的。
多进程的情况,每个进程都像一个单进程程序一样。

youkebing 发表于 2010-2-10 22:47:06

和线程池有什么区别?楼主能否解释一下

a___________a 发表于 2010-2-10 23:41:24

对裸奔的情况来说,全局和静态变量是编译时分配好的。局部变量在栈区,执行时分配,分配方法是从SP的当前位置开始分配,分配数量是编译器定好了的。
对单进程的OS来说,情况稍微复杂些。全局和静态变量依然是编译时分配好的。不同的是栈,创建线程的时候,会分配一块内存作为该线程的栈,分配数量一般需要创建线程时指定。分配好后,SP指向该块内存,线程切换时SP也作为上下文的一部分保存。该线程的函数执行时需要局部变量,也是执行时分配的。
多进程的情况,每个进程都像一个单进程程序一样。

-------------------------------------------------

单进程的OS :“不同的是栈,创建线程的时候,会分配一块内存作为该线程的栈,分配数量一般需要创建线程时指定。”
这个编译器是如何具体处理的,创建线程时起作用的核心函数或者机制是如何运作?我理解好像是比如C程序中这个线程定义1k内存要用,那编译器就会对应生成一段创建堆栈代码:执行到这段代码的时候就会创建1个1k深度的栈用于局部变量操作,对不对?但回收内存块又是如何实现的呢?是不是上下文切换时候不保存,这段地址就自然被其他线程使用或覆盖了?

{扯的更远一点:window里面有内存整理程序,好像可以实现扫描功能,发现没有用的内存就释放,好像叫内存池,这个原理是不是可以理解为针对内存建立一个类似文件系统管理的机制?比如通过索引记录内存的使用情况,那widows为啥不建立一个内置的定时扫描机制来提升自身的性能?}


堆栈的创建和使用看起来是很核心的一步,哎,没学过汇编原理,真是头痛。

我现在只记得51里面的进栈出栈的汇编代码了,对于arm,晕啊

djyos 发表于 2010-2-11 10:22:51

回复【5楼】youkebing
和线程池有什么区别?楼主能否解释一下
-----------------------------------------------------------------------

先回忆一下,VC是如何实现事件触发式编程的,原来,VC背着程序员,创建了一个或多个线程,该线程一直大部分时间处于休眠状态,一旦相应的事件发生(比如点击鼠标),就激活线程,处理该事件,从程序员眼里,只看到事件。VC并没有对内核做任何改动,内核仍然以线程为调度目标,对于内核来说,VC也是应用程序。

与VC相似,相对于内核来说,线程池管理器属于应用程序,内核并没有因此作出改变。线程池管理器针对某些可预见的、可并行的、大量发生的任务,预先创建一定数量的线程来满足需要,如果实际情况跟你设计线程池时预见的不一样的话,线程池可能不能提高性能,反而白白占用大量资源。因此,除仔细预计线程池中线程数外,又有了动态线程池、多个线程池的技术。总之,线程池时是用复杂的、应用程序级别的代码来弥补内核不足的技术。

而djyos中,内核的本质,天生就具备线程池技术能产生的效益,无需应用程序操心。它直接针对计算机所要处理的所有任务,而不是某些特定的任务,没有预测错误带来的风险问题,也没有消耗大量资源的问题。djyos天生具备线程池技术的一切优点,而克服了其缺点。你想一下,传统线程池技术可以用在像stm32这样的单片机中吗?djyos可以。


回复【6楼】a___________a
-----------------------------------------------------------------------

你的问题涉及面太广,而且很多是基础问题,建议你先系统学习下《计算机原理》之类的课程。
PS:你能同时提出这些问题,说明你有天赋,但基础不好,努力吧。

xizi 发表于 2010-2-13 02:51:12

高人。学习中。

xiaobendan 发表于 2010-2-13 07:41:24

看着晕啊!

fp007 发表于 2010-9-28 03:55:20

djyos设想了一个美丽的梦,但对系统速度,程序长度有要求,就不是最好的选择。在实时控制尤为突出
页: [1]
查看完整版本: 答疑:djyos每次事件都新开线程,不会低效吗?(兼谈内存管理)【恢复】