2 girls 1 hulu

Posted by dengwei


春媛小同学的葫芦和realjons的套娃。

Posted by ShoZu


加快Flex应用启动速度的5种方式

Posted by dengwei

Jun Heider在O’Reilly的InsideRIA站点上发表了一篇精彩的文章,该文章就如何加快Flex应用的启动速度提出了很多建议,以帮助用户减少看见讨厌的“Loading”对话框的出现时间。他深入探讨了问题的不同方面,并对每种技术的优势和劣势进行了评判。

从外部加载媒体(Media)
Heider提到了一个常用的Flex最佳实践——限制嵌入到应用/SWF文件中的媒体的数量,如图像、影片及mp3等资源都可以从外部的SWF文件加载。 Flex框架可以直接将图片、mp3及字体等资源编译到SWF中。当你想让最终用户获得全部资源时,这种方式确实能派上用场,但是这会导致你的应用长时间停留在“Loading”阶段。中国最大的RIA分享社区-与中国闪客一起成长和发展!

在嵌入式字体中限制字符集
Heider建议在嵌入式字体中限制字符集以降低SWF文件的总下载时间: 当你在Flex中嵌入一种字体时,你就会获得该字体的全部字符的支持。尽管这可能是你想要的,但你确信你需要全部字符么?例如,在一个只面向英文的应用中,你确信你真的想花时间下载中文字符数据么?
缓存框架

Heider回顾了Flex 3 support for runtime-shared-libraries (RSL)这篇文章:从Flex 3开始,你可以将Adobe签名的框架——RSLs缓存到 Player的中。这有两个好处。首先,缓存在 Player 中的签名的框架RSLs可由所有配置好的Flex应用共享。换句话说,如果某人的应用已经下载了500k的签名的框架RSL,并且该RSL仍旧 在 Player 中,那么你的应用就可以使用缓存下来的RSL。其次,即使某人清空了其浏览器缓存,对 Player 也没有任何影响。

考虑模块化
Heider谈到了将Flex应用划分成模块的好处:减少字体加载时间的另一种方式就是将你的Flex应用划分成模块。使用模块的一个好处在于当加载和卸载模块时你能完全操控它。
之所以要划分成模块的最后一个原因是他们更快,而且我能即时加载它们。换句话说,在启动时唯一需要加载的模块就是 Step1.swf模块。因此,在使用模块的情况下,最终用户节省了启动时间,但是当他从一个模块切换到另一个模块时却需要花更多时间,因为每个模块都需 要以JIT形式加载。在我的应用中,只有当用户首次在steps 1-5之间切换时需要花更多时间。

推迟实例化
Heider围绕着Flex组件的“creationPolicy”属性及何时实例化应用的不同部分给出了很多建议。如果你想减少从数据下载到用户真正可以使用的总时间,当务之急就是推迟实例化。这项技术背后的理念就是直到应用真正使用的时候才在内存中创建对象。尽管推迟实例化技术会在应用的整个使用过程中导致少许——通常不那么明显——的延迟,但与长时间的启动延迟相比,它还是可接受的。推迟实例化的另一个好处在于内存使用的优化。 Heider还谈到了一个“实验性”的条款——“使用流”,这是他在讨论Dirk Eismann的帖子(Building monolithic Flex SWFs that still startup quickly.”)时谈及的。Eismann提出一项技术以利用 Player中的多个frames以在部分应用中达到流的目的。查看所有的帖子以更多地了解该技术及关于加快Flex启动速度的建议。中国最大的RIA分享社区-与中国闪客一起成长和发展!)

原文出处:http://www.infoq.com/cn/news/2008/05/flex-startup-time


google背后的分布式架构

Posted by dengwei

  Google是与众不同的。它的独特不仅仅表现于革新的思维和充满创意的应用 (比如那个大堂里的地球模型),更在于其有别常规的IT策略……

  加利福尼亚州山景城(Mountain View)Google公司(Google,下称Google)总部有一个43号大楼,该建筑的中央大屏幕上显示着一个与Google地球(Google Earth)相仿的世界地图,一个转动的地球上不停地闪动着五颜六色的光点,恍如罗马宫廷的千万烛灯,每一次闪动标志着地球的这个角落一名Google用 户发起了一次新的搜索。

  这同时意味着Google又一次满足了人们对未知信息的好奇与渴望。

  Google是与众不同的。它的独特不仅仅表现于革新的思维和充满创意的应用 (比如那个大堂里的地球模型),更在于其有别常规的IT策略。从人们的常理来看,简单的硬件商品和免费软件是无法构建出一个帝国的,但是Google做到 了。在性能调整后,Google把它们变成一个无可比拟的分布式计算平台,该平台能够支持大规模的搜索和不断涌现的新兴应用。我们原本认为这些应用都是个 人消费级别的,但是Google改变了这一切。现在商业世界也在使用它们,这就令这家搜索公司显得那么与众不同。

  GoogleWeb 服务背后的IT架构对无数使用搜索引擎的用户来说也许并不是非常重要,但它是Google几百位致力于把全球信息组织起来,实现“随处可达,随时可用”目 标的工程师们的最核心工作。这就需要一个在覆盖范围和野心上都与Google的商业愿景完全相符的IT蓝图作为支撑。

  Google 的经理们一直对公司的IT策略话题保持沉默,他们厌恶谈及特定的厂商或者产品,当被问到他们的服务器和数据中心时,他们总是闭口不谈。但与几位 Google的IT领导一起呆了一天后,我们最终得以揭示该公司的IT是如何运作的,那可不仅仅是一个运行在无数服务器集群上的、表面看来非常简单的搜索 引擎。在其简单的外表下,蕴涵着许多内部研发软件、定制硬件、人工智能,以及对性能的执着追求和打破常规的人力管理模式。

  IT理念方面,Google对同行有一条建议:尽量避免那些人人都在使用的系统和软件,以自己的方式做事会更有独特的竞争优势。

  “企业文化决定了你的做事方式。”道格拉斯”美林(Douglas Merrill),这位Google工程副总裁和事实上的首席信息官(CIO) 指出,“到了我们这样的发展阶段,企业观念和文化非常与众不同,这也反过来鞭策我们必须要采用与众不同的方式来运行那些他人看来很常规的系统。”
  Google 最大的IT优势在于它能建造出既富于性价比(并非廉价)又能承受极高负载的高性能系统。因此IT顾问史蒂芬”阿诺德(Stephen Arnold)指出,Google与竞争对手,如亚马逊网站(Amazon)、电子港湾公司(eBay)、微软公司(Microsoft,下称微软)和雅 虎公司 (Yahoo,下称雅虎)等公司相比,具有更大的成本优势。Google程序员的效率比其他公司同行们高出50%~100%,原因是Google已 经开发出了一整套专用于支持大规模并行系统编程的定制软件库。据他估算,其他竞争公司可能要花上四倍的时间才能获得同等的效果。

  打造服务器

  Google 究竟是怎样做到这点的呢?其中一个手段,美林认为,“是因为我们自己动手打造硬件。”Google并不制造计算机系统,但它根据自己的参数定制硬件,然后 像MTV的节目“靓车打造”(Pimp My Ride)那样自己安装和调整硬件系统。开源程序经理克里斯”迪博纳(Chris DiBona)评论道:“我们很善于购买商业服务器,并且改造他们为我们所用,最后把性能压榨和发挥到极致,以致有时候他们热得像要融化了似的。”

  这种亲手打造的方式,来源于Google从车库诞生时与生俱来的节俭风格,更与Google那超大型的系统规模息息相关,良好的习惯一直延续至 今。据说 Google在65个数据中心拥有20万~45万台服务器—这个数目会有偏差(取决于你如何定义服务器和由谁来做这项统计)。但是,不变的是持续上升的趋势。

  Google不会去讨论这些资产,因为它认为保密也是一种竞争优势。事实上,Google之所以喜欢开源软件也是因为它的私密性。“如果我们购 买了软件许可或代码许可,人们只要对号入座,就可以猜出Google的IT基础架构。”迪博纳分析说, “使用开源软件,就使我们多了一条把握自己命运的途径。”

  Google喜欢规模化的服务器运行方式。当有成百上千台机器时,定制服务器的优势也会成倍增加,效果也会更趋明显。Google正在俄勒冈州 哥伦比亚河边的达勒斯市建造一个占地30亩的数据中心,在那儿它可以获得运算和降温需要的低价水力电力能源(参见边栏《Google数据中心自有一套》)。

  Google以“单元”(Cell)的形式组织这些运行 操作系统的服务器,迪博纳把这种形式比喻成互联网服务的“磁盘驱动器”(但别和一直谣传的Google存储服务Gdrive混淆了,“并没有 Gdrive这回事。”一位Google女发言人明确表示。),公司的软件程序都驻扎在这些并不昂贵的电脑机箱里,由程序员决定它们的冗余工作量。这种由 很多单元组成的文件系统代替了商业存储设备;迪博纳表示Google这些单元设备更易于建造和维护,他还暗示他们能处理更大规模的数据。

  Google 不会漏过对任何技术细节的关注。多年来,公司的工程师就在研究微处理器的内部工作机制,随着Google规模的持续壮大,必然会用到特别定制和调节过的芯 片。知名工程师路易斯”巴罗索(Luiz Barroso)去年在一篇发表在工业杂志上的论文中证实,近年来Google的主要负荷都由单核设计的系统承担着。但许多服务器端的应用,如 Google搜索索引服务,所需的并行计算在单核芯片的指令级别上执行得并不好。

  曾在数据设备公司(Digital Equipment)和康柏公司(Compaq)当过芯片设计师的巴罗索认为,随着AMD公司、英特尔公司(Intel)、太阳计算机系统公司(Sun)开始制造多核芯片,必将会出现越来越多芯片级别的并行计算。

  Google 也曾考虑过自己制造计算机芯片,但从业界潮流来看,这个冒险的举动似乎不是很必要。“微处理器的设计非常复杂而且成本昂贵,”运营高级副总裁乌尔斯”霍尔 茨勒(Urs Holzle)表示。Google宁愿与芯片制造商合作,让他们去理解自己的应用并设计适合的芯片。这是一种客户建议式的设计,其关注点在于总体吞吐量、 效能,以及耗电比,而不是看单线程的峰值性能。霍尔茨勒表示,“这也是最近多核CPU的设计潮流与未来方向。”
