<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Ruby Embedded</title>
    <description>随着嵌入式系统的配置越来越豪华，计算能力越来越强，C/C++已经不在是唯一的选择了。动态语言的高生产力和热部署特性对于嵌入式系统来说也具有很大的吸引力。嵌入式系统开发者们，来拥抱Ruby,Python,Lua等动态语言吧！</description>
    <link>http://rubyemb.group.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>Ruby'陷阱'之: '||=' 的真正展开式</title>
        <author>rubynroll</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rubynroll.javaeye.com">rubynroll</a>&nbsp;
          链接：<a href="http://rubyemb.group.javaeye.com/group/blog/208806" style="color:red;">http://rubyemb.group.javaeye.com/group/blog/208806</a>&nbsp;
          发表时间: 2008年06月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <em>前一段时间,我在这里<a href="http://rubynroll.javaeye.com/blog/192547" target="_blank">http://rubynroll.javaeye.com/blog/192547</a>展示了一个空格带来的'陷阱', 今天又见到另一个'陷阱'(http://dablog.rubypal.com/2008/3/25/a-short-circuit-edge-case by David).</em><br /><br />之所以为陷阱加引号, 是因为大部分情况下我们都没有机会掉进去 :)<br /><br /><strong>大多数Ruby教科书在解释 "a ||= b" 这个复合操作时,都说她等效于: "a = a || b", 实际上真的如此么?</strong><br /><br />让我们在irb里面来看看:<br /><br /><pre name="code" class="ruby">h = Hash.new(1)  # 生成一个新的Hash,缺省值为1