裁缝般地定制软件

  为了能尽量压榨硬件性能,Google开发了相当数量的定制软件。创新产品主要包括用于简化处理和创建大规模数据集的编程模型 MapReduce;用于存储和管理大规模数据的系统BigTable;分析分布式运算环境中大规模数据集的解释编程语言Sawzall;用于数据密集型 应用的分布式文件系统的 “Google文件系统”(Google File System);还有为处理分布式系统队列分组和任务调度的“Google工作队列”(Google Workqueue)。

  正是从Sawzall这些工具里体现出Google对计算效率的执著关注。并不是每家公司都能从底层去解决效率问题,但是对Google来说, 为常规关系型数据库无法容纳的大规模数据集专门设计一种编程语言是完全合理的。即使其他编程工具可以解决问题,Google的工程师们仍然会为了追求效率 而另外开发一套定制方案。Google工程师认为,Sawzall能与C++中的MapReduce相媲美,而且它更容易编写一些。

  Google 对效率的关注使它不可能对标准内核感到满意;Google会根据自己的需要运行修改过的内核版本。通过调整的底层性能,Google 工程师们在提高了整体系统可靠性的基础上,还一并解决了数据损坏和数据瓶颈等一系列棘手问题。对内核的修改也使Google的计算机集群系统因为通信效率 的提高而运行得更快。

  当然,Google偶尔也会出现系统故障,情况一旦发生,无数的用户就会受到影响了。三年前一次持续30分钟的系统故障使20%的搜索流量受到影响。

  Google 开发了自己的网站服务器却没有使用开源的Apache服务器,尽管它在网站服务器的市场占有率超过60%。迪博纳认为,Google的网站服务器可以运行 在更多数量的主机上,对Google站点上内容庞大又彼此互相依赖的应用程序来说,这种服务器的负载均衡能力远比Apache的能力更高。同时,在用标准 公共网关接口(CGI)访问数据库动态网页方面,Google服务器的编程难度要比 Apache更高,但是最终运行速度却更快。“如果我们能够压榨出10%~20%的性能,我们就可以节省出更多系统资源、电量和人力了。”迪博纳在总结中指出。

  Google还设计了自己的客户关系管理(CRM)系统用于支持自己基于竞价和点击的互联网广告收费业务。但对是否需要设计自己的工具,Google的态度也不是一成不变的。比如在财会软件上,它就使用了甲骨文公司(Oracle)的Financials软件。

  美林拿着一只叉子举例说明现成的产品也可以带来价值。但在有些场合现成的软件产品就不一定适用了。“我们的文化在各个层面对我们的运作都有深远影响,”他表示,“所以我们不想让购买所得的工具改变我们的工作方式和文化层面。”
Google’s BigTable 原理 (翻译)

题记:google 的成功除了一个个出色的创意外,还因为有 Jeff Dean 这样的软件架构天才。
—— 编者

官方的 Google Reader 中有对BigTable 的解释。这是Google 内部开发的一个用来处理大数据量的系统。这种系统适合处理半结构化的数据比如 RSS 数据源。 以下发言 是 Andrew Hitchcock 在 2005 年10月18号 基于: Google 的工程师 Jeff Dean 在华盛顿大学的一次谈话 (Creative Commons License).

首先,BigTable 从 2004 年初就开始研发了,到现在为止已经用了将近8个月。(2005年2月)目前大概有100个左右的服务使用BigTable,比如: Print,Search History,Maps和 Orkut。根据Google的一贯做法,内部开发的BigTable是为跑在廉价的PC机上设计的。BigTable 让Google在提供新服务时的运行成本降低,最大限度地利用了计算能力。

BigTable 是建立在 GFS ,Scheduler ,Lock Service 和 MapReduce 之上的。

每个Table都是一个多维的稀疏图 sparse map。Table 由行和列组成,并且每个存储单元 cell 都有一个时间戳。在不同的时间对同一个存储单元cell有多份拷贝,这样就可以记录数据的变动情况。在他的例子中,行是URLs ,列可以定义一个名字,比如:contents。Contents 字段就可以存储文件的数据。或者列名是:”language”,可以存储一个“EN”的语言代码字符串。

为了管理巨大的Table,把Table根据行分割,这些分割后的数据统称为:Tablets。每 个Tablets大概有 100-200 MB,每个机器存储100个左右的 Tablets。底层的架构是:GFS。由于GFS是一种分布式的文件系统,采用Tablets的机制后,可以获得很好的负载均衡。比如:可以把经常响应 的表移动到其他空闲机器上,然后快速重建。

Tablets在系统中的存储方式是不可修改的 immutable 的SSTables,一台机器一个日志文件。当系统的内存满后,系统会压缩一些Tablets。由于Jeff在论述这点的时候说的很快,所以我没有时间把听到的都记录下来,因此下面是一个大概的说明:

压缩分为:主要和次要的两部分。次要的压缩仅仅包括几个Tablets,而主要的压缩时关于整个系统的压缩。主压缩有回收硬盘空间的功能。Tablets的位置实际上是存储在几个特殊的BigTable的存储单元cell中。看起来这是一个三层的系统。
客户端有一个指向METAO的Tablets的指针。如果METAO的Tablets被频繁使用,那个这台机器就会放弃其他的tablets专门支持 METAO这个Tablets。METAO tablets 保持着所有的META1的tablets的记录。这些tablets中包含着查找tablets的实际位置。(老实说翻译到这里,我也不太明白。)在这个系统中不存在大的瓶颈,因为被频繁调用的数据已经被提前获得并进行了缓存。

现在我们返回到对列的说明:列是类似下面的形式: family:optional_qualifier。在他的例子中,行:www.search-analysis.com 也许有列:”contents:其中包含页面的代码。 “ anchor:cnn.com/news” 中包含着 相对应的url,”anchor:www.search-analysis.com/” 包含着链接的文字部分。列中包含着类型信息。
(翻译到这里我要插一句,以前我看过一个关于万能数据库的文章,当时很激动,就联系了作者,现在回想起来,或许google的 bigtable 才是更好的方案,切不说分布式的特性,就是这种建华的表结构就很有用处。)

注意这里说的是列信息,而不是列类型。列的信息是如下信息,一般是:属性/规则。 比如:保存n份数据的拷贝或者保存数据n天长等等。当 tablets 重新建立的时候,就运用上面的规则,剔出不符合条件的记录。由于设计上的原因,列本身的创建是很容易的,但是跟列相关的功能确实非常复杂的,比如上文提到 的 类型和规则信息等。为了优化读取速度,列的功能被分割然后以组的方式存储在所建索引的机器上。这些被分割后的组作用于 列 ,然后被分割成不同的 SSTables。这种方式可以提高系统的性能,因为小的,频繁读取的列可以被单独存储,和那些大的不经常访问的列隔离开来。

在一台机器上的所有的 tablets 共享一个log,在一个包含1亿的tablets的集群中,这将会导致非常多的文件被打开和写操作。新的log块经常被创建,一般是64M大小,这个GFS的块大小相等。当一个机器down掉后,控制机器就会重新发布他的log块到其他机器上继续进行处理。这台机器重建tablets然后询问控制机器处理结构的存储位置,然后直接对重建后的数据进行处理。这个系统中有很多冗余数据,因此在系统中大量使用了压缩技术。

Dean 对压缩的部分说的很快,我没有完全记下来,所以我还是说个大概吧:压缩前先寻找相似的 \行,列,和时间数据。

他们使用不同版本的: BMDiff 和 Zippy 技术。

BMDiff 提供给他们非常快的写速度: 100MB/s – 1000MB/s 。Zippy 是和 LZW 类似的。Zippy 并不像 LZW 或者 gzip 那样压缩比高,但是他处理速度非常快。

Dean 还给了一个关于压缩 蜘蛛数据的例子。这个例子的蜘蛛 包含 2.1B 的页面,行按照以下的方式命名:“com.cnn.www/index.:http”.在未压缩前的 page 页面大小是:45.1 TB ,压缩后的大小是:4.2 TB , 只是原来的 9.2%。Links 数据压缩到原来的 13.9% , 链接文本数据压缩到原来的 12.7%。
Read the rest of this entry »


专家说:服用少量大粪不影响健康

Posted by dengwei

注意:本贴所有言论皆转自国际互联网,本次的事件,让人还是一如既往的痛心疾首。中国是善于创造奇迹的国家,中华民族又是如此的充满黑色幽默的民族!但是我觉得,中国的一切食品,商品,都不能免检,不但不能免检,从今以后,还应该大检特检!!
专家说:服用少量大粪不影响健康
据《日人民报》报道,Z国营养与食品安全所研究员李狞、陈君屎,和B儿童医院副院长沈蝇、B大一医院副院长腚洁,就有些奸商用大粪水泡臭豆腐一事对记者说,不法分子用大粪水来制造臭豆腐,就是为了缩短制作时间,牟取暴利。
李狞说,一个物质的毒性作用跟剂量是有关系的。如果臭豆腐中大粪的含量比较高,人们食用时间相对比较长,则可能对健康构成损害;如果臭豆腐中大粪的含量相对低一些,就不会对健康造成危害。
专家们都指出,成人对大粪的耐受量较高,婴幼儿的耐受量更高,民间不是有“吃屎的孩子”一说吗?再说,人们每天摄入的臭豆腐极少,并不以臭豆腐为主要食物来源,所以广大人民群众的健康受到影响的机率很小。
专家们说,从有关部门公布的数据来看,被检测的臭豆腐中,只有20%是用大粪水泡过的,在检测出的企业中也只是某些批次有问题,大部分臭豆腐还是安全的。即使用大粪水泡过的臭豆腐,大部分的大粪含量也低于国际标准。WC等国际机构对人体摄入大粪的安全限量进行了科学评估,按照最严格的评估标准计算:以一个标准体重60公斤的成年人为例,食用大粪如每天不超过2公斤,对人体是安全的。
最后,陈院士幽默地对记者说:“我顺便告诉大家一下,我现在仍然顿顿一块臭豆腐。”
(本文作者一家村主声明:本文纯是虚构戏作,欢迎对号入座,后果由对号入座者自负!)
http://cache.tianya.cn/techforum/content/738/1471.shtml
小知识:
1888年,美国总统Cleveland宣布中国人乃是美国和平和利益的威胁。
因为美国为中国妇女进入美国设置重重障碍,以致唐人街充斥华人男子。下图摄于19世纪末的旧金山唐人街。


squid日志TCP命中率字段祥解

Posted by dengwei