=> {}
h[:x]
=> 1    # h[:x]未定义,所以返回1
h[:x] ||= 2
=> 1
h
=> {}   # 啊? '陷阱'?
h[:x] = h[:x] || 2
=> 1
h
=> {:x=>1}  # 啊!</pre><br /><br />David提到,<strong>Matz在RubyConf 2007上的解释是"a ||= b"真实的等价应该是: "a or a = b", 但是David后来认为"a || a = b"应该更恰当些</strong>.<br /><br />果真的如此么? 不!<br /><br />一个简单的例子可以反驳, 如果a未定义,则:<br /><br /><pre name="code" class="ruby">irb(main):001:0> a || a = 2
NameError: undefined local variable or method `a' for main:Object
        from (irb):1
        from :0</pre><br /><br />所以, <strong>看来"a ||= b"正确的展开应该是: "a = b unless a"</strong><br /><br />对了么? 还是不对!<br /><br />"a ||= b"表达式最终返回的是a, 而"a = b unless a"在a非真时返回nil.<br /><br />所以, <span style="font-size: large">"a ||= b"的正确展开式应该为: "if a then a else a = b end"<br /></span><br /><br />想不到吧?<br /><br />＝＝＝ 补充 ＝＝＝<br /><br />鉴于此帖较长，且中间夹杂着不少因我的疏忽和错误造成的无谓争论，因此把最终的到的结论列在这里，免得看起来太累，或者有些人没有耐心看完而增加更多的无谓的争论。<br /><br />结论如下：<br />1) a ||= b 不等效于: a = a || b<br />2) 归纳起来,准确的展开式应该是:<br />if defined?(a) then (a || a = b) else a = b end <br /><br />特别感谢<strong>lllyq</strong>, 这个结论的credit应归于他／她。<br /><br />若大家发现有更好的展开形式，欢迎讨论。
          <br/>
          <span style="color:red;">
            <a href="http://rubyemb.group.javaeye.com/group/blog/208806#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 27 Jun 2008 20:14:52 +0800</pubDate>
        <link>http://rubyemb.group.javaeye.com/group/blog/208806</link>
        <guid>http://rubyemb.group.javaeye.com/group/blog/208806</guid>
      </item>
      <item>
        <title>动态模块加载和ELF Loader</title>
        <author>rubynroll</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rubynroll.javaeye.com">rubynroll</a>&nbsp;
          链接：<a href="http://rubyemb.group.javaeye.com/group/blog/202461" style="color:red;">http://rubyemb.group.javaeye.com/group/blog/202461</a>&nbsp;
          发表时间: 2008年06月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          很早很早以前就想在嵌入式系统上实现动态模块加载的功能了，期间走了些弯路，直到最近，才完整地在嵌入式系统上实现动态模块加载。<br /><br />=== 动态模块加载的好处 ===<br /><br />动态模块加载的好处很多，例如，当你升级一个系统的时候，可以只升级一个模块，而不必升级整个系统。你可以把不同的模块放在不同的介质上，并实施不同等级的保护，例如BIOS部分进行写保护。<br /><br />有些系统允许用户进行二次开发，这个时候几乎一定是需要动态加载功能的，因为你不希望用户需要链接整个系统才能够进行二次开发，而且你可能希望支持多个用户模块，彼此不相互依赖，彼此不干扰。<br /><br />=== Background ===<br /><br />一般来说，C的编译器编译出来的代码，由以下几个重要的部分：<br />.code: 代码段<br />.data: 有初值的数据段<br />.bss： 无初值的数据段<br /><br />通常还有.rodata，是只读的数据段，在嵌入式系统中经常可以合并到.code段中.<br /><br />注： .code, .data 和.bss这些段的命名不同的编译器可能会有不同。<br /><br />由于不同段在实际运行的时候可能会被加载到不同的介质，例如.code和.rodata可以放在NOR FLASH上而.data,.bss放入RAM中，或者要满足所谓的scatter loading，因此编译器会努力使段可以自由移动。<br /><br />但是要做到这一点，并不容易。<br /><br />在代码段中运行的指令，要获取数据段中的数据，方法有：<br />a) 通过当前PC值＋偏移量<br />b) 通过绝对地址<br />c) 通过中间寄存器，寄存器里面：<br />   c.1) 存放绝对地址<br />   c.2) 偏移量<br /><br />方法b通常只在CISC中存在，许多RISC机器由于指令长度受限制，并不存在方法b。<br /><br />因此，从这里可以看出，要做到各段可以自由移动,有几种方法：<br />1) 保留一个寄存器专门用于指示数据段的起始地址<br />2) 运行前修改指令<br />3) 保留一小块数据段和代码段的相对位置不变，此片数据段作为指向实际数据段的入口表， 运行前修改此表。<br /><br />方法1和方法3通常会结合起来一起用，动态链接库就是用了这种技术。<br />方发2是一种通用的方法，实际上连接器就是这样生成可执行文件的。<br /><br />=== ARM AIF ===<br /><br />ARM公司的编译器有一项特殊的功能，即可以产生一种可自我重定位的可执行文件，即AIF格式。<br />在AIF文件中，包含了一个AIF头和一小段由编译器产生的重定位代码。运行AIF格式的文件，只需要告诉它起始地址，这段重定位代码就会负责修改余下的一些必要的信息达到重定位目的。目前还没有充分的公开的文档解释AIF内部的详细工作机制。<br /><br />在我过去的一些项目中，AIF工作的很好，但是运行时外部无法获取AIF文件的更多信息，例如你无法去调用AIF映像中的某一个函数，因为你不知道它的地址。另外，AIF的执行映像中，.data必须紧跟在.code之后，对于想重定位到FLASH中执行的嵌入式系统就行不通了。<br /><br />=== ELF ===<br /><br />ELF文件是最常见的目标文件格式，它可能有很多扩展名，例如.o，.so,或者最终的可执行文件也是ELF。<br /><br />ELF有几种：<br />* 可重定位<br />* 可动态链接<br />* 可执行<br />* 可执行＋可重定位<br /><br />可执行的ELF如果没有可重定位信息，那就只能靠虚拟内存系统来支持它运行。但是对于许多嵌入式系统，有可能连MMU都不具备，因此我们只关心可重定位的ELF。（可动态链接ELF实际上也是可重定位的一种，附加很多额外信息）<br /><br />有关ELF的详细信息，请参阅：http://www.skyfree.org/linux/references/ELF_Format.pdf<br /><br />=== ELF Loader ===<br /><br />我花了不少时间寻找小型的ELF Loader实现，但是真正适合嵌入式系统的却不多。<br /><br />+Contiki OS:<br />在Contiki OS里面，有一个很有趣的ELF Loader实现，嗯，其实Contiki OS有很多有意思的东西 :)<br /><br />+ucLinux:<br />ucLinux也是一个很有意思的例子。由于ucLinux没有启用虚拟内存系统，因此它在加载可执行文件的时候，就要进行重定位。为了加速重定位和减小ELF文件的体积，ucLinux提供了特殊的工具链，在产生ELF之前进行部分的“预重定位”，最后ELF中只需要携带很小体积的重定位信息。<br /><br />+其它RTOS：<br />其它嵌入式OS，如VxWorks也实现了ELF Loader, eCos的ELF Loader看起来尚未完整。<br /><br />+Linux Kernel:<br />哦，差点忘了一个最重要的，Linux Kernel。<br /><br />Linux Kernel的模块是可以通过insmod动态地加入内核。虽然Linux的用户空间程序运行在虚拟内存中，整个内核的空间确只有一个。一些奉行micro kernel的人批评Linux的这种方式，但是一个单一空间的内核运行效率却是最高的。<br /><br />在2.6内核中，模块重定位工作不再由insmod来完成，而是由内核来做所有的重定位工作。实现代码在：kernel/module.c中。<br /><br />剥去那些处理特殊section的代码，Linux内核模块加载部分的代码其实是非常简单明了的，而且Linux支持数十种架构意味着你几乎不要担心架构移植的问题。<br /><br />=== 结论 ===<br /><br />在嵌入式系统中实现动态模块加载的技术是成熟的，可靠的，可以借鉴的开发源码的实现例子也有不少。一个参考数据： 我最近在一个嵌入式RTOS上实现的ELF Loader，运行在ARM7 CPU上，从NAND FLASH中加载一个400K左右的ELF，耗时大约0.5秒。<br /><br /><br />=== THE END ===
          <br/>
          <span style="color:red;">
            <a href="http://rubyemb.group.javaeye.com/group/blog/202461#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 12 Jun 2008 13:09:17 +0800</pubDate>
        <link>http://rubyemb.group.javaeye.com/group/blog/202461</link>
        <guid>http://rubyemb.group.javaeye.com/group/blog/202461</guid>
      </item>
      <item>
        <title>可以使用Python编程的嵌入式无线模块！</title>
        <author>rubynroll</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rubynroll.javaeye.com">rubynroll</a>&nbsp;
          链接：<a href="http://rubyemb.group.javaeye.com/group/blog/195372" style="color:red;">http://rubyemb.group.javaeye.com/group/blog/195372</a>&nbsp;
          发表时间: 2008年05月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Telit 是一家专业设计和生产无线模块产品的公司，值得注意的是，它几乎在所有的最新产品中集成了嵌入式Python解释器，这样使用者就可以使用Python脚本快速地开发应用，这些Python脚本可以保存在模块内部运行，而不用另外的MCU去和模块进行AT命令交互。<br /><br />想起以前在WaveCom的OpenAT平台上开发应用，那个叫郁闷....<br /><br />以下链接是Telit的一个4频GSM/GPRS模块的flyer：<br />http://www.telit.com/module/infopool/download.php?id=166
          <br/>
          <span style="color:red;">
            <a href="http://rubyemb.group.javaeye.com/group/blog/195372#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 21 May 2008 17:45:42 +0800</pubDate>
        <link>http://rubyemb.group.javaeye.com/group/blog/195372</link>
        <guid>http://rubyemb.group.javaeye.com/group/blog/195372</guid>
      </item>
  </channel>
</rss>