squid的日志很重要。常常要了解的,其中最重要的就是命中率啦,不然反向代理做的用就不大。
#cat access.log|gawk ‘{print $4}’|sort|uniq -c|sort -nr
9568 TCP_IMS_HIT/304
6313 TCP_HIT/200
2133 TCP_MISS/200
1568 TCP_MISS/206
587 TCP_MEM_HIT/200
531 TCP_MISS/304
207 TCP_REFRESH_HIT/200
152 TCP_REFRESH_HIT/304
86 TCP_NEGATIVE_HIT/404
69 TCP_MISS/404
9 TCP_MISS/000
4 TCP_MISS/503
1 TCP_REFRESH_MISS/000
1 TCP_DENIED/400
可以使用上面的方法,大约的分析一下命令中比。什么意思就看下面的详解.
#cat /var/log/squid/access.log |grep TCP_MEM_HIT
如果看到很多的TCP_MEM_HIT ,这表明该文件是从内存缓存读取的,squid已经起作用了!你再用浏览器打开该文件,应该是快如闪电了。。呵呵,大功告成了!还有其他类型的HIT,如TCP_HIT等等,这些是从磁盘读取的,我� ��得加速的意义不大,只不过缓解了apache的压力而已。
相应于HTTP请求,下列标签可能出现在access.log文件的第四个域。
TCP_HIT
Squid发现请求资源的貌似新鲜的拷贝,并将其立即发送到客户端。
TCP_MISS
Squid没有请求资源的拷贝。
TCP_REFERSH_HIT
Squid发现请求资源的貌似陈旧的拷贝,并发送确认请求到原始服务器。原始服务器返回304(未修改)响应,指示squid的拷贝仍旧是新鲜的。
TCP_REF_FAIL_HIT
Squid发现请求资源的貌似陈旧的拷贝,并发送确认请求到原始服务器。然而,原始服务器响应失败,或者返回的响应Squid不能理解。在此情形下,squid发送现有拷贝(很可能是陈旧的)到� �户端。
TCP_REFRESH_MISS
Squid发现请求资源的貌似陈旧的拷贝,并发送确认请求到原始服务器。原始服务器响应新的内容,指示这个拷贝确实是陈旧的。
TCP_CLIENT_REFRESH_MISS
Squid发现了请求资源的拷贝,但客户端的请求包含了-Control: no-指令。Squid转发客户端的请求到原始服务器,强迫确认。
TCP_IMS_HIT
客户端发送确认请求,Squid发现更近来的、貌似新鲜的请求资源的拷贝。Squid发送更新的内容到客户端,而不联系原始服务器。
TCP_SWAPFAIL_MISS
Squid发现请求资源的有效拷贝,但从磁盘装载它失败。这时squid发送请求到原始服务器,就如同这是个丢失一样。
TCP_NEGATIVE_HIT
在对原始服务器的请求导致HTTP错误时,Squid也会这个响应。在短时间内对这些资源的重复请求,导致了否命中。 negative_ttl指令控制这些错误被的时间数量。请注意这些错误只在内存,不会写往磁盘。下列HTTP状态码可能导致否定 (也遵循于其他约束): 204, 305, 400, 403, 404, 405, 414, 500, 501, 502, 503, 504。
TCP_MEM_HIT
Squid在内存里发现请求资源的有效拷贝,并将其立即发送到客户端。注意这点并非精确的呈现了所有从内存服务的响应。例如,某些在内存里,但要求确认的响应,会以TCP_REFRESH_HIT, TCP_REFRESH_MISS等形式记录。
TCP_DENIED
因为http_access或http_reply_access规则,客户端的请求被拒绝了。注意被http_access拒绝的请求在第9域的值是NONE/-,然而被http_reply_access拒绝的请求,在相应地方有一个有效值。
TCP_OFFLINE_HIT
当offline_mode激活时,Squid对任何响应返回命中,而不用考虑它的新鲜程度。
TCP_REDIRECT
重定向程序告诉Squid产生一个HTTP重定向到新的URI(见11.1节)。正常的,Squid不会记录这些重定向。假如要这样做,必须在编译squid前,手工定义LOG_TCP_REDIRECTS预处理指令。
NONE
无分类的结果用于特定错误,例如无效主机名。
相应于ICP查询,下列标签可能出现在access.log文件的第四域。
UDP_HIT
Squid在里发现请求资源的貌似新鲜的拷贝。
UDP_MISS
Squid没有在里发现请求资源的貌似新鲜的拷贝。假如同一目标通过HTTP请求,就可能是个丢失。请对比UDP_MISS_NOFETCH。
UDP_MISS_NOFETCH
跟UDP_MISS类似,不同的是这里也指示了Squid不愿去处理相应的HTTP请求。假如使用了-Y命令行选项,Squid在启动并编译其内存索引时,会返回这个标签而不是UDP_MISS。
UDP_DENIED
因为icp_access规则,ICP查询被拒绝。假如超过95% 的到某客户端的ICP响应是UDP_DENIED,并且客户端数据库激活了(见附录A),Squid在1小时内,停止发送任何ICP响应到该客户端。若这点发生,你也可在.log里见到一个警告。
UDP_INVALID
Squid接受到无效查询(例如截断的消息、无效协议版本、URI里的空格等)。Squid发送UDP_INVALID响应到客户端。


不一样的百度知道

Posted by dengwei

▉提问:怎样可以最有效地瘦臀?
回答:蹭树。
▉提问:显示器画面不停地轻微抖动,有什么办法?
答:你也不停地抖动,当你的频率和振幅与显示器画面一致时,你就感觉不出来了。
▉提问:为什么好马不吃回头草?
回答:因为马儿拉屎在后面拉。
▉提问:如何除掉烦人的狗?我家附近有人养狗,且不管它随便跑,经常晚上在我家门口拉屎,有没有办法不让它在我家拉屎,或神不知鬼不觉地把它弄死且没人知道。
回答一:和主人说没用,我告诉你个好主意。每次狗拉屎的时候,你去偷看,等狗发现了你在偷看,它会害羞的,就再也不敢到你家门口拉屎了。
回答二:给它买一台计算机,然后教它上网,它就没空去你家门口了。
▉提问:为什么我玩3D游戏时会头晕?
回答一:小脑不发达。
回答二:大脑不发达。
回答三:大小脑都不发达。
▉提问:怎么驱赶蚂蚁?
回答一:在寝室门上贴上“戒严”或者“查封”等字样,造成寝室已经停止营业的假象。
回答二:买个食蚁兽回来不就结了。
回答三:播放张楚的歌曲《蚂蚁》三十遍。
回答四:把这个问题贴到蚁巢门口,难死它们!难不死的也会被这个悖论折磨死。
回答五:养些白蚁,让他们种族歧视,自相残杀。
▉提问:怎么样才能在街上捡到更多的钱?
回答一:把自己的钱包丢在地上就可。
回答二:最好当垃圾清扫员。这样拾零钱几率大。
回答三:钱不是捡来的,也不要低头走,钱是天上掉下来的,要时刻抬头看。
▉提问:最简单的长寿秘诀是什么?
回答:保持呼吸,不要断气。
▉提问:我要问百度知道知道不知道知道就知道不知道就不知道不要知道说不知道不知道说知道到头来知道变成不知道不知道还是不知道天知道地知道百度知道知道若要问我知道不知道知道不知道也不知道。请加标点符号,眼睛不好慎入~
回答:我要问百度知道:“知道不知道?”知道就知道,不知道就不知道。不要知道说不知道,不知道说知道,到头来知道变成不知道,不知道还是不知道。天知道、地知道、百度知道知道,若要问我知道不知道,知道不知道也不知道!
▉提问:为什么月亮不围着太阳转?
回答:因为月亮已经围着地球转了。
▉提问:刘关张三结义供的是谁?
回答一:皇天后土。
回答二:炎黄二帝。
回答三:桃子。
▉提问:“实在难以置信”用英语怎么说?经常在电影里听到,“安宝累宝宝”或者“挠怕司宝”这两句怎么写?准确的意思是什么?
回答:应该是这样才对:
unbelievable(安宝累宝宝)难以置信!
notpossible(挠怕司宝)不可能!这一句的语气比上面那个更强烈些。
▉提问:跷二郎腿的危害?
回答:屁股会一半大一半小。
▉提问:为什么人会怕高,而鸟却不会?
回答一:人知道掉下来是什么滋味,但鸟不知道。
回答二:鸟在飞翔的时候,从来没有顾虑,它不会惦记自己的翅膀。而人总是想得太多,负重太大。
▉提问:巫师为什么要骑扫把不骑板凳呢?
回答:因为骑扫把比骑板凳帅多了,而且遇到敌人(强大的,自己打不过)就可以伪装成扫地工。
▉提问:超人的内裤为什么总是穿在外面?
回答一:穿在里面了,谁知道你是超人?
回答二:蝙蝠侠,内裤套头了;蜘蛛侠,内衣外穿了;超人怎么能不走时尚路线呢?他就内裤外穿了……
▉提问:我的电脑里有病毒我应该买什么杀虫剂好?
回答一:什么都不用,你可以一个月不开机,把病毒饿死在里面。
回答二:光饿死还不够,万一病毒太饿了爬出来感染别人的电脑怎么办!不光要不开机饿死它还要拿个袋子把电脑密封起来给它断水断粮断空气才行。
回答三:用妇炎洁吧,洗洗更健康。
回答四:用妇炎洁不行啊,楼上的。如果电脑是男性怎么办?其实用汰渍最好了。不伤手,除菌。
回答五:楼上的全都不厚道,电脑病毒是不能用杀虫剂的,你把电脑带到防疫站给医生去打一针就行了,以后每年打一针就能彻底防止病毒入侵了。
▉提问:我的电脑中病毒;我用杀虫剂喷在主机上,怎么不管事?
回答一:可以找杀虫剂厂家理论啊,再不你可以告到消费者协会去
回答二:没事 你喷得不够多 多盆一点就好了
最佳答案:中病毒应该是软件的问题,不是硬件问题,所以,你喷在主机上是没用的,你应该打开电脑,拆下硬盘,再拆开硬盘进行喷射即可解决你的问题! (不许笑,严肃点)
▉提问:市场上有增肥药吗?吃什么东西能胖一点?越简单越好!
回答:有,只要一会儿就马上变肥。方法是找个马蜂窝,用手伸进去搅拌两下,呵,只要一会儿,保证肥得连老妈都不认识你了。
▉提问:向高手请教,抢银行什么枪合适,还有枪在哪儿买,AK-47多少钱一把?知道的说一下。谢谢!
回答:有经验的都不在这里,不过你试着抢一下就会见到他们。
▉提问:请举一些化学造福人类的例子。
回答一:近一个世纪以来,化学对人类社会所作出的最卓越的贡献大约有:合成纤维、染料、石化、制药、化肥、合成材料等。
回答二:原子弹。没有不“服”的。
▉提问:一个智力问题。228的后面是什么?103的后面是什么?85的后面是什么?3个答案都一样!给我答案就好。
回答:的。
▉提问:明星要吃饭上厕所吗?
回答一:当然不用,明星吃饭叫“用餐”。明星上厕所叫上“洗手间”。所以不用“吃饭”和“上厕所”。
回答二:没看见的就当没发生。
▉提问:维护世界和平的使命可以交给我吗
回答一:如果你是动感超人,我会考虑的。
回答二:当然不能交给你了,下一届的美国总统选举必须由你来出面,否则美国人民决不答应的。
回答三:如果你拥有超人的力量,百变星君的能力,忍者神龟的身手,阿童木的勇气,一休的智慧,毛泽东的魄力,周恩来的手段,布什的谋划……基本上就可以去维护世界和平了。
回答四:开这么大的玩笑
回答五:你算老几啊?凭什么给你!如果你是奥特曼,那就可以!
▉提问:为什么学生宿舍要禁用“热得快”
答: 第一,费电
第二,容易失火
第三,烧得水只能洗脚,因为质量不好
▉提问:怎样洗衣服干净
答: 勤洗
▉提问:为虾米稀饭一个人那么难???
1答:锻鍊一下口齿吧,说的清楚就不难了
2答: 稀饭是个人?…用的拟人手法??
3答: 给稀饭个包子..它就不难了.
▉提问: 我不慎吞入一只飞虫,是否会出事?
回答:当然是好事了,能品尝到世间少有的野味,而且那些东西还有丰富蛋白质,有许多微量元素,肯定能增加你的功力的。
▉提问: 求助!我电脑开不了机了!风扇都不转,主板灯也不亮啊!
最佳回答: 插线了么?
对最佳答案的补充:没!
▉提问:我是计算机网络班的学生。我们要开运动会了,老师要我们为班级说一个口号?要新奇,有创新,跟我们所学的计算机网络有关。
回答1:最大的流量,最快的速度!
回答2:我们保证不卡
回答3:XX班,电话线,我们班小光纤!
▉提问:谁能形容一下CPU,内存和硬盘的关系??
回答:你是cpu内存是碗硬盘是锅,你吃饭时直接用碗,但是东西是从锅里盛出来的
▉提问:宝宝将在2007年2月诞生,爸姓章,妈姓王,请大家起个名,男女孩什么?最好是双字名,且是动宾结构的.
回答:章鱼王
▉提问:我爱的人名花有主!爱我的人残不忍睹!!为什么会这样啊!
回答:虽然名花已有主,偶尔也可去松松土
虽然看来不忍睹,闷热也可来解解暑
▉提问:如何抵挡美色的诱惑??
回答:糖衣吃了,炮弹打回去!
▉提问:我的孔雀鱼一天之内死100只?为什么会这样呢?
回答:都是因为你~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 因为你是个有钱的笨蛋,钱多烧的啊
2 因为你是个没有文化的笨蛋,一次性买这么多干什么 你不会先放两条试试水
3 因为你是个容易上当的笨蛋,商家买给你的是病鱼
4 因为你是个不懂养鱼的笨蛋,你自己琢磨去吧~~~………
▉提问:为什么沈阳工业大学的上空那么多乌鸦啊?
回答:因为乌鸦也要混文凭啊


[转]内存种类知多少

Posted by gavinkwoe

    终于知道为什么都被CPU当做Internal 来用。
    凡是对电脑有所了解的朋友都知道内存这玩意,可是,可能有不少朋友对内存的认识仅仅局限在和DDR 这两种类型,事实上,内存的种类是非常多的,从能否写入的角度来分,就可以分为(随机存取存储器)和ROM(只读存储器)这两大类。每一类别里面有分别有许多种类的内存。以下就让我们看看内存到底有些什么种类吧!

 
  一、(Random Access Memory,随机存取存储器)
 

 
  的特点是:电脑开机时,操作系统和应用程序的所有正在运行的数据和程序都会放置其中,并且随时可以对存放在里面的数据进行修改和存取。它的工作需要由持续的电力提供,一旦系统断电,存放在里面的所有数据和程序都会自动清空掉,并且再也无法恢复。
 
  根据组成元件的不同,内存又分为以下十八种:
 
  01.DRAM(Dynamic ,动态随机存取存储器):
 

 
  这是最普通的,一个电子管与一个电容器组成一个位存储单元,DRAM将每个内存位作为一个电荷保存在位存储单元中,用电容的充放电来做储存动作,但因电容本身有漏电问题,因此必须每几微秒就要刷新一次,否则数据会丢失。存取时间和放电时间一致,约为2~4ms。因为成本比较便宜,通常都用作计算机内的主存储器。
 
  02.SRAM(Static ,静态随机存取存储器)
 

 
  静态,指的是内存里面的数据可以长驻其中而不需要随时进行存取。每6颗电子管组成一个位存储单元,因为没有电容器,因此无须不断充电即可正常运作,因此它可以比一般的动态随机处理内存处理速度更快更稳定,往往用来做高速缓存。
 
  03.VRAM(Video ,视频内存)
 

 
  它的主要功能是将显卡的视频数据输出到数模转换器中,有效降低绘图显示芯片的工作负担。它采用双数据口设计,其中一个数据口是并行式的数据输出入口,另一个是串行式的数据输出口。多用于高级显卡中的高档内存。
 
  04.FPM DRAM(Fast Page Mode DRAM,快速页切换模式动态随机存取存储器)
 

 
  改良版的DRAM,大多数为72Pin或30Pin的模块。传统的DRAM在存取一个BIT的数据时,必须送出行地址和列地址各一次才能读写数据。而FRM DRAM在触发了行地址后,如果CPU需要的地址在同一行内,则可以连续输出列地址而不必再输出行地址了。由于一般的程序和数据在内存中排列的地址是连续的,这种情况下输出行地址后连续输出列地址就可以得到所需要的数据。FPM将记忆体内部隔成许多页数Pages,从512B到数KB不等,在读取一连续区域内的数据时,就可以通过快速页切换模式来直接读取各page内的资料,从而大大提高读取速度。在96年以前,在486时代和PENTIUM时代的初期,FPM DRAM被大量使用。
 
  05.EDO DRAM(Extended Data Out DRAM,延伸数据输出动态随机存取存储器)
 

 
  这是继FPM之后出现的一种存储器,一般为72Pin、168Pin的模块。它不需要像FPM DRAM那样在存取每一BIT 数据时必须输出行地址和列地址并使其稳定一段时间,然后才能读写有效的数据,而下一个BIT的地址必须等待这次读写操作完成才能输出。因此它可以大大缩短等待输出地址的时间,其存取速度一般比FPM模式快15%左右。它一般应用于中档以下的Pentium主板标准内存,后期的486系统开始支持EDO DRAM,到96年后期,EDO DRAM开始执行。。
 
  06.BEDO DRAM(Burst Extended Data Out DRAM,爆发式延伸数据输出动态随机存取存储器)
 
  这是改良型的EDO DRAM,是由美光公司提出的,它在芯片上增加了一个地址计数器来追踪下一个地址。它是突发式的读取方式,也就是当一个数据地址被送出后,剩下的三个数据每一个都只需要一个周期就能读取,因此一次可以存取多组数据,速度比EDO DRAM快。但支持BEDO DRAM内存的主板可谓少之又少,只有极少几款提供支持(如VIA APOLLO VP2),因此很快就被DRAM取代了。
 
  07.MDRAM(Multi-Bank DRAM,多插槽动态随机存取存储器)
 

 
  MoSys公司提出的一种内存规格,其内部分成数个类别不同的小储存库 (BANK),也即由数个属立的小单位矩阵所构成,每个储存库之间以高于外部的资料速度相互连接,一般应用于高速显示卡或加速卡中,也有少数主机板用于L2高速缓存中。
 
  08.WRAM(Window ,窗口随机存取存储器)
 

 
  韩国Samsung公司开发的内存模式,是VRAM内存的改良版,不同之处是它的控制线路有一、二十组的输入/输出控制器,并采用EDO的资料存取模式,因此速度相对较快,另外还提供了区块搬移功能(BitBlt),可应用于专业绘图工作上。
 
  09.RDRAM(Rambus DRAM,高频动态随机存取存储器)
 

 
  Rambus公司独立设计完成的一种内存模式,速度一般可以达到500~530MB/s,是DRAM的10倍以上。但使用该内存后内存控制器需要作相当大的改变,因此它们一般应用于专业的图形加速适配卡或者电视游戏机的视频内存中。
 
  10.(Synchronous DRAM,同步动态随机存取存储器)
 

 
  这是一种与CPU实现外频Clock同步的内存模式,一般都采用168Pin的内存模组,工作电压为3.3V。 所谓clock同步是指内存能够与CPU同步存取资料,这样可以取消等待周期,减少数据传输的延迟,因此可提升计算机的性能和效率。
 
  11.SGRAM(Synchronous Graphics ,同步绘图随机存取存储器)
 

 
  的改良版,它以区块Block,即每32bit为基本存取单位,个别地取回或修改存取的资料,减少内存整体读写的次数,另外还针对绘图需要而增加了绘图控制器,并提供区块搬移功能(BitBlt),效率明显高于
 
  12.SB SRAM(Synchronous Burst SRAM,同步爆发式静态随机存取存储器)
 
  一般的SRAM是非同步的,为了适应CPU越来越快的速度,需要使它的工作时脉变得与系统同步,这就是SB SRAM产生的原因。
 
  13.PB SRAM(Pipeline Burst SRAM,管线爆发式静态随机存取存储器)
 
  CPU外频速度的迅猛提升对与其相搭配的内存提出了更高的要求,管线爆发式SRAM取代同步爆发式SRAM成为必然的选择,因为它可以有效地延长存取时脉,从而有效提高访问速度。
 
  14.DDR (Double Data Rate二倍速率同步动态随机存取存储器)
 

 
  作为的换代产品,它具有两大特点:其一,速度比有一倍的提高;其二,采用了DLL(Delay Locked Loop:延时锁定回路)提供一个数据滤波信号。这是目前内存市场上的主流模式。
 
  15.SLDRAM (Synchronize Link,同步链环动态随机存取存储器)
 
 

 
 
 
  这是一种扩展型结构内存,在增加了更先进同步电路的同时,还改进了逻辑控制电路,不过由于技术显示,投入实用的难度不小。
 
  16.CDRAM(CACHED DRAM,同步缓存动态随机存取存储器)
 
  这是三菱电气公司首先研制的专利技术,它是在DRAM芯片的外部插针和内部DRAM之间插入一个SRAM作为二级使用。当前,几乎所有的CPU都装有一级来提高效率,随着CPU时钟频率的成倍提高,不被选中对系统性能产生的影响将会越来越大,而 DRAM所提供的二级正好用以补充CPU一级之不足,因此能极大地提高CPU效率。
 
  17.DDRII (Double Data Rate Synchronous DRAM,第二代同步双倍速率动态随机存取存储器)
 

 
  DDRII 是DDR原有的SLDRAM联盟于1999年解散后将既有的研发成果与DDR整合之后的未来新标准。DDRII的详细规格目前尚未确定。
 
  18.DRDRAM (Direct Rambus DRAM)
 

 
  是下一代的主流内存标准之一,由Rambus 公司所设计发展出来,是将所有的接脚都连结到一个共同的Bus,这样不但可以减少控制器的体积,已可以增加资料传送的效率。
 
  二、ROM(READ Only Memory,只读存储器)
 
  ROM是线路最简单半导体电路,通过掩模工艺,一次性制造,在元件正常工作的情况下,其中的代码与数据将永久保存,并且不能够进行修改。一般应用于PC系统的程序码、主机板上的 BIOS (基本输入/输出系统Basic Input/Output System)等。它的读取速度比慢很多。
 
  根据组成元件的不同,ROM内存又分为以下五种:
 
  1.MASK ROM(掩模型只读存储器)
 
  制造商为了大量生产ROM内存,需要先制作一颗有原始数据的ROM或EPROM作为样本,然后再大量复制,这一样本就是MASK ROM,而烧录在MASK ROM中的资料永远无法做修改。它的成本比较低。
 
  2.PROM(Programmable ROM,可编程只读存储器)
 
  这是一种可以用刻录机将资料写入的ROM内存,但只能写入一次,所以也被称为“一次可编程只读存储器”(One Time Progarmming ROM,OTP-ROM)。PROM在出厂时,存储的内容全为1,用户可以根据需要将其中的某些单元写入数据0(部分的PROM在出厂时数据全为0,则用户可以将其中的部分单元写入1), 以实现对其“编程”的目的。
 
  3.EPROM(Erasable Programmable,可擦可编程只读存储器)
 

 
  这是一种具有可擦除功能,擦除后即可进行再编程的ROM内存,写入前必须先把里面的内容用紫外线照射它的IC卡上的透明视窗的方式来清除掉。这一类芯片比较容易识别,其封装中包含有“石英玻璃窗”,一个编程后的EPROM芯片的“石英玻璃窗”一般使用黑色不干胶纸盖住, 以防止遭到阳光直射。
 
  4.EEPROM(Electrically Erasable Programmable,电可擦可编程只读存储器)
 

 
  功能与使用方式与EPROM一样,不同之处是清除数据的方式,它是以约20V的电压来进行清除的。另外它还可以用电信号进行数据写入。这类ROM内存多应用于即插即用(PnP)接口中。
 
  5. Memory(快闪存储器)
 

 
  这是一种可以直接在主机板上修改内容而不需要将IC拔下的内存,当电源关掉后储存在里面的资料并不会流失掉,在写入资料时必须先将原本的资料清除掉,然后才能再写入新的资料,缺点为写入资料的速度太慢。

[转]嵌入式系统 Boot Loader 技术内幕

Posted by gavinkwoe

级别: 初级

詹荣开 (zhanrk@sohu.com), 爱好者

2003 年 12 月 01 日

本文详细地介绍了基于嵌入式系统中的 OS 启动加载程序 ―― 的概念、软件设计的主要任务以及结构框架等内容。

1. 引言

在专用的嵌入式板子运行 GNU/ 系统已经变得越来越流行。一个嵌入式 系统从软件的角度看通常可以分为四个层次:

1. 引导加载程序。包括固化在固件(firmware)中的 代码(可选),和 两大部分。

2. 内核。特定于嵌入式板子的定制内核以及内核的启动参数。

3. 文件系统。包括根文件系统和建立于 内存设备之上文件系统。通常用 disk 来作为 root fs。

4. 用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。常用的嵌入式 GUI 有:MicroWindows 和 MiniGUI 懂。

引导加载程序是系统加电后运行的第一段软件代码。回忆一下 PC 的体系结构我们可以知道,PC 机中的引导加载程序由 BIOS(其本质就是一段固件程序)和位于硬盘 MBR 中的 OS (比如,LILO 和 GRUB 等)一起组成。BIOS 在完成硬件检测和资源分配后,将硬盘 MBR 中的 读到系统的 中,然后将控制权交给 OS 的主要运行任务就是将内核映象从硬盘上读到 中,然后跳转到内核的入口点去运行,也即开始启动操作系统。

而在嵌入式系统中,通常并没有像 BIOS 那样的固件程序(注,有的嵌入式 CPU 也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由 来完成。比如在一个基于 ARM7TDMI core 的嵌入式系统中,系统在上电或复位时通常都从地址 0×00000000 处开始执行,而在这个地址处安排的通常就是系统的 程序。

本文将从 的概念、 的主要任务、 的框架结构以及 的安装等四个方面来讨论嵌入式系统的


回页首

2. 的概念

简单地说, 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。

通常, 是严重地依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的 几乎是不可能的。尽管如此,我们仍然可以对 归纳出一些通用的概念来,以指导用户特定的 设计与实现。

1. 所支持的 CPU 和嵌入式板

每种不同的 CPU 体系结构都有不同的 。有些 也支持多种体系结构的 CPU,比如 U- 就同时支持 ARM 体系结构和MIPS 体系结构。除了依赖于 CPU 的体系结构外, 实际上也依赖于具体的嵌入式板级设备的配置。这也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种 CPU 而构建的,要想让运行在一块板子上的 程序也能运行在另一块板子上,通常也都需要修改 的源程序。

2. 的安装媒介(Installation Medium)

系统加电或复位后,所有的 CPU 通常都从某个由 CPU 制造商预先安排的地址上取指令。比如,基于 ARM7TDMI core 的 CPU 在复位时通常都从地址 0×00000000 取它的第一条指令。而基于 CPU 构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROM、EEPROM 或 等)被映射到这个预先安排的地址上。因此在系统加电后,CPU 将首先执行 程序。

下图1就是一个同时装有 、内核的启动参数、内核映像和根文件系统映像的固态存储设备的典型空间分配结构图。
图1 固态存储设备的典型空间分配结构

3. 用来控制 的设备或机制

主机和目标机之间一般通过串口建立连接, 软件在执行时通常会通过串口来进行 I/O,比如:输出打印信息到串口,从串口读取用户控制字符等。

4. 的启动过程是单阶段(Single Stage)还是多阶段(Multi-Stage)

通常多阶段的 能提供更为复杂的功能,以及更好的可移植性。从固态存储设备上启动的 大多都是 2 阶段的启动过程,也即启动过程可以分为 stage 1 和 stage 2 两部分。而至于在 stage 1 和 stage 2 具体完成哪些任务将在下面讨论。

5. 的操作模式 (Operation Mode)

大多数 都包含两种不同的操作模式:”启动加载”模式和”下载”模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看, 的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。

启动加载( loading)模式:这种模式也称为”自主”(Autonomous)模式。也即 从目标机上的某个固态存储设备上将操作系统加载到 中运行,整个过程并没有用户的介入。这种模式是 的正常工作模式,因此在嵌入式产品发布的时侯, 显然必须工作在这种模式下。

下载(Downloading)模式:在这种模式下,目标机上的 将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 保存到目标机的 中,然后再被 写到目标机上的 类固态存储设备中。 的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 的这种工作模式。工作于这种模式下的 通常都会向它的终端用户提供一个简单的命令行接口。

像 Blob 或 U- 等这样功能强大的 通常同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。比如,Blob 在启动时处于正常的启动加载模式,但是它会延时 10 秒等待终端用户按下任意键而将 blob 切换到下载模式。如果在 10 秒内没有用户按键,则 blob 继续启动 内核。

6. BootLoader 与主机之间进行文件传输所用的通信设备及协议

最常见的情况就是,目标机上的 通过串口与主机之间进行文件传输,传输协议通常是 xmodem/ymodem/zmodem 协议中的一种。但是,串口传输的速度是有限的,因此通过以太网连接并借助 TFTP 协议来下载文件是个更好的选择。

此外,在论及这个话题时,主机方所用的软件也要考虑。比如,在通过以太网连接和 TFTP 协议来下载文件时,主机方必须有一个软件用来的提供 TFTP 服务。

在讨论了 BootLoader 的上述概念后,下面我们来具体看看 BootLoader 的应该完成哪些任务。


回页首

3. 的主要任务与典型结构框架

在继续本节的讨论之前,首先我们做一个假定,那就是:假定内核映像与根文件系统映像都被加载到 中运行。之所以提出这样一个假设前提是因为,在嵌入式系统中内核映像与根文件系统映像也可以直接在 ROM 或 这样的固态存储设备中直接运行。但这种做法无疑是以运行速度的牺牲为代价的。

从操作系统的角度看, 的总目标就是正确地调用内核来执行。

另外,由于 的实现依赖于 CPU 的体系结构,因此大多数 都分为 stage1 和 stage2 两大部分。依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在 stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而 stage2 则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。

的 stage1 通常包括以下步骤(以执行的先后顺序):

  • 硬件设备初始化。
  • 为加载 的 stage2 准备 空间。
  • 拷贝 的 stage2 到 空间中。
  • 设置好堆栈。
  • 跳转到 stage2 的 C 入口点。

的 stage2 通常包括以下步骤(以执行的先后顺序):

  • 初始化本阶段要使用到的硬件设备。
  • 检测系统内存映射(memory map)。
  • 将 kernel 映像和根文件系统映像从 上读到 空间中。
  • 为内核设置启动参数。
  • 调用内核。

3.1 的 stage1

3.1.1 基本的硬件初始化

这是 一开始就执行的操作,其目的是为 stage2 的执行以及随后的 kernel 的执行准备好一些基本的硬件环境。它通常包括以下步骤(以执行的先后顺序):

1. 屏蔽所有的中断。为中断提供服务通常是 OS 设备驱动程序的责任,因此在 的执行全过程中可以不必响应任何中断。中断屏蔽可以通过写 CPU 的中断屏蔽寄存器或状态寄存器(比如 ARM 的 CPSR 寄存器)来完成。

2. 设置 CPU 的速度和时钟频率。

3. 初始化。包括正确地设置系统的内存控制器的功能寄存器以及各内存库控制寄存器等。

4. 初始化 LED。典型地,通过 GPIO 来驱动 LED,其目的是表明系统的状态是 OK 还是 Error。如果板子上没有 LED,那么也可以通过初始化 UART 向串口打印 的 Logo 字符信息来完成这一点。

5. 关闭 CPU 内部指令/数据

3.1.2 为加载 stage2 准备 空间

为了获得更快的执行速度,通常把 stage2 加载到 空间中来执行,因此必须为加载 的 stage2 准备好一段可用的 空间范围。

由于 stage2 通常是 C 语言执行代码,因此在考虑空间大小时,除了 stage2 可执行映象的大小外,还必须把堆栈空间也考虑进来。此外,空间大小最好是 memory page 大小(通常是 4KB)的倍数。一般而言,1M 的 空间已经足够了。具体的地址范围可以任意安排,比如 blob 就将它的 stage2 可执行映像安排到从系统 起始地址 0xc0200000 开始的 1M 空间内执行。但是,将 stage2 安排到整个 空间的最顶 1MB(也即(RamEnd-1MB) - RamEnd)是一种值得推荐的方法。

为了后面的叙述方便,这里把所安排的 空间范围的大小记为:stage2_size(字节),把起始地址和终止地址分别记为:stage2_start 和 stage2_end(这两个地址均以 4 字节边界对齐)。因此:

stage2_end=stage2_start+stage2_size

另外,还必须确保所安排的地址范围的的确确是可读写的 空间,因此,必须对你所安排的地址范围进行测试。具体的测试方法可以采用类似于 blob 的方法,也即:以 memory page 为被测试单位,测试每个 memory page 开始的两个字是否是可读写的。为了后面叙述的方便,我们记这个检测算法为:test_mempage,其具体步骤如下:

1. 先保存 memory page 一开始两个字的内容。

2. 向这两个字中写入任意的数字。比如:向第一个字写入 0×55,第 2 个字写入 0xaa。

3. 然后,立即将这两个字的内容读回。显然,我们读到的内容应该分别是 0×55 和 0xaa。如果不是,则说明这个 memory page 所占据的地址范围不是一段有效的 空间。

4. 再向这两个字中写入任意的数字。比如:向第一个字写入 0xaa,第 2 个字中写入 0×55。

5. 然后,立即将这两个字的内容立即读回。显然,我们读到的内容应该分别是 0xaa 和 0×55。如果不是,则说明这个 memory page 所占据的地址范围不是一段有效的 空间。

6. 恢复这两个字的原始内容。测试完毕。

为了得到一段干净的 空间范围,我们也可以将所安排的 空间范围进行清零操作。

3.1.3 拷贝 stage2 到

拷贝时要确定两点:(1) stage2 的可执行映象在固态存储设备的存放起始地址和终止地址;(2) 空间的起始地址。

3.1.4 设置堆栈指针 sp

堆栈指针的设置是为了执行 C 语言代码作好准备。通常我们可以把 sp 的值设置为(stage2_end-4),也即在 3.1.2 节所安排的那个 1MB 的 空间的最顶端(堆栈向下生长)。

此外,在设置堆栈指针 sp 之前,也可以关闭 led 灯,以提示用户我们准备跳转到 stage2。

经过上述这些执行步骤后,系统的物理内存布局应该如下图2所示。

3.1.5 跳转到 stage2 的 C 入口点

在上述一切都就绪后,就可以跳转到 的 stage2 去执行了。比如,在 ARM 系统中,这可以通过修改 PC 寄存器为合适的地址来实现。
图2 bootloader 的 stage2 可执行映象刚被拷贝到 空间时的系统内存布局

3.2 的 stage2

正如前面所说,stage2 的代码通常用 C 语言来实现,以便于实现更复杂的功能和取得更好的代码可读性和可移植性。但是与普通 C 语言应用程序不同的是,在编译和链接 这样的程序时,我们不能使用 glibc 库中的任何支持函数。其原因是显而易见的。这就给我们带来一个问题,那就是从那里跳转进 main() 函数呢?直接把 main() 函数的起始地址作为整个 stage2 执行映像的入口点或许是最直接的想法。但是这样做有两个缺点:1)无法通过main() 函数传递函数参数;2)无法处理 main() 函数返回的情况。一种更为巧妙的方法是利用 trampoline(弹簧床)的概念。也即,用汇编语言写一段trampoline 小程序,并将这段 trampoline 小程序来作为 stage2 可执行映象的执行入口点。然后我们可以在 trampoline 汇编小程序中用 CPU 跳转指令跳入 main() 函数中去执行;而当 main() 函数返回时,CPU 执行路径显然再次回到我们的 trampoline 程序。简而言之,这种方法的思想就是:用这段 trampoline 小程序来作为 main() 函数的外部包裹(external wrapper)。

下面给出一个简单的 trampoline 程序示例(来自blob):

.text .globl _trampoline _trampoline: 	bl	main 	/* if main ever returns we just call it again */ 	b	_trampoline

可以看出