试问这种效果是怎么做出来的?

richgod 2007-11-02 09:16:39
由于言语表达不如图片来得方便,我在网易相册中上传了两张示例照片,
http://photo.163.com/photos/yizhikuai/140461400/4016117285/#4016096363
另一张是:
http://photo.163.com/photos/yizhikuai/140461400/4016117285/#4016117285

我想做这样的效果,分别点击左边的按钮,右边可以显示出不同的图片,图片上有各种不同的控件,通过这些控件实现一些功能,我是初学PB,请教一下该如何详细制作呢?困惑许久,十分想弄出来,还望能够帮我:-)
...全文
166 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
richgod 2007-11-09
  • 打赏
  • 举报
回复
在这里非常感谢lllyyymmm 算命先生的热心帮助,在QQ在电话,甚至给我示例代码,我太感谢了
DavidNoWay 2007-11-07
  • 打赏
  • 举报
回复
用两个DATAWINDOW,一个放导航,一个放具体内容
richgod 2007-11-06
  • 打赏
  • 举报
回复
要是用图片的话,是不是就不能自适应分辨率了?毕竟客户的机器的分辨率不一样啊
richgod 2007-11-06
  • 打赏
  • 举报
回复
AFIC师傅可否细说,愿听其详:-)
richgod 2007-11-06
  • 打赏
  • 举报
回复
然后呢?然后设置各个图层的隐显属性,通过按钮对其控制嘛?
AFIC 2007-11-06
  • 打赏
  • 举报
回复
首先,你要画一堆图片,其次,把图片放到窗口上
richgod 2007-11-04
  • 打赏
  • 举报
回复
谢谢楼上的,我还是打算用PB,刚学啊,不想放弃
lllyyymmm 2007-11-03
  • 打赏
  • 举报
回复
pb,在做这面挺方便的,你留个QQ吧
richgod 2007-11-03
  • 打赏
  • 举报
回复
jlwei888 2007-11-03
  • 打赏
  • 举报
回复
看不到,这里就能发图片!
Kenqin 2007-11-03
  • 打赏
  • 举报
回复
应该是用了外挂,要不就是用FLASH
lovelybee 2007-11-03
  • 打赏
  • 举报
回复
帮顶
立在心间 2007-11-03
  • 打赏
  • 举报
回复
还是用C#比较好点,PB太麻烦!
xiaofei1107 2007-11-03
  • 打赏
  • 举报
回复
好像不是很难,有好多种方法,一是用好控件的VISIBLE属性就可以,但是很麻烦;二是用多个窗口就可以,不过,得用到HIDE方法……如果可能的话,用.net会好做一点!支持你……
richgod 2007-11-03
  • 打赏
  • 举报
回复
我的QQ:46077430 一苇渡江 msn:renxinwen@hotmail.com 谢谢你的回复和关注,期待你的音讯
常见问题目录 本光盘的使用方法:点击感兴趣的问题,就可以链接到该问题的答案。所有文件都是用WORD打开的。在点击所要看的问题时,请同时按住Control键(Ctrl)。 第1章 概述 问题1-1:“主机”和“计算机”一样不一样? 问题1-2:能否说:“电路交换和面向连接是等同的,而分组交换和无连接是等同的”? 问题1-3:因特网使用的IP协议是无连接的,因此其传输是不可靠的。这样容易使人们感到因特网很不可靠。那么为什么当初不把因特网的传输设计成为可靠的? 问题1-4:在具有五层协议的体系结构中,如果下面的一层使用面向连接服务或无连接服务,那么在上面的一层是否也必须使用同样性质的服务呢?或者说,是否我们可以在各层任意使用面向连接服务或无连接服务呢? 问题1-5:在运输层应根据什么原则来确定应当使用面向连接服务还是无连接服务? 问题1-6:在数据链路层应根据什么原则来确定应当使用面向连接服务还是无连接服务? 问题1-7:TCP/IP的体系结构到底是四层还是五层? 问题1-8:我们常说“分组交换”。但又常说“路由器转发IP数据报”或“路由器转发帧”。究竟“分组”一词应当用在什么场合? 问题1-9:到商店购买可一个希捷公司生产的80 G的硬盘。安装到电脑上以后用WINDOWS的资源管理器发现在该磁盘的“属性”中只有74.5 G。是不是商店出了差错? 问题1-10:有这样的说法:习惯上,人们都将网络的“带宽”作为网络所能传送的“最高数据率”的同义语。这样的说法有何根据? 问题1-11:有时可听到人们将“带宽为10 Mb/s的以太网”说成是“速率(或速度)为10 Mb/s的以太网”或“10兆速率(或速度)的以太网”。试问这样的说法正确否? 问题1-12:有人说,宽带信道相当于高速公路车道数目增多了,可以同时并行地跑更多数量的汽车。虽然汽车的时速并没有提高(这相当于比特在信道上的传播速率没有提高),但整个高速公路的运输能力却增多了,相当于能够传送更多数量的比特。这种比喻合适否? 问题1-13:如果用时延带宽积管道来比作传输链路,那么是否宽带链路对应的时延带宽积管道就比较宽呢? 问题1-14:网络的吞吐量与网络的时延有何关系? 问题1-15:什么是“无缝的”、“透明的”和“虚拟的”? 问题1-16:在教材的1.7.2节提到协议有三个要素,即语法、语义和同步。语义是否已经包括了同步的意思? 问题1-17:为什么协议不能设计成100%可靠的? 问题1-18:什么是因特网的摩尔定律? 第2章 物理层 问题2-1:“规程”、“协议”和 “规约”都有何区别? 问题2-2:在许多文献中经常见到人们将“模拟”与“仿真”作为同义语。那么,“模拟信道”能否说成是“仿真信道”? 问题2-3:为什么电话信道的标准带宽是3.1 kHz? 问题2-4:奈氏准则和香农公式的主要区别是什么?这两个公式对数据通信的意义是什么? 问题2-5:传输媒体是物理层吗?传输媒体和物理层的主要区别是什么? 问题2-6:同步(synchronous)和异步(asynchronous)的区别是什么? 问题2-7:同步通信和异步通信的区别是什么? 问题2-8:位同步(比特同步)和帧同步的区别是什么? 第3章 数据链路层 问题3-1:旧版的《计算机网络》认为数据链路层的任务是在两个相邻结点间的线路上无差错地传送以帧(frame)为单位的数据。数据链路层可以把一条有可能出差错的实际链路,转变成为让网络层向下看起来好像是一条不出差错的链路。 但最近新版的《计算机网络》(第4版和第5版)中对数据链路层的提法就改变了。数据链路层的传输不能让网络层向下看起来好像是一条不出差错的链路。 到底哪一种说法是正确的? 问题3-2:当数据链路层使用PPP协议或CSMA/CD协议时,既然不保证可靠传输,那么为什么对所传输的帧进行差错检验呢? 问题3-3:为什么旧的版本教材在数据链路层一章中讲授可靠传输,但现在新的版本教材则取消了可靠传输? 问题3-4:通过普通的电话用户线拨号上网时(使用调制解调器),试问一对用户线可容许多少个用户同时上网? 问题3-5:除了差错检测外,面向字符的数据链路层协议还必须解决哪些特殊的问题? 问题3-6:为什么计算机进行通信时发送缓存和接收缓存总是需要的? 问题3-7:以太网使用载波监听多点接入碰撞检测协议CSMA/CD。频分复用FDM才使用载波。以太网有没有使用频分复用? 问题3-8:在以太网中,不同的传输媒体会产生不同的传播时延吗? 问题3-9:在以太网中发生了碰撞是否说明这时出现了某种故障? 问题3-10:从什么地方可以查阅到以太网帧格式中的“类型”字段是怎样分配的? 问题3-11:是什么原因使以太网有一个最小帧长和最大帧长? 问题3-12:在双绞线以太网中,其连接导线只需要两对线:一对线用于发送,另一对线用于接收。但现在的标准是使用RJ-45连接器。这种连接器有8根针脚,一共可连接4对线。这是否有些浪费?是否可以不使用RJ-45而使用RJ-11? 问题3-13:RJ-45连接器对8根针脚的编号有什么规定? 问题3-14:剥开5类线的外塑料保护套管就可以看见不同颜色的4对双绞线。哪一根线应当连接到哪一个针脚呢? 问题3-15:将5类线电缆与RJ-45插头连接起来的具体操作步骤是怎样的? 问题3-16:不用集线器或以太网交换机,能否将两台计算机用带有RJ-45插头的5类线电缆直接连接起来? 问题3-17:使用屏蔽双绞线电缆STP安装以太网是否可获得更好的效果? 问题3-18:如果将已有的10 Mb/s以太网升级到100 Mb/s,试问原来使用的连接导线是否还能继续使用? 问题3-19:使用5类线的10BASE-T以太网的最大传输距离是100 m。但听到有人说,他使用10BASE-T以太网传送数据的距离达到180 m。这可能吗? 问题3-20:粗缆以太网有一个单独的收发器。细缆以太网和双绞线以太网有没有收发器?如果有,都在什么地方? 问题3-21:什么叫“星形总线(star-shaped bus)”或“盒中总线(bus-in-a-box)”? 问题3-22:以太网的覆盖范围受限的一个原因是:如果站点之间的距离太大,那么由于信号传输时会衰减得很多因而无法对信号进行可靠的接收。试问:如果我们设法提高发送信号的功率,那么是否就可以提高以太网的通信距离? 问题3-23:一个大学能否就使用一个很大的局域网而不使用许多相互连接的较小的局域网? 问题3-24:一个10 Mb/s以太网若工作在全双工状态,那么其数据率是发送和接收各为5 Mb/s还是发送和接收各为10 Mb/s? 问题3-25:一个单个的以太网上所使用的网桥数目有没有上限? 问题3-26:当我们在PC机插上以太网的适配器(网卡)后,是否还必须编制以太网所需的MAC协议的程序? 问题3-27:使用网络分析软件可以分析出所捕获到的每一个帧的首部中各个字段的值。但是有时却无法找出LLC帧首部的各字段的值。这是什么原因? 问题3-28:整个的IEEE 802委员会现在一共有多少个工作组? 问题3-29:在一些文献和教材中,可以见到关于以太网的“前同步码”(preamble)有两种不同的说法。一种说法是:前同步码共8个字节。另一种说法是:前同步码共7个字节,而在前同步码后面还有一个字节的“帧开始定界符”SFD (Start-of-Frame Delimiter)。那么哪一种说法是正确的呢? 问题3-30:802.3标准共包含有多少种协议? 问题3-31:在802.3标准中有没有对人为干扰信号(jamming signal)制定出标准呢? 问题3-32:在以太网中,有没有可能在发送了512 bit(64 B)以后才发生碰撞? 问题3-33:在有的文献中会见到runt和jabber这两个名词,它们是什么意思? 问题3-34:当局域网刚刚问世时,总线形的以太网被认为可靠性比星形结构的网络好。但现在以太网又回到了星形结构,使用集线器作为交换结点。那么以前的看法是否有些不正确? 第4章 网络层 问题4-1:存在多种异构网络对不同网络之间的通信会造成一些麻烦。但为什么世界上还存在多种异构网络? 问题4-2:“IP网关”和“IP路由器”是否为同义语? 问题4-3:“互连网”和“互联网”有没有区别? 问题4-4:在文献中有时会见到对等连网(peer-to-peer networking),这是什么意思? 问题4-5:在一个互联网中,能否使用一个很大的交换机(switch)来代替互联网中很多的路由器? 问题4-6:为什么IP地址又称为“虚拟地址”? 问题4-7:有的文献上使用“虚拟分组”(virtual packet)这一名词。虚拟分组是什么意思? 问题4-8:如下图所示。五个网络用四个路由器(每一个路由器有两个端口)互连起来。能否改变这种连接方法,使用一个具有五个端口的路由器将这五个网络互连起来? 问题4-9:当运行PING 127.0.0.1时,这个IP数据报将发送给谁? 问题4-10:网络前缀是指网络号字段(net-id)中前面的几个类别位还是指整个的网络号字段? 问题4-11:有的书(如[COME06])将IP地址分为前缀和后缀两大部分,它们和网络号字段及主机号字段有什么关系? 问题4-12:IP地址中的前缀和后缀最大的不同是什么? 问题4-13:IP数据报中的数据部分的长度是可变的(即IP数据报不是定长的)。这样有什么好处? 问题4-14:IP地址中的各种类别的地址所拥有的地址数目的比例是怎样的? 问题4-15:在IP地址中,为什么使用最前面的一个或几个比特来表示地址的类别? 问题4-16:全1的IP地址是否是向整个因特网进行广播的一种地址? 问题4-17:IP协议有分片的功能,但广域网中的分组则不必分片。这是为什么? 问题4-18:路由表中只给出到目的网络的下一跳路由器的IP地址,然后在下一个路由器的路由表中再给出再下一跳的路由器的IP地址,最后才能到达目的网络进行直接交付。采用这样的方法有什么好处? 问题4-19:链路层广播和IP广播有何区别? 问题4-20:主机在接收一个广播帧或多播帧时其CPU所要的事情有何区别? 问题4-21:有的路由器在和广域网相连时,在该路由器的广域网接口处并没有硬件地址,这怎样解释? 问题4-22:IP地址和电话号码相比时有何异同之处? 问题4-23:“尽最大努力交付”(best effort delivery)都有哪些含义? 问题4-24:假定在一个局域网中计算机A发送ARP请求分组,希望找出计算机B的硬件地址。这时局域网上的所有计算机都能收到这个广播发送的ARP请求分组。试问这时由哪一个计算机使用ARP响应分组将计算机B的硬件地址告诉计算机A? 问题4-25:有人将ARP列入网络接口层,即认为ARP不在IP层,这样对吗? 问题4-26:一个主机要向另一个主机发送IP数据报。是否使用ARP就可以得到该目的主机的硬件地址,然后直接用这个硬件地址将IP数据报发送给目的主机? 问题4-27:在因特网中最常见的分组长度大约是多少个字节? 问题4-28:IP数据报的最大长度是多少个字节? 问题4-29:IP数据报的首部的最大长度是多少个字节?典型的IP数据报首部是多长? 问题4-30:IP数据报在传输的过程中,其首部长度是否会发生变化? 问题4-31:当路由器利用IP数据报首部中的“首部检验和”字段检测出在传输过程中出现了差错时,就简单地将其丢弃。为什么不发送一个ICMP报文给源主机呢? 问题4-32:RIP协议的好处是简单,但缺点是不够稳定。有的书上介绍“触发更新”、“分离范围”和“毒性逆转”。能否简单介绍一下它们的要点? 问题4-33:IP数据报必须考虑最大传送单元MTU (Maximum Transfer Unit)。这是指哪一层的最大传送单元?包括不包括首部或尾部等开销在内? 问题4-34:如果一个路由器要同时连接在一个以太网和一个ATM网络上,需要有什么样的硬件加到路由器上? 问题4-35:教材中的图4-19的B类网络145.13.0.0在划分子网时,所给出的三个子网号是怎样得出的? 问题4-36:“交换(switching)”的准确含义是什么? 问题4-37:为什么生存时间TTL原来用秒作为单位而现在TTL却表示数据报在网络中所能通过的路由器数的最大值? 第5章 运输层 问题5-1:TCP协议是面向连接的,但TCP使用的IP协议却是无连接的。这两种协议都有哪些主要的区别? 问题5-2:从通信的起点和终点来比较,TCP和IP的不同点是什么? 问题5-3:端口(port)和套接字(socket)的区别是什么? 问题5-4:一个套接字能否同时与远地的两个套接字相连? 问题5-5:数据链路层的HDLC协议和运输层的TCP协议都使用滑动窗口技术。从这方面来进行比较,数据链路层协议和运输层协议的主要区别是什么? 问题5-6:TCP协议能够实现可靠的端到端传输。在数据链路层和网络层的传输还有没有必要来保证可靠传输呢? 问题5-7:在TCP报文段的首部中只有端口号而没有IP地址。当TCP将其报文段交给IP层时,IP协议怎样知道目的IP地址呢? 问题5-8:在TCP传送数据时,有没有规定一个最大重传次数? 问题5-9:TCP都使用哪些计时器? 问题5-10:是否TCP和UDP都需要计算往返时间RTT? 问题5-11:假定TCP开始进行连接建立。当TCP发送第一个SYN报文段时,显然无法利用教材中5.6.3节所介绍的方法计算往返时间RTT。那么这时TCP又怎样设置重传计时器呢? 问题5-12:糊涂窗口综合症产生的条件是什么?是否只有在接收方才产生这种症状? 问题5-13:能否更详细些讨论一下糊涂窗口综合症及其解决方法? 问题5-14:为什么TCP在建立连接时不能每次都选择相同的、固定的初始序号? 问题5-15:能否利用TCP发送端和接收端交换报文段的图来说明慢开始的特点? 问题5-16:对于拥塞避免是否也能够用发送端和接收端交换的报文段来说明其工作原理? 问题5-17:TCP连接很像一条连接发送端和接收端的双向管道。当TCP在连续发送报文段时,若要管道得到充分的利用,则发送窗口的大小应怎样选择? 问题5-18:假定在一个互联网中,所有的链路的传输都不出现差错,所有的结点也都不会发生故障。试问这种情况下,TCP的“可靠交付”的功能是否就是多余的? 问题5-19:TCP是通信协议还是软件? 问题5-20:在计算TCP的往返时间RTT的公式中,本教材过去的版本是取 = 7/8。但现在的新版本是取 = 1/8。为什么会有这样大的改变? 第6章 应用层 问题6-1:我们经常说“两个计算机进行通信”。我们应当怎样理解这句话? 问题6-2:能否用你的PC机进行一个简单的实验:一个计算机同时和5个计算机进行通信? 问题6-3:因特网中计算机程序之间的通信和电信网中的电话通信有何相同或不同之处? 问题6-4:连接在因特网上的主机名必须是唯一的吗? 问题6-5:在因特网中通过域名系统查找某个主机的IP地址,和在电话系统中通过114查号台查找某个单位的电话号码相比,有何异同之处? 问题6-6:一个单位的DNS服务器可以采用集中式的一个DNS服务器,也可以采用分布式的多个DNS服务器。哪一种方案更好些? 问题6-7:对同一个域名向DNS服务器发出好几次的DNS请求报文后,每一次得到IP地址都不一样。这可能吗? 问题6-8:当使用56 kb/s的调制解调器上网时,经常会发现数据下载的速率远远小于56 kb/s。这是什么原因? 问题6-9:ARP和DNS是否有些相似?它们有何区别? 问题6-10:“网关”和“路由器”是否为同义语? 问题6-11:我们常在文献上看到“远程登录”这样的名词。它的英文名字应当是remote log-in还是Telnet? 问题6-12:电话通信和电子邮件通信是使用客户服务器工作方式吗? 问题6-13:在电子邮件中,“信封”、“内容”、“首部”、“主体”是个什么样的关系? 问题6-14:能否更加细致地介绍一下base64编码? 问题6-15:能否归纳一下HTTP协议的主要特点? 问题6-16:HTTP 1.1协议比起HTTP 1.0协议有哪些主要的变化? 问题6-17:抽象语法、传送语法的主要区别是什么?数据类型、编码以及编码规则的区别又是什么? 第7章 计算机网络的安全 问题7-1:用一个例子说明置换密码的加密和解密过程。假定密钥为CIPHER,而明文为attack begins at four,加密时明文中的空格去除。 问题7-2:拒绝服务DOS (Denial Of Service)和分布式拒绝服务DDOS (Distributed DOS)这两种攻击是怎样产生的? 问题7-3:报文的保密性和报文的完整性有何不同?保密性和完整性能否只要其中的一个而不要另一个? 问题7-4:常规密钥体制与公钥体制最主要的区别是什么? 问题7-5:能否举一个实际的RSA加密和解密的例子? 问题7-6:要进一步理解RSA密码体制的原理,需要知道哪一些数论的基本知识? 问题7-7:怎样证明RSA密码体制的解码公式? 问题7-8:RSA加密能否被认为是保证安全的? 问题7-9:报文摘要并不对传送的报文进行加密。这怎么能算是一种网络安全的措施?不管在什么情况下永远将报文进行加密不是更好一些吗? 问题7-10:不重数(nonce)是否就是随机数? 问题7-11:在防火墙技术中的分组过滤器工作在哪一个层次? 第8章 因特网上的音频/视频服务 问题8-1:为什么说传统的因特网本身是非等时的? 问题8-2:IP协议是不保证服务质量的。可是因特网的成功可以说在很大的程度上得益于IP协议。那么IP协议最主要的优点是什么? 问题8-3:端到端时延(end-to-end delay)和时延抖动(delay jitter)有什么区别? 问题8-4:能否简单归纳一下,为了适应多媒体信息的传输,目前对因特网应如何演进,都有哪三种主要观点? 问题8-5:在教材第8章的图8-2中的缓存(其作用是将非恒定速率的分组变为恒定速率的分组)是否就是在运输层中的接收缓存? 问题8-6:假定在教材第8章图8-19中对应于三种分组流的权重分别为0.5,0.25和0.25,并且所有的分组流都有大量分组在缓存中。试问这三种分组流被服务的顺序可能是怎样的(对于轮流服务的情况,被服务的顺序是1 2 3 1 2 3 1 2 3…)? 问题8-7:假定在问题8-6中,只有第一类和第二类分组流有大量分组在缓存中,而第三类分组流目前暂时没有分组在缓存中。试问这三种分组流被服务的顺序可能是怎样的? 第9章 无线网络(略) 第10章 下一代因特网 问题10-1:本章叫“下一代因特网”。这是否意味着前面几章讨论的因特网协议都属于传统的因特网,而只有本章讨论的内容才涉及到因特网的一些新的演进? 问题10-2:三网融合是目的吗? 有关广域网WAN的问题 问题WAN-1:广域网在地理上覆盖的范围较大,那么能不能说“凡是在地理上覆盖范围较大的网络就是广域网”? 问题WAN-2:在广域网中的结点交换机是否就是路由器? 问题WAN-3:为什么在第5版的《计算机网络》取消了“广域网”这一章? 问题WAN-4:为什么ATM信元的有效载荷规定为48字节? 问题WAN-5:异步传递方式ATM和同步传输有什么关系? 问题WAN-6:是否SDH/SONET只能为ATM使用? 问题WAN-7:在ATM中发送端或接收端的传输汇聚子层TC能否辨认出不同的虚通路VC? 问题WAN-8:按照分层原理,下层不检查上层协议数据单元PDU的首部。在ATM中,在传输汇聚子层TC上面的是ATM层。那么TC子层是否也不检查ATM信元的首部?
第1章 概述 问题1-1:“主机”和“计算机”一样不一样? 问题1-2:能否说:“电路交换和面向连接是等同的,而分组交换和无连接是等同的”? 问题1-3:因特网使用的IP协议是无连接的,因此其传输是不可靠的。这样容易使人们感到因特网很不可靠。那么为什么当初不把因特网的传输设计成为可靠的?在教材中1.2.1节提到这种新型计算机网络必须满足的要求有一条是“能够非常可靠地传送数据”。但因特网的网络层使用IP协议,它只能提供不可靠的数据传输。那么这里有没有什么矛盾? 问题1-4:在具有五层协议的体系结构中,如果下面的一层使用面向连接服务或无连接服务,那么在上面的一层是否也必须使用同样性质的服务呢?或者说,是否我们可以在各层任意使用面向连接服务或无连接服务呢? 问题1-5:在运输层应根据什么原则来确定应当使用面向连接服务还是无连接服务? 问题1-6:在数据链路层应根据什么原则来确定应当使用面向连接服务还是无连接服务? 问题1-7:TCP/IP的体系结构到底是四层还是五层? 问题1-8:我们常说“分组交换”。但又常说“路由器转发IP数据报”或“路由器转发帧”。究竟“分组”一词应当用在什么场合? 问题1-9:到商店购买可一个希捷公司生产的80 G的硬盘。安装到电脑上以后用WINDOWS的资源管理器发现在该磁盘的“属性”中只有74.5 G。是不是商店出了差错? 问题1-10:在教材的1.4.1节中有这样一段话:人们愿意将“带宽”作为数字信道的“数据率”的同义语。这样说有何根据? 问题1-11:有时可听到人们将“带宽为10 Mb/s的以太网”说成是“速率(或速度)为10 Mb/s的以太网”或“10兆速率(或速度)的以太网”。试问这样的说法正确否? 问题1-12:有人说,宽带信道相当于高速公路车道数目增多了,可以同时并行地跑更多数量的汽车。虽然汽车的时速并没有提高(这相当于比特在信道上的传播速率没有提高),但整个高速公路的运输能力却增多了,相当于能够传送更多数量的比特。这种比喻合适否? 问题1-13:如果用时延带宽积管道来比作传输链路,那么是否宽带链路对应的时延带宽积管道就比较宽呢? 问题1-14:网络的吞吐量与网络的时延有何关系? 问题1-15:什么是“无缝的”、“透明的”和“虚拟的”? 问题1-16:在教材的1.5.2节提到协议有三个要素,即语法、语义和同步。语义是否已经包括了同步的意思? 问题1-17:为什么协议不能设计成100%可靠的? 问题1-18:什么是因特网的穆尔定律? 问题1-19:局域网、广域网和公用网、专用网有什么关系? 问题1-20:信道的利用率是否越高越好? 问题1-21:怎样理解教材中图1-8所示的椭圆形表示的各种服务提供者?这些ISP都在具体的什么位置? 问题1-22:在计算机网络中的结点是指主机还是指路由器? 问题1-23:ISO与OSI有何不同? 问题1-24:我们常听说“要增加政府机构办事的透明度”。意思是:政府机关的许多办事程序和步骤应当向群众公开,让大家看得见。而计算机网络所讨论的透明传输,是指比特流看不见电路的存在。这样看来,两种“透明”的意思很不一样。应当怎样理解? 问题1-25:怎样才能知道哪些RFC文档已经成为因特网的正式标准(草案或建议标准)? 问题1-26:怎样知道一个RFC文档是否被改为陈旧的? 第2章 物理层 问题2-1:“规程”、“协议”和 “规约”都有何区别? 问题2-2:在许多文献中经常见到人们将“模拟”与“仿真”作为同义语。那么,“模拟信道”能否说成是“仿真信道”? 问题2-3:为什么电话信道的标准带宽是3.1 kHz? 问题2-4:奈氏准则和香农公式的主要区别是什么?这两个公式对数据通信的意义是什么? 问题2-5:传输媒体是物理层吗?传输媒体和物理层的主要区别是什么? 问题2-6:同步(synchronous)和异步(asynchronous)的区别是什么? 问题2-7:同步通信和异步通信的区别是什么? 问题2-8:比特同步和帧同步的区别是什么? 问题2-9:教材的表2-4的OC和STS有什么区别?例如OC-3和STS-3的数据率是一样的,为什么要使用两种表示方法?有的文献还使用如OC-3C的表示方法,这有区别吗? 问题2-10:ATM是异步传递方式。是否ATM方式与同步通信完全无关? 第3章 数据链路层 问题3-1:在1999年4月出版的《计算机网络》(第2版)的1.3.2节中有这样的话: “(2) 数据链路层 数据链路层的任务是在两个相邻结点间的线路上无差错地传送以帧(frame)为单位的数据。……这样,数据链路层就把一条有可能出差错的实际链路,转变成为让网络层向下看起来好像是一条不出差错的链路。” 但在2003年出版的《计算机网络》(第4版)中对数据链路层就改变了这种提法。在1.5.3节中有这样的话: “控制信息还使接收端能够检测到所收到的帧中有无差错。如发现有差错,数据链路层就丢弃这个出了差错的帧,然后采取下面两种方法之一:或者不作任何其他的处理;或者由数据链路层通知对方重传这一帧,直到正确无误地收到此帧为止。” 可见,如果选择前一种方法,即不作任何其他的处理,那么数据链路层的传输就不能“让网络层向下看起来好像是一条不出差错的链路。” 现在的问题是:到底哪一种说法是正确的? 问题3-2:当数据链路层使用PPP协议或CSMA/CD协议时,既然不保证可靠传输,那么为什么对所传输的帧进行差错检验呢? 问题3-3:既然现在因特网使用得最多的数据链路层协议并不保证可靠传输,那么为什么我们在数据链路层一章中还要讲授保证可靠传输的停止等待协议呢? 问题3-4:通过普通的电话用户线拨号上网时(使用调制解调器),试问一对用户线可容许多少个用户同时上网? 问题3-5:除了差错检测外,面向字符的数据链路层协议还必须解决哪些特殊的问题? 问题3-6:为什么计算机进行通信时发送缓存和接收缓存总是需要的? 问题3-7:在教材中的3.3.3节提到“发送窗口用来对发送端进行流量控制”。但在发送窗口和接收窗口的共同作用下可以在数据传输时提高对信道的利用率。那么到底应当怎样看待发送窗口的作用? 问题3-8:在关于数据链路层工作原理的叙述中,经常会见到两个不同的名词——“丢失”和“丢弃”。它们有区别吗? 问题3-9:停止等待协议中的确认帧如果没有序号会出现什么问题? 问题3-10:在停止等待协议中,A发送的数据帧有差错,被B的CRC检验器静悄悄地丢弃了。如果A进行超时重传后,但又连续出错,重传的数据帧又被B的CRC检验器丢弃。这样,B总是收不到A发送的数据帧。这种情况是否说明停止等待协议这时不能正常工作? 问题3-11:在连续ARQ协议中,如果A向B发送数据帧而B只向A发送确认帧(即假定B没有数据帧向A发送),那么这两种帧的序号序列各有什么特点? 问题3-12:在连续ARQ协议中,如果B收到A发送的数据帧的序号没有落在B的接收窗口中,B就应当丢弃这个序号不对的帧。如果B这时不向A发送任何信息而一直静悄悄地等待正确序号的数据帧的到来,那么这种策略是否可行? 问题3-13:在问题3-12中,如果B发送的确认帧在传输过程中总是出错,那么A也是一直重复发送DATA0到DATA6这7个数据帧。在这种情况下,连续ARQ协议还正确吗? 问题3-14:能否归纳一下连续ARQ协议都有哪些主要功能和特别要注意的地方? 问题3-15:在许多有关网络技术的书籍或文献中,经常会看到“应答”、“回答”、“响应”和“确认”等术语。这些术语的意思都一样吗? 问题3-16:连续ARQ协议中的图3-6在第2次印刷时改变了。为什么要进行这样的改变? 问题3-17:接收端对收到的帧进行CRC检验后,若发现有差错就丢弃这个帧。是用户(人)下命令丢弃,还是高层软件下命令丢弃? 问题3-18:在[MINGCI94]中,flow control的标准译名是“流控制”。为什么我们的教材不使用这个译名,而使用“流量控制”这样的译名? 第4章 局域网 问题4-1:以太网使用载波监听多点接入碰撞检测协议CSMA/CD。频分复用FDM才使用载波。以太网有没有使用频分复用? 问题4-2:在以太网中,不同的传输媒体会产生不同的传播时延吗? 问题4-3:在以太网中发生了碰撞是否说明这时出现了某种故障? 问题4-4:从什么地方可以查阅到以太网帧格式中的“类型”字段是怎样分配的? 问题4-5:是什么原因使以太网有一个最小帧长和最大帧长? 问题4-6:在双绞线以太网中,其连接导线只需要两对线:一对线用于发送,另一对线用于接收。但现在的标准是使用RJ-45连接器。这种连接器有8根针脚,一共可连接4对线。这是否有些浪费?是否可以不使用RJ-45而使用RJ-11? 问题4-7:RJ-45连接器对8根针脚的编号有什么规定? 问题4-8:剥开5类线的外塑料保护套管就可以看见不同颜色的4对双绞线。哪一根线应当连接到哪一个针脚呢? 问题4-9:将5类线电缆与RJ-45插头连接起来的具体操作步骤是怎样的? 问题4-10:不用集线器或以太网交换机,能否将两台计算机用带有RJ-45插头的5类线电缆直接连接起来? 问题4-11:使用屏蔽双绞线电缆STP安装以太网是否可获得更好的效果? 问题4-12:如果将已有的10 Mb/s以太网升级到100 Mb/s,试问原来使用的连接导线是否还能继续使用? 问题4-13:使用5类线的10BASE-T以太网的最大传输距离是100 m。但听到有人说,他使用10BASE-T以太网传送数据的距离达到180 m。这可能吗? 问题4-14:粗缆以太网有一个单独的收发器。细缆以太网和双绞线以太网有没有收发器?如果有,都在什么地方? 问题4-15:什么叫“星形总线(star-shaped bus)”或“盒中总线(bus-in-a-box)”? 问题4-16:以太网的覆盖范围受限的一个原因是:如果站点之间的距离太大,那么由于信号传输时会衰减得很多因而无法对信号进行可靠的接收。试问:如果我们设法提高发送信号的功率,那么是否就可以提高以太网的通信距离? 问题4-17:一个大学能否就使用一个很大的局域网而不使用许多相互连接的较小的局域网? 问题4-18:一个10 Mb/s以太网若工作在全双工状态,那么其数据率是发送和接收各为5 Mb/s还是发送和接收各为10 Mb/s? 问题4-19:一个单个的以太网上所使用的网桥数目有没有上限? 问题4-20:当我们在PC机插上以太网的网卡后,是否还必须编制以太网所需的MAC协议的程序? 问题4-21:使用网络分析软件可以分析出所捕获到的每一个帧的首部中各个字段的值。但是有时却无法找出LLC帧首部的各字段的值。这是什么原因? 问题4-22:整个的IEEE 802委员会现在一共有多少个工作组? 问题4-23:在一些文献和教材中,可以见到关于以太网的“前同步码”(preamble)有两种不同的说法。一种说法是:前同步码共8个字节。另一种说法是:前同步码共7个字节,而在前同步码后面还有一个字节的“帧开始定界符”SFD (Start-of-Frame Delimiter)。那么哪一种说法是正确的呢? 问题4-24:802.3标准共包含有多少种协议? 问题4-25:在802.3标准中有没有对人为干扰信号(jamming signal)制定出标准呢? 问题4-26:在以太网中,有没有可能在发送了512 bit(64 B)以后才发生碰撞? 问题4-27:在有的文献中会见到runt和jabber这两个名词,它们是什么意思? 问题4-28:当局域网刚刚问世时,总线形的以太网被认为可靠性比星形结构的网络好。但现在以太网又回到了星形结构,使用集线器作为交换结点。那么以前的看法是否有些不正确? 问题4-29:什么是10 Mb/s以太网的5-4-3规则? 第5章 广域网 问题5-1:广域网在地理上覆盖的范围较大,那么能不能说“凡是在地理上覆盖范围较大的网络就是广域网”? 问题5-2:在广域网中的结点交换机是否就是路由器? 问题5-3:为什么路由选择功能不放在第5章广域网中详细讨论,而是推后到第6章(网络互连)才深入讨论? 问题5-4:为什么ATM信元的有效载荷规定为48字节? 问题5-5:异步传递方式ATM和同步传输有什么关系? 问题5-6:是否SDH/SONET只能为ATM使用? 问题5-7:在ATM中发送端或接收端的传输汇聚子层TC能否辨认出不同的虚通路VC? 问题5-8:按照分层原理,下层不检查上层协议数据单元PDU的首部。在ATM中,在传输汇聚子层TC上面的是ATM层。那么TC子层是否也不检查ATM信元的首部? 问题5-9:ATM使用的是面向连接的分组交换技术(采用定长分组——信元)。那么,ATM是否提供了可靠交付的服务呢? 问题5-10:ATM在刚刚问世时,曾被各界寄予了很大的希望。不少人认为ATM将是未来宽带网的重要基石。但很多年已经过去了,ATM始终不能成为宽带网的核心技术。那么对ATM的批评主要有哪些? 问题5-11:“不可靠的交付”(unreliable delivery)和“尽最大努力交付”(best effort delivery)是一样的意思吗? 第6章 网络互连 问题6-1:存在多种异构网络对不同网络之间的通信会造成一些麻烦。但为什么世界上还存在多种异构网络? 问题6-2:“IP网关”和“IP路由器”是否为同义语? 问题6-3:“互连网”和“互联网”有没有区别? 问题6-4:在文献中有时会见到对等连网(peer-to-peer networking),这是什么意思? 问题6-5:在一个互连网中,能否使用一个很大的交换机(switch)来代替互连网中很多的路由器? 问题6-6:为什么IP地址又称为“虚拟地址”? 问题6-7:有的文献上使用“虚拟分组”(virtual packet)这一名词。虚拟分组是什么意思? 问题6-8:如下图所示。五个网络用四个路由器(每一个路由器有两个端口)互连起来。能否改变这种连接方法,使用一个具有五个端口的路由器将这五个网络互连起来? 问题6-9:当运行PING 127.0.0.1时,这个IP数据报将发送给谁? 问题6-10:网络前缀是指网络号字段(net-id)中前面的几个类别比特还是指整个的网络号字段? 问题6-11:有的书(如[COME01])将IP地址分为前缀和后缀两大部分,它们和网络号字段及主机号字段有什么关系? 问题6-12:IP地址中的前缀和后缀最大的不同是什么? 问题6-13:IP数据报中的数据部分的长度是可变的(即IP数据报不是定长的)。这样有什么好处? 问题6-14:IP地址中的各种类别的地址所拥有的地址数目的比例是怎样的? 问题6-15:在IP地址中,为什么使用最前面的一个或几个比特来表示地址的类别? 问题6-16:全1的IP地址是否是向整个因特网进行广播的一种地址? 问题6-17:IP协议有分片的功能,但广域网中的分组则不必分片。这是为什么? 问题6-18:路由表中只给出到目的网络的下一跳路由器的IP地址,然后在下一个路由器的路由表中再给出再下一跳的路由器的IP地址,最后才能到达目的网络进行直接交付。采用这样的方法有什么好处? 问题6-19:链路层广播和IP广播有何区别? 问题6-20:主机在接收一个广播帧或多播帧时其CPU所要的事情有何区别? 问题6-21:有的路由器在和广域网相连时,在该路由器的广域网接口处并没有硬件地址,这怎样解释? 问题6-22:IP地址和电话号码相比时有何异同之处? 问题6-23:“尽最大努力交付”(best effort delivery)都有哪些含义? 问题6-24:假定在一个局域网中计算机A发送ARP请求分组,希望找出计算机B的硬件地址。这时局域网上的所有计算机都能收到这个广播发送的ARP请求分组。试问这时由哪一个计算机使用ARP响应分组将计算机B的硬件地址告诉计算机A? 问题6-25:有人将ARP列入网络接口层,即认为ARP不在IP层,这样对吗? 问题6-26:一个主机要向另一个主机发送IP数据报。是否使用ARP就可以得到该目的主机的硬件地址,然后直接用这个硬件地址将IP数据报发送给目的主机? 问题6-27:在因特网中最常见的分组长度大约是多少个字节? 问题6-28:IP数据报的最大长度是多少个字节? 问题6-29:IP数据报的首部的最大长度是多少个字节?典型的IP数据报首部是多长? 问题6-30:IP数据报在传输的过程中,其首部长度是否会发生变化? 问题6-31:当路由器利用IP数据报首部中的“首部检验和”字段检测出在传输过程中出现了差错时,就简单地将其丢弃。为什么不发送一个ICMP报文给源主机呢? 问题6-32:RIP协议的好处是简单,但缺点是不够稳定。有的书上介绍“触发更新”、“分离范围”和“毒性逆转”。能否简单介绍一下它们的要点? 问题6-33:IP数据报必须考虑最大传送单元MTU (Maximum Transfer Unit)。这是指哪一层的最大传送单元?包括不包括首部或尾部等开销在内? 问题6-34:如果一个路由器要同时连接在一个以太网和一个ATM网络上,需要有什么样的硬件加到路由器上? 问题6-35:教材中的图6-19的B类网络145.13.0.0在划分子网时,所给出的三个子网号是怎样得出的? 问题6-36:“交换(switching)”的准确含义是什么? 问题6-37:路由器到底有没有运输层?如果有,似乎就和“运输层只存在与分组交换网外面的主机中”相矛盾。如果没有,那么路由选择协议RIP又怎样能够使用UDP来传送呢? 第7章 运输层 问题7-1:TCP协议是面向连接的,但TCP使用的IP协议却是无连接的。这两种协议都有哪些主要的区别? 问题7-2:从通信的起点和终点来比较,TCP和IP的不同点是什么? 问题7-3:端口(port)和插口(socket)的区别是什么? 问题7-4:一个插口能否同时与远地的两个插口相连? 问题7-5:数据链路层的HDLC协议和运输层的TCP协议都使用滑动窗口技术。从这方面来进行比较,数据链路层协议和运输层协议的主要区别是什么? 问题7-6:TCP协议能够实现可靠的端到端传输。在数据链路层和网络层的传输还有没有必要来保证可靠传输呢? 问题7-7:在TCP报文段的首部中只有端口号而没有IP地址。当TCP将其报文段交给IP层时,IP协议怎样知道目的IP地址呢? 问题7-8:在TCP传送数据时,有没有规定一个最大重传次数? 问题7-9:TCP都使用哪些计时器? 问题7-10:是否TCP和UDP都需要计算往返时延RTT? 问题7-11:假定TCP开始进行连接建立。当TCP发送第一个SYN报文段时,显然无法利用教材中7.4.5节所介绍的方法计算往返时延RTT。那么这时TCP又怎样设置重传计时器呢? 问题7-12:糊涂窗口综合症产生的条件是什么?是否只有在接收方才产生这种症状? 问题7-13:能否更详细些讨论一下糊涂窗口综合症及其解决方法? 问题7-14:为什么TCP在建立连接时不能每次都选择相同的、固定的初始序号? 问题7-15:能否利用TCP发送端和接收端交换报文段的图来说明慢开始的特点? 问题7-16:对于拥塞避免是否也能够用发送端和接收端交换的报文段来说明其工作原理? 问题7-17:TCP连接很像一条连接发送端和接收端的双向管道。当TCP在连续发送报文段时,若要管道得到充分的利用,则发送窗口的大小应怎样选择? 问题7-18:假定在一个互连网中,所有的链路的传输都不出现差错,所有的结点也都不会发生故障。试问这种情况下,TCP的“可靠交付”的功能是否就是多余的? 问题7-19:进行TCP通信的一方收到了确认号为4001的报文段。这是否表示对方已经收到了4000个字节的数据,而期望接收编号为4001的数据字节?还是否表示对方已经收到了4001个字节的数据,而期望接收编号为4001的数据字节? 问题7-20:在7.4.7节的注释①中提到的“三次握手”(three-way handshake)的译名不太准确,那么有没有这个术语的标准译名呢?? 问题7-21:有的资料上把TCP连接说成是“虚连接”。这样说正确吗? 问题7-22:教材中说运输层的熟知端口号可以在[RFC 1700]中查找到。但有的资料却说应当在网上查找。究竟哪种说法正确? 问题7-23:在TCP报文段中,如果是没有数据的确认报文段,其序号字段应当填入什么号码? 第8章 应用层 问题8-1:我们经常说“两个计算机进行通信”。我们应当怎样理解这句话? 问题8-2:能否用你的PC机进行一个简单的实验:一个计算机同时和5个计算机进行通信? 问题8-3:因特网中计算机程序之间的通信和电信网中的电话通信有何相同或不同之处? 问题8-4:连接在因特网上的主机名必须是惟一的吗? 问题8-5:在因特网中通过域名系统查找某个主机的IP地址,和在电话系统中通过114查号台查找某个单位的电话号码相比,有何异同之处? 问题8-6:一个单位的DNS服务器可以采用集中式的一个DNS服务器,也可以采用分布式的多个DNS服务器。哪一种方案更好些? 问题8-7:对同一个域名向DNS服务器发出好几次的DNS请求报文后,每一次得到IP地址都不一样。这可能吗? 问题8-8:当使用56 kb/s的调制解调器上网时,经常会发现数据下载的速率远远小于56 kb/s。这是什么原因? 问题8-9:ARP和DNS是否有些相似?它们有何区别? 问题8-10:“网关”和“路由器”是否为同义语? 问题8-11:我们常在文献上看到“远程登录”这样的名词。它的英文名字应当是remote log-in还是Telnet? 问题8-12:电话通信和电子邮件通信是使用客户服务器工作方式吗? 问题8-13:在电子邮件中,“信封”、“内容”、“首部”、“主体”是个什么样的关系? 问题8-14:能否更加细致地介绍一下base64编码? 问题8-15:能否归纳一下HTTP协议的主要特点? 问题8-16:HTTP 1.1协议比起HTTP 1.0协议有哪些主要的变化? 问题8-17:抽象语法、传送语法的主要区别是什么?数据类型、编码以及编码规则的区别又是什么? 问题8-18:为什么SNMP还必须有SMI和MIB两个构件才能工作? 问题8-19:SNMP现已发展到第三个版本SNMPv3。是否前两个版本SNMPv1和SNMPv2现在已经不使用了呢? 第9章 计算机网络的安全 问题9-1:请仔细说明本教材中置换密码的例子的加密和解密过程(密钥为CIPHER,而明文为attack begins at four,加密时明文中的空格去除)。 问题9-2:拒绝服务DOS (Denial Of Service)和分布式拒绝服务DDOS (Distributed DOS)这两种攻击是怎样产生的? 问题9-3:报文的保密性和报文的完整性有何不同?保密性和完整性能否只要其中的一个而不要另一个? 问题9-4:常规密钥体制与公开密钥体制最主要的区别是什么? 问题9-5:能否举一个实际的RSA加密和解密的例子? 问题9-6:要进一步理解RSA密码体制的原理,需要知道哪一些数论的基本知识? 问题9-7:怎样证明第9章中RSA密码体制的解码公式(9-8)? 问题9-8:RSA加密能否被认为是保证安全的? 问题9-9:报文摘要并不对传送的报文进行加密。这怎么能算是一种网络安全的措施?不管在什么情况下永远将报文进行加密不是更好一些吗? 问题9-10:在防火墙技术中的分组过滤器工作在哪一个层次? 第10章 因特网的演进 问题10-1:本章叫“因特网的演进”。这是否意味着前面几章讨论的因特网协议都不存在因特网演进的问题,而只有本章讨论的内容才属于“因特网的演进”的范围? 问题10-2:为什么说传统的因特网本身是非等时的? 问题10-3:IP协议是不保证服务质量的。可是因特网的成功可以说在很大的程度上得益于IP协议。那么IP协议最主要的优点是什么? 问题10-4:端到端时延(end-to-end delay)和时延抖动(delay jitter)有什么区别? 问题10-5:能否简单归纳一下,为了适应多媒体信息的传输,目前对因特网应如何演进,都有哪三种主要观点? 问题10-6:在教材第10章的图10-2中的缓存(其作用是将非恒定速率的分组变为恒定速率的分组)是否就是在运输层中的接收缓存? 问题10-7:假定在教材第10章图10-14中对应于三种分组流的权重分别为0.5,0.25和0.25,并且所有的分组流都有大量分组在缓存中。试问这三种分组流被服务的顺序可能是怎样的(对于轮流服务的情况,被服务的顺序是1 2 3 1 2 3 1 2 3…)? 问题10-8:假定在问题10-7中,只有第一类和第二类分组流有大量分组在缓存中,而第三类分组流目前暂时没有分组在缓存中。试问这三种分组流被服务的顺序可能是怎样的? 问题10-9:三网融合是目的吗?
内容简介   本书从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。书中不仅关注代码本身,同时关注完成这些代码的思路和过程。本书不同于其他的理论型书籍,而是提供给读者一个动手实践的路线图。读者可以根据路线图逐步完成各部分的功能,从而避免了一开始就面对整个操作系统数万行代码时的迷茫和挫败感。书中讲解了大量在开发操作系统中需注意的细节问题,这些细节不仅能使读者更深刻地认识操作系统的核心原理,而且使整个开发过程少走弯路。本书分上下两篇,共11章。其中每一章都以前一章的工作成果为基础,实现一项新的功能。而在章的内部,一项大的功能被分解成许多小的步骤,通过完成每个小的步骤,读者可以不断获得阶段性的成果,从而让整个开发过程变得轻松并且有趣。   本书适合各类程序员、程序开发爱好者阅读,也可作为高等院校操作系统课程的实践参考书。 序   真正 Hacker的乐趣──自己动手去实践   2004年我听编辑说有个年轻人写了本《自己动手写操作系统》,第一反应是不可能,恐怕是翻译稿,写这种书籍是要考作者硬功夫的,不但需要深入掌握操作系统的原理,还需要实际动手写出原型。   历史上的 Linux就是这么产生的,Linus Torvalds当时是一名赫尔辛基大学计算机科学系的二年级学生,经常要用自己的电脑去访问大学主机上的新闻组和邮件,为了方便读写和下载文件,他自己编写了磁盘驱动程序和文件系统,这成为了 Linux第一个内核的雏形。   我想中国有能力写出内核原型的程序员应该也有,但把这个题目写成一本书,感觉上不会有人愿意这件事情,作者要花很多时间,加上主题比较硬,销售量不会太高,经济上回报有限。   但拿来文稿一看,整个编辑部大为惊艳,内容文笔俱佳,而且绝对原创,马上决定在《程序员》连载。2005年博文视点出版的第一版也广受好评。   不过有很多读者还是质疑:现在软件编程主要领域是框架和应用,还需要了解操作系统底层吗?   经过四年的磨练成长,于渊又拿出第二版的书稿《Orange'S:一个操作系统的实现》,这本书是属于真正 Hacker的。我虽然已经有多年不写代码了,但看这本书的时候,让我又重新感受到程序员的乐趣:用代码建设属于自己的系统,让电脑听从自己的指令,对系统的每个部分都了如指掌。   黑客(hacker)实际是褒义词,维基百科的解释是喜欢用智力通过创造性方法来挑战脑力极限的人,特别是他们所感兴趣的领域,例如软件编程或电气工程。个人电脑、软件和互联网等划时代的产品都是黑客创造出来的,如苹果的 Apple电脑、微软的 Basic解释器、互联网的 Mosaic浏览器。   回答前面读者的质疑,学软件编程并不需要看这本书,想成为优秀程序员和黑客的朋友,我强烈建议你花时间来阅读这本书,并亲自动手实践。正如于渊在本书结尾中所说“我们写自己的操作系统是出于一种好奇,或者说一种求知欲。我希望这样不停地‘过把瘾’能让这种好奇不停地延续”。   好奇心是动力的源泉,追究问题的本质是优秀黑客的必备素质,只有充分掌握了系统原理,才能在技术上游刃有余,才能有真正的创新和发展。中国需要更多真正的黑客,也希望更多的程序员能享受属于黑客的创造乐趣。   蒋涛   2009年 4月 作者自序   本书是《自己动手写操作系统》的第二版,通过一个具体的实例向读者呈现一个操作系统雏形的实现过程。有关操作系统的书籍资料可以找到很多,但是关注如何帮助读者实现一个试验性操作系统的书籍却不多见,本书便是从一个简单的引导扇区开始,讲述一个操作系统成长的故事,以作读者参考之用。   本书面向实践,通过具体实例教读者开发自己的操作系统。书中的步骤遵循由小到大、由浅入深的顺序,跟随这些步骤,读者可以由一个最简单的引导扇区开始,逐渐完善代码,扩充功能,最后形成一个小的操作系统。   本书不仅介绍操作系统的各要素,同时涉及开发操作系统需要的各个方面,比如如何建立开发环境、如何调试以及如何在虚拟机中运行等。书中的实例操作系统采用IA32作为默认平台,所以保护模式也作为必备知识储备收入书中,而这是传统的操作系统实践书籍经常忽略的。总之,只要是开发自己的操作系统中需要的知识,书中都尽量涉及,以便于读者参考。   众所周知,一个成型的操作系统往往非常复杂。如果考虑到操作系统作为软硬件桥梁的特殊地位,那么它可能看上去比一般的软件系统更难理解,因为其核心部分往往包含许多直接针对CPU、内存和 I/O端口的操作,它们夹杂在一片代码汪洋之中,显得更加晦涩。   我们有许多源代码公开的操作系统,可供随时下载和阅读,看上去好像让实现一个供自己把玩的微型操作系统变得容易很多,但事实往往不尽人意,因为这些代码动辄上万甚至几十几百万行,而且细节之间经常互相关联,要理解它们着实不易。我们有许多容易得到的操作系统教程,但读来好像总觉得跟我们有隔膜,不亲近。造成这些的根本原因,在于学习者一开始就面对一个完整的操作系统,或者面对前辈们积累了几十年的一系列理论成果。而无论作者多么擅长写作,读者多么聪明,或者代码多么优秀,要一个初学者理清其中的头绪都将是非常困难的。   我并非在此危言耸听,因为这曾经是我的亲身体会。当然,如果只是为了考试,几本操作系统理论书籍就足够了,你不需要对细节那么清楚。但如果是出于兴趣呢?如果你是想编写自己的操作系统呢?你会发现理论书籍好像一下子变得无用武之地,你会发现任何一个细节上的理解错误都可能导致自己辛辛苦苦编写的代码运行异常甚至崩溃。   我经历过这一切!我曾经翻遍了一本《操作系统:设计与实现》,也没有找到实现一个操作系统应该从何处着手。并不是这些书不好,也不是前人的代码不优秀,而是作为一无所知的初学者,我们所不了解的不仅是高居庙堂的理论知识,还有让我们举步维艰的实践细节。   可能在这些教科书作者的眼里,操作的细节不属于课程的一部分,或者这些细节看上去太容易,根本不值一提,甚至作者认为这些属于所谓“经验”的一部分,约定俗成是由读者本人去摸索的。但是实际情况往往是,这些书中忽略掉的内容恰恰占去了一个初学者大部分的时间,甚至影响了学习的热情。   我至今仍记得当我开始编写自己的操作系统时所遭受的挫败感,那是一种不知道如何着手的无助的感觉。还好我坚持了下来,克服了各种困难,并完成了自己的操作系统雏形。   进而我想到,一定不只是我一个人对编写自己的操作系统怀有兴趣,也一定不只是我一个人在实践时遇到困难。或许我应该把自己的经历写下来,从而可以帮助跟我相似的后来者,就这样,我编写了本书的第一版,也就是《自己动手写操作系统》。我相信,如果你也对神奇的计算机世界充满好奇,并且希望通过自己编写操作系统的方式来了解背后发生的故事,那么你一定可以在这本书中得到一些帮助。而假如你真的因为我的书而重新燃起实践的热情,从而开始一段操作系统旅程,我将会感到非常高兴。   不过我得坦白,在写作《自己动手写操作系统》的时候,我并不敢期待它能引起多少反响,一方面因为操作系统并不是时尚的话题,另一方面我也是走在学习的路上,或许只是比读者早走了一小步而已。然而出乎我的意料,它面世后重印多次,甚至一度登上销量排行榜的榜首,这让我觉得它的确有一定的参考价值,我要借此机会感谢所有支持我的读者。   在我写作《自己动手写操作系统》的时候,并没有想过今天会有一个第二版。原因在于,我希望这本书是用来填补空白的,而不是重复去别人已经得很好的事情。所谓填补空白,具体说就是让像我一样的操作系统爱好者在读完本书之后,能够有信心去读其他比较流行的开源的操作系统代码,有能力从零开始自己动手写操作系统,而这个任务第一版已经完成了。   那么为什么我又写作了第二版呢?原因有几个方面。第一,虽然第一版未曾涉及的进程间通信、文件系统等内容在许多书中都有讲解,但阅读的时候还是感觉有语焉不详的通病,作者本人可能很清楚原委,但写得太简略,以至于读者看来未必清晰。第二,我自己想把这个圈画圆。第一版的书虽然完成了它的使命,但毕竟到书的结尾,读者看到的不是一个真正的操作系统,它没有文件系统,没有内存管理,什么也干不了。在第二版中,你将会看到,你已经可以通过交叉编译的方式为我们的实验性 OS编写应用程序了,也就是说,它已经具备操作系统的基本功能,虽然仍然极其简陋,但第一个圈,毕竟是已经圆起来了。第三,实践类的操作系统书籍还是太少了,以至于你要想看看别人是怎么的,除了读以《操作系统:设计与实现》为代表的极少数书籍之外,就是一头扎进源代码中,而结果有时相当令人气馁。我自己也气馁过,所以我在第二版中,仍然试图把话说细一点,把自己的经验拿出来分享。而且我选择我能想到的最精简的设计,以便让读者不至于陷入太多细节而无法看到全貌。我想这是本书可能具有的价值所在──简化的易懂的设计,还有尽量详细的文字。   在这一版中,内容被划分成上下两篇。上篇基本上是第一版的修订,只是了一个调整,那便是在兼顾 Windows和Linux两方面用户的基础上,默认在Linux下建立开发环境来编写我们的操作系统。至于这样的原因,在本书第 2章有比较详细的说明。当然,开发环境毕竟是第二位的,书中讲述的内容以及涉及的代码跟第一版都是一致的。本书的下篇全部都是新鲜内容,主要是增加了进程间通信、文件系统和内存管理。跟第一版的法相同,下篇仍然不仅关注结果,更加致力于将形成一个结果的过程呈现出来。与此同时,由于本书旨在分享和引路,所以尽可能地简化了设计,以便将最重要的部分凸显出来。读者将看到,一个操作系统的文件系统和内存管理可以简陋到什么程度。简陋不是缺点,对于我们初学者而言,正是需要从简陋入手。换言之,如果你已经对实现一个操作系统有了一定的经验,那么这本书可能不适合你。这本书适合从来没有编写过操作系统的初学者。   本书的排版是我用L ATEX自己完成的。在排版中我花了一些工夫,因为我希望读者购买的首先是一本易于阅读且赏心悦目的书,其次才是编写操作系统的方法。另外,书中列出的代码均由我自己编写的程序自动嵌入L ATEX源文件,从而严格保证书和光盘的一致性,读者可以根据文件名和行号方便地找到光盘中   代码的准确位置。   此外,在第二版中还有一些小的变化。首先是操作系统的名字改变了,原因在于虽然我们的试验性   OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字Orange ’S(这个名字来自于我的妻子 ,),以表示它们的不同。另外,书中的代码风格,有些地方也了调整。   我想,虽然第二版有着这样那样的变化,但有一点没有变,那就是本书试图将我在编写自己操作系统的过程中的经验尽可能地告诉读者,同时尽可能将我当初的思路和编码过程呈现出来。很可能读者比我更聪明,有更好的解决问题的方法,但无论如何,我认为我自己的经验可以为读者所借鉴。如果真是如   此,我将会非常欣慰。   在第二版的编写过程中,我同样要感谢许多人。感谢我的父母和爷爷对我的爱,并希望爷爷不要为我担心,写书是件辛苦的事,但同时也使我收获良多。爸爸在第二版的最后阶段帮我订正文字,这本书里有你的功劳。我要感谢博文视点的各位朋友,感谢郭老师的理解和支持,感谢李玲的辛勤工作,感谢江立和李冰,你们的高效让我非常钦佩。我还要感谢孟岩老师,你给我的鼓励我一直记在心里。我要感谢我的挚友郭洪桥,不仅仅因为你在技术上给我的帮助,更加因为你在精神上给我的支持。感谢我的同事和朋友张会昌,你在技术上的广度和深度总令我钦佩。另外,在第一版中帮助我的人,我要再次谢谢你们,因为没有第一版,也就没有第二版。   在所有人中我最应该感谢和最想感谢的,是我的妻子黄丹红,感谢你给我的所有建议,还有你帮我画的图。尤其是,当这本书在我预想的时间内没有完成的时候,当我遇到困难迟迟不能解决的时候,你总在一旁给我鼓励,在你那里,我从来都能感觉到一种温暖,我深知,如果没有你的支持,我无法坚持下来将书写完。谢谢你,这本书同样属于你。   跟第一版相比,这本书涉及的内容触及操作系统设计的更多方面,而由于笔者的水平实在有限,难免有纰漏甚至错误。如果读者有任何的问题、意见或建议,请登录http://www.osfromscratch.org,让我们共同探讨,共同进步。   本书导读   这本书适合谁   本书是一本操作系统实践的技术书籍。对于操作系统技术感兴趣,想要亲身体验编写操作系统过程的实践主义者,以及Minix、Linux源代码爱好者,都可以在本书中得到实践中所需的知识和思路。   本书以“动手写”为指导思想,只要是跟“动手写”操作系统有关的知识,都作为介绍对象加以讨论,所以,从开发环境的搭建,到保护模式,再到IBMPC中有关芯片的知识,最后到操作系统本身的设计实现,都能在本文中找到相应介绍。所以如果你也想亲身实践的话,本书可以省去你在书店和互联网寻找相应资料的过程,使你的学习过程事半功倍。在读完本书后,你不但可以获得对于操作系统初步的感性认识,并且对 IBMPC的接口、IA架构之保护模式,以及操作系统整体上的框架都将会有一定程度的了解。   笔者相信,当你读完本书之后,如果再读那些纯理论性的操作系统书籍,所获得的体验将会完全不同,因为那些对你而言不再是海市蜃楼。   对于想阅读 Linux源代码的操作系统爱好者,本书可以提供阅读前所必要的知识储备,而这些知识储备不但在本书中有完整的涉及,而且在很多 Linux书籍中是没有提到的。   特别要提到的是,对于想通过阅读 Andrew S. Tanenbaum和 Albert S. Woodhull的《操作系统:设计与实现》来学习操作系统的读者,本书尤其适合作为你的引路书籍,因为它翔实地介绍了初学者入门时所必需的知识积累,而这些知识在《操作系统:设计与实现》一书中是没有涉及的,笔者本人是把这本书作为写操作系统的主要参考书籍之一,所以在本书中对它多有借鉴。   你需要什么技术基础   在本书中所用到的计算机语言只有两种:汇编和 C语言。所以只要你具备汇编和 C语言的经验,就可以阅读本书。除对操作系统常识性的了解(比如知道中断、进程等概念)之外,本书不假定读者具备其他任何经验。   如果你学习过操作系统的理论课程,你会发现本书是对于理论的吻合和补充。它是从实践的角度为你展现一幅操作系统画面。   书中涉及了 Intel CPU保护模式、Linux命令等内容,到时候会有尽可能清晰的讲解,如果笔者认为某些内容可以通过其他教材系统学习,会在书中加以说明。   另外,本书只涉及 Intel x86平台。   统一思想——让我们在这些方面达成共识   道篇   让我们有效而愉快地学习   你大概依然记得在你亲自敲出第一个“Hello world”程序并运行成功时的喜悦,那样的成就感助燃了你对编写程序浓厚的兴趣。随后你不断地学习,每学到新的语法都迫不及待地在计算机上调试运行,在调试的过程中克服困难,学到新知,并获得新的成就感。   可现在请你设想一下,假如课程不是这样的安排,而是先试图告诉你所有的语法,中间没有任何实践的机会,试问这样的课程你能接受吗?我猜你唯一的感受将是索然寡味。   原因何在?只是因为你不再有因为不断实践而获得的源源不断的成就感。而成就感是学习过程中快乐的源泉,没有了成就感,学习的愉快程度将大打折扣,效果于是也将变得不容乐观。   每个人都希望有效而且愉快的学习过程,可不幸的是,我们见到的操作系统课程十之八九令我们失望,作者喋喋不休地讲述着进程管理存储管理I/O控制调度算法,可我们到头来也没有一点的感性认识。我们好像已经理解却又好像一无所知。很明显,没有成就感,一点也没有。笔者痛恨这样的学习过程,也决不会重蹈这样的覆辙,让读者获得成就感将是本书的灵魂。   其实这本书完全可以称作一本回忆录,记载了笔者从开始不知道保护模式为何物到最终形成一个小小   OS的过程,这样的回忆录性质保证了章节的安排完全遵从操作的时间顺序,于是也就保证了每一步的可操作性,毫无疑问,顺着这样的思路走下来,每一章的成果都需要努力但又尽在眼前,步步为营是我   们的战术,成就感是我们的宗旨。   我们将从二十行代码开始,让我们最简单的操作系统婴儿慢慢长大,变成一个翩翩少年,而其中的每一步,你都可以在书中的指导下自己完成,不仅仅是看到,而是自己到!你将在不断的实践中获得不断的成就感,笔者真心希望在阅读本书的过程中,你的学习过程可以变得愉快而有效。   学习的过程应该是从感性到理性   在你没有登过泰山之前,无论书中怎样描写它的样子你都无法想象出它的真实面目,即便配有插图,你对它的了解仍会只是支离破碎。毫无疑问,一千本对泰山描述的书都比不上你一次登山的经历。文学家的描述可能是华丽而优美的,可这样的描述最终产生的效果可能是你非去亲自登泰山不可。反过来想呢,假如你已经登过泰山,这样的经历产生的效果会是你想读尽天下描述泰山的书而后快吗?可能事实恰恰相反,你可能再也不想去看那些文字描述。   是啊,再好的讲述,又哪比得上亲身的体验?人们的认知规律本来如此,有了感性的认识,才能上升为理性的理论。反其道而行之只能是事倍功半。   如果操作系统是一座这样的大山,本书愿你的导游,引领你进入它的门径。传统的操作系统书籍仅仅是给你讲述这座大山的故事,你只是在听讲,并没有身临其境,而随着这本书亲身体验,则好像置身于山门之内,你不但可以看见眼前的每一个细节,更是具有了走完整座大山的信心。   值得说明的是,本书旨在引路,不会带领你走完整座大山,但是有兴趣的读者完全可以在本书最终形成的框架的基础上容易地实现其他操作系统书籍中讲到的各种原理和算法,从而对操作系统有个从感性到理性的清醒认识。   暂时的错误并不可怕   当我们对一件事情的全貌没有很好理解的时候,很可能会对某一部分产生理解上的误差,这就是所谓的断章取义。很多时候断章取义是难免的,但是,在不断学习的过程中,我们会逐渐看到更多,了解更多,对原先事物的认识也会变得深刻甚至不同。   对于操作系统这样复杂的东西来说,要想了解所有的细节无疑是非常困难的,所以在实践的过程中,可能在很多地方,会有一些误解发生。这都没有关系,随着了解的深入,这些误解总会得到澄清,到时你会发现,自己对某一方面已经非常熟悉了,这时的成就感,一定会让你感到非常愉悦。   本书内容的安排遵从的是代码编写的时间顺序,它更像是一本开发日记,所以在书中一些中间过程不完美的产物被有意保留了下来,并会在以后的章节中对它们进行修改和完善,因为笔者认为,一些精妙的东西背后,一定隐藏着很多中间的产物,一个伟大的发现在很多情况下可能不是天才们刹那间的灵光一闪,背后也一定有着我们没有看到的不伟大甚至是谬误。笔者很想追寻前辈们的脚步,重寻他们当日的足迹。到这一点无疑很难,但即便无法到,只要能引起读者的一点思索,也是本书莫大的幸事。   挡住了去路的,往往不是大树,而是小藤   如果不是亲身去,你可能永远都不知道,困难是什么。   就好像你买了一台功能超全的微波炉回家,研究完了整本说明书,踌躇满志想要烹饪的时候,却突然发现家里的油盐已经用完。而当时已经是晚上十一点,所有的商店都已经关门,你气急败坏,简直想摸起铁勺砸向无辜的微波炉。   研究说明书是没有错的,但是在没开始之前,你永远都想不到让你无法烹饪的原因居然是十块钱一瓶的油和一块钱一袋的更加微不足道的盐。你还以为困难是微波炉面板上密密麻麻的控制键盘。   其实其他事情也是一样的,比如写一个操作系统,即便一个很小的可能受理论家们讥笑的操作系统雏形,仍然可能遇到一大堆你没有想过的问题,而这些问题在传统的操作系统书籍中根本没有提到。所以唯一的办法,便是亲自去,只有实践了,才知道是怎么回事。   术篇   用到什么再学什么   我们不是在考试,我们只是在为了自己的志趣而努力,所以就让我们忠于自己的喜好吧,不必为了考试而看完所有的章节,无论那是多么的乏味。让我们马上投入实践,遇到问题再图解决的办法。笔者非常推崇这样的学习方法:   实践 →遇到问题 →解决问题 →再实践   因为我们知道我们为什么学习,所以我们才会非常投入;由于我们知道我们的目标是解决什么问题,所以我们才会非常专注;由于我们在实践中学习,所以我们才会非常高效。而最有趣的是,最终你会发现你并没有因为选择这样的学习方法而少学到什么,相反,你会发现你用更少的时间学到更多的东西,并且格外的扎实。   只要用心,就没有学不会的东西   笔者还清楚地记得刚刚下载完 Intel Architecture Software Developer Manual那三个可怕的 PDF文件时的心情,那时心里暗暗嘀咕,什么时候才能把这些东西读懂啊!可是突然有一天,当这些东西真的已经被基本读完的时候,我想起当初的畏惧,时间其实并没有过去多少。   所有的道理都是相通的,没有什么真正可怕,尤其是,我们所的并非创造性的工作,所有的问题前人都曾经解决,所以我们更是无所畏惧,更何况我们不仅有书店,而且有互联网,动动手脚就能找到需要的资料,我们只要认真研究就够了。   所以当遇到困难时,请静下心来,慢慢研究,因为只要用心,就没有学不会的东西。   适当地囫囵吞枣   如果囫囵吞枣仅仅是学习的一个过程而非终点,那么它并不一定就是坏事。大家都应该听说过鲁迅先生学习英语的故事,他建议在阅读的过程中遇到不懂的内容可以忽略,等到过一段时间之后,这些问题会自然解决。   在本书中,有时候可能先列出一段代码,告诉你它能完成什么,这时你也可以大致读过,因为下面会有对它详细的解释。第一遍读它的时候,你只要了解大概就够了。    本书的原则   1.宁可啰嗦一点,也不肯漏掉细节   在书中的有些地方,你可能觉得有些很“简单”的问题都被列了出来,甚至显得有些啰嗦,但笔者宁可让内容写得啰嗦点,因为笔者自己在读书的时候有一个体验,就是有时候一个问题怎么也想不通,经过很长时间终于弄明白的时候才发现原来是那么“简单”。可能作者认为它足够简单以至于可以跳过不提,但读者未必那么幸运一下子就弄清楚。   不过本书到后面的章节,如果涉及的细节是前面章节提到过的,就有意地略过了。举个非常简单的例子,开始时本书会提醒读者增加一个源文件之后不要忘记修改Makefile,到后来就假定读者已经熟悉了这个步骤,可能就不再提及了。   2.努力到平易近人   笔者更喜欢把本书称作一本笔记或者学习日志,不仅仅是因为它基本是真实的学习过程的再现,而且笔者不想让它有任何居高临下甚至是晦涩神秘的感觉。如果有一个地方你觉得书中没有说清楚以至于你没有弄明白,请你告诉我,我会在以后出改进。 3.代码注重可读性但不注重效率   本书的代码力求简单易懂,在此过程中很少考虑运行的效率。一方面因为书中的代码仅仅供学习之用,暂时并不考虑实际用途;另一方面笔者认为当我们对操作系统足够了解之后再考虑效率的问题也不迟。   本书附带光盘说明   本书附带光盘中有本书用到的所有源代码。值得一提的是,其中不止包含完整的操作系统代码,还包含各个步骤的中间产物。换句话说,开发中每一步骤的代码,都可在光盘中单独文件夹中找到。举例说明,书的开篇介绍引导扇区,读者在相应文件夹中就只看到引导扇区的代码;第 9章介绍文件系统,在相应文件夹中就不会包含第 10章内存管理的代码。在任何一个步骤对应的文件夹中,都包含一个完整可编译运行的代码树,以方便读者试验之用。这样在学习的任何一个阶段,读者都可彻底了解阶段性成果,且不必担心受到自己还未学习的内容的影响,从而使学习不留死角。   在书的正文中引用的代码会标注出出自哪个文件。以“chapter5/b/bar.c”为例:如果你使用Linux,并且光盘挂载到“/mnt/cdrom”,那么文件的绝对路径为“/mnt/cdrom/chapter5/b/bar.c”;如果你使用Windows,并且光盘是 X:盘,那么文件的绝对路径为“X:nchapter5nbnbar.c”。 目 录   上 篇   第1章 马上动手写一个最小的“操作系统” 2   1.1 准备工作 2   1.2 十分钟完成的操作系统 3   1.3 引导扇区 4   1.4 代码解释 4   1.5 水面下的冰山 6   1.6 回顾 7   第2章 搭建你的工作环境 8   2.1 虚拟计算机Bochs 8   2.1.1 Bochs初体验 8   2.1.2 Bochs的安装 9   2.1.3 Bochs的使用 10   2.1.4 用Bochs调试操作系统 12   2.2 QEMU 15   2.3 平台之争:Windows还是*nix 16   2.4 GNU/Linux下的开发环境 20   2.5 Windows下的开发环境 22   2.6 总结 23   第3章 保护模式(Protect Mode) 25   3.1 认识保护模式 25   3.1.1 保护模式的运行环境 29   3.1.2 GDT(Global Descriptor Table) 31   3.1.3 实模式到保护模式,不一般的jmp 33   3.1.4 描述符属性 35   3.2 保护模式进阶 38   3.2.1 海阔凭鱼跃 38   3.2.2 LDT(Local Descriptor Table) 44   3.2.3 特权级概述 48   3.2.4 特权级转移 51   3.2.5 关于“保护”二字的一点思考 65   3.3 页式存储 65   3.3.1 分页机制概述 66   3.3.2 编写代码启动分页机制 67   3.3.3 PDE和PTE 68   3.3.4 cr3 71   3.3.5 回头看代码 72   3.3.6 克勤克俭用内存 73   3.3.7 进一步体会分页机制 81   3.4 中断和异常 87   3.4.1 中断和异常机制 87   3.4.2 外部中断 90   3.4.3 编程操作8259A 91   3.4.4 建立IDT 94   3.4.5 实现一个中断 95   3.4.6 时钟中断试验 96   3.4.7 几点额外说明 98   3.5 保护模式下的I/O 100   3.5.1 IOPL 100   3.5.2 I/O许可位图(I/O Permission Bitmap) 100   3.6 保护模式小结 101   第4章 让操作系统走进保护模式 102   4.1 突破512字节的限制 102   4.1.1 FAT12 103   4.1.2 DOS可以识别的引导盘 108   4.1.3 一个最简单的Loader 108   4.1.4 加载Loader入内存 109   4.1.5 向Loader交出控制权 116   4.1.6 整理boot.asm 116   4.2 保护模式下的“操作系统” 117   第5章 内核雏形 119   5.1 在Linux下用汇编写Hello World 119   5.2 再进一步,汇编和C同步使用 120   5.3 ELF(Executable and Linkable Format) 123   5.4 从Loader到内核 127   5.4.1 用Loader加载ELF 127   5.4.2 跳入保护模式 131   5.4.3 重新放置内核 137   5.4.4 向内核交出控制权 142   5.5 扩充内核 143   5.5.1 切换堆栈和GDT 144   5.5.2 整理我们的文件夹 148   5.5.3 Makefile 149   5.5.4 添加中断处理 155   5.5.5 两点说明 168   5.6 小结 169   第6章 进程 171   6.1 迟到的进程 171   6.2 概述 171   6.2.1 进程介绍 172   6.2.2 未雨绸缪——形成进程的必要考虑 172   6.2.3 参考的代码 173   6.3 最简单的进程 174   6.3.1 简单进程的关键技术预测 175   6.3.2 第一步——ring0→ring1 178   6.3.3 第二步——丰富中断处理程序 189   6.4 多进程 200   6.4.1 添加一个进程体 200   6.4.2 相关的变量和宏 200   6.4.3 进程表初始化代码扩充 202   6.4.4 LDT 203   6.4.5 修改中断处理程序 203   6.4.6 添加一个任务的步骤总结 206   6.4.7 号外:Minix的中断处理 207   6.4.8 代码回顾与整理 212   6.5 系统调用 220   6.5.1 实现一个简单的系统调用 222   6.5.2 get_ticks的应用 227   6.6 进程调度 232   6.6.1 避免对称——进程的节奏感 232   6.6.2 优先级调度总结 240   第7章 输入/输出系统 242   7.1 键盘 242   7.1.1 从中断开始——键盘初体验 242   7.1.2 AT、PS/2键盘 243   7.1.3 键盘敲击的过程 244   7.1.4 用数组表示扫描码 248   7.1.5 键盘输入缓冲区 251   7.1.6 用新加的任务处理键盘操作 253   7.1.7 解析扫描码 254   7.2 显示器 263   7.2.1 初识TTY 264   7.2.2 基本概念 264   7.2.3 寄存器 267   7.3 TTY任务 270   7.3.1 TTY任务框架的搭建 272   7.3.2 多控制台 277   7.3.3 完善键盘处理 281   7.3.4 TTY任务总结 288   7.4 区分任务和用户进程 289   7.5 printf 291   7.5.1 为进程指定TTY 292   7.5.2 printf()的实现 292   7.5.3 系统调用write() 294   7.5.4 使用printf() 296   下 篇   第8章 进程间通信 300   8.1 微内核还是宏内核 300   8.1.1 Linux的系统调用 302   8.1.2 Minix的系统调用 303   8.1.3 我们的选择 305   8.2 IPC 306   8.3 实现IPC 306   8.3.1 assert()和panic() 309   8.3.2 msg_send()和msg_receive() 313   8.3.3 增加消息机制之后的进程调度 321   8.4 使用IPC来替换系统调用get_ticks 322   8.5 总结 324   第9章 文件系统 325   9.1 硬盘简介 325   9.2 硬盘操作的I/O 端口 326   9.3 硬盘驱动程序 327   9.4 文件系统 337   9.5 硬盘分区表 338   9.6 设备号 344   9.7 用代码遍历所有分区 347   9.8 完善硬盘驱动程序 352   9.9 在硬盘上制作一个文件系统 355   9.9.1 文件系统涉及的数据结构 356   9.9.2 编码建立文件系统 358   9.10 创建文件 366   9.10.1 Linux下的文件操作 366   9.10.2 文件描述符(file descriptor) 367   9.10.3 open() 369   9.11 创建文件所涉及的其他函数 377   9.11.1 strip_path() 377   9.11.2 search_file() 378   9.11.3 get_inode()和sync_inode() 379   9.11.4 init_fs() 381   9.11.5 read_super_block()和get_super_block() 382   9.12 关闭文件 383   9.13 查看已创建的文件 384   9.14 打开文件 386   9.15 读写文件 387   9.16 测试文件读写 390   9.17 文件系统调试 393   9.18 删除文件 395   9.19 插曲:奇怪的异常 401   9.20 为文件系统添加系统调用的步骤 403   9.21 将TTY纳入文件系统 404   9.22 改造printf 411   9.23 总结 413   第10章 内存管理 414   10.1 fork 414   10.1.1 认识fork 414   10.1.2 fork前要的工作(为fork所的准备) 417   10.1.3 fork()库函数 421   10.1.4 MM 421   10.1.5 运行 427   10.2 exit和wait 427   10.3 exec 432   10.3.1 认识exec 433   10.3.2 为自己的操作系统编写应用程序 434   10.3.3 “安装”应用程序 436   10.3.4 实现exec 442   10.4 简单的shell 447   10.5 总结 449   第11章 尾声 451   11.1 让mkfs()只执行一次 451   11.2 从硬盘引导 455   11.2.1 编写硬盘引导扇区和硬盘版loader 455   11.2.2 “安装”hdboot.bin和hdldr.bin 461   11.2.3 grub 461   11.2.4 小结 463   11.3 将OS安装到真实的计算机 465   11.3.1 准备工作 465   11.3.2 安装Linux 466   11.3.3 编译源代码 466   11.3.4 开始安装 467   11.4 总结 467   参考文献 470 解密《一个操作系统的实现》这本书 5 月 18 日见到了《 Orange'S :一个操作系统的实现》的样书,多少有些激动。想一想前一版本《自己动手写操作系统》是那么畅销,这一本一定不能含糊。整个出版过程我能看到作者于渊为此付出的努力,还在自己排版的过程有深入体会,通过于渊的讲座也让博文视点的员工分享到他在排版过程中的很多心得。 应该有几万个朋友读过《自己动手写操作系统》了,本书的第 2 版《 Orange'S :一个操作系统的实现》出来肯定有非常多的朋友想问,这两本书到底有何区别呢?就此博文视点对本书作者于渊进行了简单的采访。 * 提问:《 Orange'S :一个操作系统的实现》与《自己动手写操作系统》明显区别在哪些方面? * 于渊:作为《自己动手写操作系统》(以下简称《自》)的第二版,《 Orange'S :一个操作系统的实现》(以下简称“新版”)主要有以下变化: 1. 书中示例操作系统的名字改为 Orange'S 2. 书名改为《 Orange'S :一个操作系统的实现》 3. 增加了有关 IPC 、 FS 、 MM 等内容 4. 将默认开发平台改为 GNU/Linux ,同时兼顾 Windows 5. 更改了排版工具,并使用技术手段增加书的可读性,比如代码行号的运用 6. 建立专门网站以服务读者 7. 建立专门讨论区供读者交流 读过《自己动手写操作系统》的读者一定知道,其中默认使用 Windows 作为开发平台,同时使用虚拟机来编译及运行自己的 OS ,在新版中这一点发生了变化(如上述第 4 条所述),具体的变化原因在书中第二章有详细的叙述。虽然开发平台是第二位的事情,但书中的默认平台却不免影响到叙述细节,所以,如果读者基于自己的原因坚持在 Windows 上开发(可能的原因或许有对 Linux 不熟悉、需要边开发操作系统边登录某些网上银行等等),则可能对读到的内容进行一点点额外加工。当然,所需的额外加工是少量的,而且在第二章中也有专门的文字介绍如何在两种平台下搭建工作环境。此外,如果读者不介意花钱,还可以同时购买《自己动手写操作系统》和新版,相互参照阅读。 * 提问:《 Orange'S :一个操作系统的实现》与《自己动手写操作系统》相比是否有所增加吗?增加了多少内容量呢? 于渊:新版的内容是有增加的,新增文字约占整本书的三分之一,《 Orange'S :一个操作系统的实现》新增代码则是《自己动手写操作系统》中代码的数倍。这些新增的内容,读者只能从新版中获得。目前并未有将新增内容单独成书的打算,所以读者即便仅想阅读第八章以后的内容,也需要购买整本《 Orange'S :一个操作系统的实现》。已经购买了《自己动手写操作系统》的读者可能觉得有点浪费,但事实并不如此,因为《自己动手写操作系统》的内容经过了重新排版、修订和编辑(比如代码格式进行了重排,更方便与光盘中的文件对照阅读,以及其中所有的矢量图都用 pgf/TikZ 重新绘制等)笔者倾注的心血使得新版的感官已经大为不同,读者一看便知。 * 提问:在《自己动手写操作系统》大卖的时候,您是否想过会有第二版出版呢? * 于渊:坦白讲,我在写作《自》的时候,并没有想过今天会有一个第二版。原因在于,我希望这本书是用来填补空白的,而不是重复去别人已经得很好的事情。所谓填补空白,具体说就是让像我一样的操作系统爱好者在读完本书之后,能够有信心去读其他比较流行的开源的操作系统代码,有能力从零开始自己动手写操作系统,而这个任务第一版已经完成了。 * 提问:那么为什么又写作了第二版呢? * 于渊:原因有几个方面。第一,虽然第一版未曾涉及的进程间通信、文件系统等内容在许多书中都有讲解,但阅读的时候还是感觉有语焉不详的通病,作者本人可能很清楚原委,但写得太简略,以至于读者看来未必清晰。第二,我自己想把这个圈画圆。第一版的书虽然完成了它的使命,但毕竟到书的结尾,读者看到的不是一个真正的操作系统,它没有文件系统,没有内存管理,什么也干不了。在第二版中,你将会看到,你已经可以通过交叉编译的方式为我们的实验性 OS 编写应用程序了,也就是说,它已经具备操作系统的基本功能,虽然仍然极其简陋,但第一个圈,毕竟是已经圆起来了。第三,实践类的操作系统书籍还是太少了,以至于你要想看看别人是怎么的,除了读以《操作系统:设计与实现》为代表的极少数书籍之外,就是一头扎进源代码中,而结果有时相当令人气馁。我自己也气馁过,所以我在第二版中,仍然试图把话说细一点,把自己的经验拿出来分享。而且我选择我能想到的最精简的设计,以便让读者不至于陷入太多细节而无法看到全貌。我想这是本书可能具有的价值所在──简化的易懂的设计,还有尽量详细的文字。 * 提问:这本书为何不考虑用 WORD 排版? * 于渊:新版的排版是我用 LaTeX 自己完成的。在排版中我花了一些工夫,因为我希望读者购买的首先是一本易于阅读且赏心悦目的书,其次才是编写操作系统的方法。另外,书中列出的代码均由我自己编写的程序自动嵌入 LaTeX 源文件,从而严格保证书和光盘的一致性,读者可以根据文件名和行号方便地找到光盘中代码的准确位置。 * 提问:第二版还有哪些区别呢? Orange'S 这个名字很特别,有什么寓意吗? * 于渊:新版中还有一些小的变化。首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS 从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix (本意为 TryMinix )改成了新名字 Orange'S (这个名字来自于我的妻子),以表示它们的不同。另外,书中的代码风格,有些地方也了调整。 新版中,原先的叙述风格都尽量地得以贯彻,而在表现形式上,新版用了更多心思,我相信读者能在其中发现这些特点:关注动手细节,探寻代码背后的故事,结果与过程兼顾,内容与形式并重。加上专门为本书建立的网站和讨论区,我相信读者能更容易地阅读,更轻松地学习。
内容简介   本书从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。书中不仅关注代码本身,同时关注完成这些代码的思路和过程。本书不同于其他的理论型书籍,而是提供给读者一个动手实践的路线图。读者可以根据路线图逐步完成各部分的功能,从而避免了一开始就面对整个操作系统数万行代码时的迷茫和挫败感。书中讲解了大量在开发操作系统中需注意的细节问题,这些细节不仅能使读者更深刻地认识操作系统的核心原理,而且使整个开发过程少走弯路。本书分上下两篇,共11章。其中每一章都以前一章的工作成果为基础,实现一项新的功能。而在章的内部,一项大的功能被分解成许多小的步骤,通过完成每个小的步骤,读者可以不断获得阶段性的成果,从而让整个开发过程变得轻松并且有趣。   本书适合各类程序员、程序开发爱好者阅读,也可作为高等院校操作系统课程的实践参考书。 序   真正 Hacker的乐趣──自己动手去实践   2004年我听编辑说有个年轻人写了本《自己动手写操作系统》,第一反应是不可能,恐怕是翻译稿,写这种书籍是要考作者硬功夫的,不但需要深入掌握操作系统的原理,还需要实际动手写出原型。   历史上的 Linux就是这么产生的,Linus Torvalds当时是一名赫尔辛基大学计算机科学系的二年级学生,经常要用自己的电脑去访问大学主机上的新闻组和邮件,为了方便读写和下载文件,他自己编写了磁盘驱动程序和文件系统,这成为了 Linux第一个内核的雏形。   我想中国有能力写出内核原型的程序员应该也有,但把这个题目写成一本书,感觉上不会有人愿意这件事情,作者要花很多时间,加上主题比较硬,销售量不会太高,经济上回报有限。   但拿来文稿一看,整个编辑部大为惊艳,内容文笔俱佳,而且绝对原创,马上决定在《程序员》连载。2005年博文视点出版的第一版也广受好评。   不过有很多读者还是质疑:现在软件编程主要领域是框架和应用,还需要了解操作系统底层吗?   经过四年的磨练成长,于渊又拿出第二版的书稿《Orange'S:一个操作系统的实现》,这本书是属于真正 Hacker的。我虽然已经有多年不写代码了,但看这本书的时候,让我又重新感受到程序员的乐趣:用代码建设属于自己的系统,让电脑听从自己的指令,对系统的每个部分都了如指掌。   黑客(hacker)实际是褒义词,维基百科的解释是喜欢用智力通过创造性方法来挑战脑力极限的人,特别是他们所感兴趣的领域,例如软件编程或电气工程。个人电脑、软件和互联网等划时代的产品都是黑客创造出来的,如苹果的 Apple电脑、微软的 Basic解释器、互联网的 Mosaic浏览器。   回答前面读者的质疑,学软件编程并不需要看这本书,想成为优秀程序员和黑客的朋友,我强烈建议你花时间来阅读这本书,并亲自动手实践。正如于渊在本书结尾中所说“我们写自己的操作系统是出于一种好奇,或者说一种求知欲。我希望这样不停地‘过把瘾’能让这种好奇不停地延续”。   好奇心是动力的源泉,追究问题的本质是优秀黑客的必备素质,只有充分掌握了系统原理,才能在技术上游刃有余,才能有真正的创新和发展。中国需要更多真正的黑客,也希望更多的程序员能享受属于黑客的创造乐趣。   蒋涛   2009年 4月 作者自序   本书是《自己动手写操作系统》的第二版,通过一个具体的实例向读者呈现一个操作系统雏形的实现过程。有关操作系统的书籍资料可以找到很多,但是关注如何帮助读者实现一个试验性操作系统的书籍却不多见,本书便是从一个简单的引导扇区开始,讲述一个操作系统成长的故事,以作读者参考之用。   本书面向实践,通过具体实例教读者开发自己的操作系统。书中的步骤遵循由小到大、由浅入深的顺序,跟随这些步骤,读者可以由一个最简单的引导扇区开始,逐渐完善代码,扩充功能,最后形成一个小的操作系统。   本书不仅介绍操作系统的各要素,同时涉及开发操作系统需要的各个方面,比如如何建立开发环境、如何调试以及如何在虚拟机中运行等。书中的实例操作系统采用IA32作为默认平台,所以保护模式也作为必备知识储备收入书中,而这是传统的操作系统实践书籍经常忽略的。总之,只要是开发自己的操作系统中需要的知识,书中都尽量涉及,以便于读者参考。   众所周知,一个成型的操作系统往往非常复杂。如果考虑到操作系统作为软硬件桥梁的特殊地位,那么它可能看上去比一般的软件系统更难理解,因为其核心部分往往包含许多直接针对CPU、内存和 I/O端口的操作,它们夹杂在一片代码汪洋之中,显得更加晦涩。   我们有许多源代码公开的操作系统,可供随时下载和阅读,看上去好像让实现一个供自己把玩的微型操作系统变得容易很多,但事实往往不尽人意,因为这些代码动辄上万甚至几十几百万行,而且细节之间经常互相关联,要理解它们着实不易。我们有许多容易得到的操作系统教程,但读来好像总觉得跟我们有隔膜,不亲近。造成这些的根本原因,在于学习者一开始就面对一个完整的操作系统,或者面对前辈们积累了几十年的一系列理论成果。而无论作者多么擅长写作,读者多么聪明,或者代码多么优秀,要一个初学者理清其中的头绪都将是非常困难的。   我并非在此危言耸听,因为这曾经是我的亲身体会。当然,如果只是为了考试,几本操作系统理论书籍就足够了,你不需要对细节那么清楚。但如果是出于兴趣呢?如果你是想编写自己的操作系统呢?你会发现理论书籍好像一下子变得无用武之地,你会发现任何一个细节上的理解错误都可能导致自己辛辛苦苦编写的代码运行异常甚至崩溃。   我经历过这一切!我曾经翻遍了一本《操作系统:设计与实现》,也没有找到实现一个操作系统应该从何处着手。并不是这些书不好,也不是前人的代码不优秀,而是作为一无所知的初学者,我们所不了解的不仅是高居庙堂的理论知识,还有让我们举步维艰的实践细节。   可能在这些教科书作者的眼里,操作的细节不属于课程的一部分,或者这些细节看上去太容易,根本不值一提,甚至作者认为这些属于所谓“经验”的一部分,约定俗成是由读者本人去摸索的。但是实际情况往往是,这些书中忽略掉的内容恰恰占去了一个初学者大部分的时间,甚至影响了学习的热情。   我至今仍记得当我开始编写自己的操作系统时所遭受的挫败感,那是一种不知道如何着手的无助的感觉。还好我坚持了下来,克服了各种困难,并完成了自己的操作系统雏形。   进而我想到,一定不只是我一个人对编写自己的操作系统怀有兴趣,也一定不只是我一个人在实践时遇到困难。或许我应该把自己的经历写下来,从而可以帮助跟我相似的后来者,就这样,我编写了本书的第一版,也就是《自己动手写操作系统》。我相信,如果你也对神奇的计算机世界充满好奇,并且希望通过自己编写操作系统的方式来了解背后发生的故事,那么你一定可以在这本书中得到一些帮助。而假如你真的因为我的书而重新燃起实践的热情,从而开始一段操作系统旅程,我将会感到非常高兴。   不过我得坦白,在写作《自己动手写操作系统》的时候,我并不敢期待它能引起多少反响,一方面因为操作系统并不是时尚的话题,另一方面我也是走在学习的路上,或许只是比读者早走了一小步而已。然而出乎我的意料,它面世后重印多次,甚至一度登上销量排行榜的榜首,这让我觉得它的确有一定的参考价值,我要借此机会感谢所有支持我的读者。   在我写作《自己动手写操作系统》的时候,并没有想过今天会有一个第二版。原因在于,我希望这本书是用来填补空白的,而不是重复去别人已经得很好的事情。所谓填补空白,具体说就是让像我一样的操作系统爱好者在读完本书之后,能够有信心去读其他比较流行的开源的操作系统代码,有能力从零开始自己动手写操作系统,而这个任务第一版已经完成了。   那么为什么我又写作了第二版呢?原因有几个方面。第一,虽然第一版未曾涉及的进程间通信、文件系统等内容在许多书中都有讲解,但阅读的时候还是感觉有语焉不详的通病,作者本人可能很清楚原委,但写得太简略,以至于读者看来未必清晰。第二,我自己想把这个圈画圆。第一版的书虽然完成了它的使命,但毕竟到书的结尾,读者看到的不是一个真正的操作系统,它没有文件系统,没有内存管理,什么也干不了。在第二版中,你将会看到,你已经可以通过交叉编译的方式为我们的实验性 OS编写应用程序了,也就是说,它已经具备操作系统的基本功能,虽然仍然极其简陋,但第一个圈,毕竟是已经圆起来了。第三,实践类的操作系统书籍还是太少了,以至于你要想看看别人是怎么的,除了读以《操作系统:设计与实现》为代表的极少数书籍之外,就是一头扎进源代码中,而结果有时相当令人气馁。我自己也气馁过,所以我在第二版中,仍然试图把话说细一点,把自己的经验拿出来分享。而且我选择我能想到的最精简的设计,以便让读者不至于陷入太多细节而无法看到全貌。我想这是本书可能具有的价值所在──简化的易懂的设计,还有尽量详细的文字。   在这一版中,内容被划分成上下两篇。上篇基本上是第一版的修订,只是了一个调整,那便是在兼顾 Windows和Linux两方面用户的基础上,默认在Linux下建立开发环境来编写我们的操作系统。至于这样的原因,在本书第 2章有比较详细的说明。当然,开发环境毕竟是第二位的,书中讲述的内容以及涉及的代码跟第一版都是一致的。本书的下篇全部都是新鲜内容,主要是增加了进程间通信、文件系统和内存管理。跟第一版的法相同,下篇仍然不仅关注结果,更加致力于将形成一个结果的过程呈现出来。与此同时,由于本书旨在分享和引路,所以尽可能地简化了设计,以便将最重要的部分凸显出来。读者将看到,一个操作系统的文件系统和内存管理可以简陋到什么程度。简陋不是缺点,对于我们初学者而言,正是需要从简陋入手。换言之,如果你已经对实现一个操作系统有了一定的经验,那么这本书可能不适合你。这本书适合从来没有编写过操作系统的初学者。   本书的排版是我用L ATEX自己完成的。在排版中我花了一些工夫,因为我希望读者购买的首先是一本易于阅读且赏心悦目的书,其次才是编写操作系统的方法。另外,书中列出的代码均由我自己编写的程序自动嵌入L ATEX源文件,从而严格保证书和光盘的一致性,读者可以根据文件名和行号方便地找到光盘中   代码的准确位置。   此外,在第二版中还有一些小的变化。首先是操作系统的名字改变了,原因在于虽然我们的试验性   OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字Orange ’S(这个名字来自于我的妻子 ,),以表示它们的不同。另外,书中的代码风格,有些地方也了调整。   我想,虽然第二版有着这样那样的变化,但有一点没有变,那就是本书试图将我在编写自己操作系统的过程中的经验尽可能地告诉读者,同时尽可能将我当初的思路和编码过程呈现出来。很可能读者比我更聪明,有更好的解决问题的方法,但无论如何,我认为我自己的经验可以为读者所借鉴。如果真是如   此,我将会非常欣慰。   在第二版的编写过程中,我同样要感谢许多人。感谢我的父母和爷爷对我的爱,并希望爷爷不要为我担心,写书是件辛苦的事,但同时也使我收获良多。爸爸在第二版的最后阶段帮我订正文字,这本书里有你的功劳。我要感谢博文视点的各位朋友,感谢郭老师的理解和支持,感谢李玲的辛勤工作,感谢江立和李冰,你们的高效让我非常钦佩。我还要感谢孟岩老师,你给我的鼓励我一直记在心里。我要感谢我的挚友郭洪桥,不仅仅因为你在技术上给我的帮助,更加因为你在精神上给我的支持。感谢我的同事和朋友张会昌,你在技术上的广度和深度总令我钦佩。另外,在第一版中帮助我的人,我要再次谢谢你们,因为没有第一版,也就没有第二版。   在所有人中我最应该感谢和最想感谢的,是我的妻子黄丹红,感谢你给我的所有建议,还有你帮我画的图。尤其是,当这本书在我预想的时间内没有完成的时候,当我遇到困难迟迟不能解决的时候,你总在一旁给我鼓励,在你那里,我从来都能感觉到一种温暖,我深知,如果没有你的支持,我无法坚持下来将书写完。谢谢你,这本书同样属于你。   跟第一版相比,这本书涉及的内容触及操作系统设计的更多方面,而由于笔者的水平实在有限,难免有纰漏甚至错误。如果读者有任何的问题、意见或建议,请登录http://www.osfromscratch.org,让我们共同探讨,共同进步。   本书导读   这本书适合谁   本书是一本操作系统实践的技术书籍。对于操作系统技术感兴趣,想要亲身体验编写操作系统过程的实践主义者,以及Minix、Linux源代码爱好者,都可以在本书中得到实践中所需的知识和思路。   本书以“动手写”为指导思想,只要是跟“动手写”操作系统有关的知识,都作为介绍对象加以讨论,所以,从开发环境的搭建,到保护模式,再到IBMPC中有关芯片的知识,最后到操作系统本身的设计实现,都能在本文中找到相应介绍。所以如果你也想亲身实践的话,本书可以省去你在书店和互联网寻找相应资料的过程,使你的学习过程事半功倍。在读完本书后,你不但可以获得对于操作系统初步的感性认识,并且对 IBMPC的接口、IA架构之保护模式,以及操作系统整体上的框架都将会有一定程度的了解。   笔者相信,当你读完本书之后,如果再读那些纯理论性的操作系统书籍,所获得的体验将会完全不同,因为那些对你而言不再是海市蜃楼。   对于想阅读 Linux源代码的操作系统爱好者,本书可以提供阅读前所必要的知识储备,而这些知识储备不但在本书中有完整的涉及,而且在很多 Linux书籍中是没有提到的。   特别要提到的是,对于想通过阅读 Andrew S. Tanenbaum和 Albert S. Woodhull的《操作系统:设计与实现》来学习操作系统的读者,本书尤其适合作为你的引路书籍,因为它翔实地介绍了初学者入门时所必需的知识积累,而这些知识在《操作系统:设计与实现》一书中是没有涉及的,笔者本人是把这本书作为写操作系统的主要参考书籍之一,所以在本书中对它多有借鉴。   你需要什么技术基础   在本书中所用到的计算机语言只有两种:汇编和 C语言。所以只要你具备汇编和 C语言的经验,就可以阅读本书。除对操作系统常识性的了解(比如知道中断、进程等概念)之外,本书不假定读者具备其他任何经验。   如果你学习过操作系统的理论课程,你会发现本书是对于理论的吻合和补充。它是从实践的角度为你展现一幅操作系统画面。   书中涉及了 Intel CPU保护模式、Linux命令等内容,到时候会有尽可能清晰的讲解,如果笔者认为某些内容可以通过其他教材系统学习,会在书中加以说明。   另外,本书只涉及 Intel x86平台。   统一思想——让我们在这些方面达成共识   道篇   让我们有效而愉快地学习   你大概依然记得在你亲自敲出第一个“Hello world”程序并运行成功时的喜悦,那样的成就感助燃了你对编写程序浓厚的兴趣。随后你不断地学习,每学到新的语法都迫不及待地在计算机上调试运行,在调试的过程中克服困难,学到新知,并获得新的成就感。   可现在请你设想一下,假如课程不是这样的安排,而是先试图告诉你所有的语法,中间没有任何实践的机会,试问这样的课程你能接受吗?我猜你唯一的感受将是索然寡味。   原因何在?只是因为你不再有因为不断实践而获得的源源不断的成就感。而成就感是学习过程中快乐的源泉,没有了成就感,学习的愉快程度将大打折扣,效果于是也将变得不容乐观。   每个人都希望有效而且愉快的学习过程,可不幸的是,我们见到的操作系统课程十之八九令我们失望,作者喋喋不休地讲述着进程管理存储管理I/O控制调度算法,可我们到头来也没有一点的感性认识。我们好像已经理解却又好像一无所知。很明显,没有成就感,一点也没有。笔者痛恨这样的学习过程,也决不会重蹈这样的覆辙,让读者获得成就感将是本书的灵魂。   其实这本书完全可以称作一本回忆录,记载了笔者从开始不知道保护模式为何物到最终形成一个小小   OS的过程,这样的回忆录性质保证了章节的安排完全遵从操作的时间顺序,于是也就保证了每一步的可操作性,毫无疑问,顺着这样的思路走下来,每一章的成果都需要努力但又尽在眼前,步步为营是我   们的战术,成就感是我们的宗旨。   我们将从二十行代码开始,让我们最简单的操作系统婴儿慢慢长大,变成一个翩翩少年,而其中的每一步,你都可以在书中的指导下自己完成,不仅仅是看到,而是自己到!你将在不断的实践中获得不断的成就感,笔者真心希望在阅读本书的过程中,你的学习过程可以变得愉快而有效。   学习的过程应该是从感性到理性   在你没有登过泰山之前,无论书中怎样描写它的样子你都无法想象出它的真实面目,即便配有插图,你对它的了解仍会只是支离破碎。毫无疑问,一千本对泰山描述的书都比不上你一次登山的经历。文学家的描述可能是华丽而优美的,可这样的描述最终产生的效果可能是你非去亲自登泰山不可。反过来想呢,假如你已经登过泰山,这样的经历产生的效果会是你想读尽天下描述泰山的书而后快吗?可能事实恰恰相反,你可能再也不想去看那些文字描述。   是啊,再好的讲述,又哪比得上亲身的体验?人们的认知规律本来如此,有了感性的认识,才能上升为理性的理论。反其道而行之只能是事倍功半。   如果操作系统是一座这样的大山,本书愿你的导游,引领你进入它的门径。传统的操作系统书籍仅仅是给你讲述这座大山的故事,你只是在听讲,并没有身临其境,而随着这本书亲身体验,则好像置身于山门之内,你不但可以看见眼前的每一个细节,更是具有了走完整座大山的信心。   值得说明的是,本书旨在引路,不会带领你走完整座大山,但是有兴趣的读者完全可以在本书最终形成的框架的基础上容易地实现其他操作系统书籍中讲到的各种原理和算法,从而对操作系统有个从感性到理性的清醒认识。   暂时的错误并不可怕   当我们对一件事情的全貌没有很好理解的时候,很可能会对某一部分产生理解上的误差,这就是所谓的断章取义。很多时候断章取义是难免的,但是,在不断学习的过程中,我们会逐渐看到更多,了解更多,对原先事物的认识也会变得深刻甚至不同。   对于操作系统这样复杂的东西来说,要想了解所有的细节无疑是非常困难的,所以在实践的过程中,可能在很多地方,会有一些误解发生。这都没有关系,随着了解的深入,这些误解总会得到澄清,到时你会发现,自己对某一方面已经非常熟悉了,这时的成就感,一定会让你感到非常愉悦。   本书内容的安排遵从的是代码编写的时间顺序,它更像是一本开发日记,所以在书中一些中间过程不完美的产物被有意保留了下来,并会在以后的章节中对它们进行修改和完善,因为笔者认为,一些精妙的东西背后,一定隐藏着很多中间的产物,一个伟大的发现在很多情况下可能不是天才们刹那间的灵光一闪,背后也一定有着我们没有看到的不伟大甚至是谬误。笔者很想追寻前辈们的脚步,重寻他们当日的足迹。到这一点无疑很难,但即便无法到,只要能引起读者的一点思索,也是本书莫大的幸事。   挡住了去路的,往往不是大树,而是小藤   如果不是亲身去,你可能永远都不知道,困难是什么。   就好像你买了一台功能超全的微波炉回家,研究完了整本说明书,踌躇满志想要烹饪的时候,却突然发现家里的油盐已经用完。而当时已经是晚上十一点,所有的商店都已经关门,你气急败坏,简直想摸起铁勺砸向无辜的微波炉。   研究说明书是没有错的,但是在没开始之前,你永远都想不到让你无法烹饪的原因居然是十块钱一瓶的油和一块钱一袋的更加微不足道的盐。你还以为困难是微波炉面板上密密麻麻的控制键盘。   其实其他事情也是一样的,比如写一个操作系统,即便一个很小的可能受理论家们讥笑的操作系统雏形,仍然可能遇到一大堆你没有想过的问题,而这些问题在传统的操作系统书籍中根本没有提到。所以唯一的办法,便是亲自去,只有实践了,才知道是怎么回事。   术篇   用到什么再学什么   我们不是在考试,我们只是在为了自己的志趣而努力,所以就让我们忠于自己的喜好吧,不必为了考试而看完所有的章节,无论那是多么的乏味。让我们马上投入实践,遇到问题再图解决的办法。笔者非常推崇这样的学习方法:   实践 →遇到问题 →解决问题 →再实践   因为我们知道我们为什么学习,所以我们才会非常投入;由于我们知道我们的目标是解决什么问题,所以我们才会非常专注;由于我们在实践中学习,所以我们才会非常高效。而最有趣的是,最终你会发现你并没有因为选择这样的学习方法而少学到什么,相反,你会发现你用更少的时间学到更多的东西,并且格外的扎实。   只要用心,就没有学不会的东西   笔者还清楚地记得刚刚下载完 Intel Architecture Software Developer Manual那三个可怕的 PDF文件时的心情,那时心里暗暗嘀咕,什么时候才能把这些东西读懂啊!可是突然有一天,当这些东西真的已经被基本读完的时候,我想起当初的畏惧,时间其实并没有过去多少。   所有的道理都是相通的,没有什么真正可怕,尤其是,我们所的并非创造性的工作,所有的问题前人都曾经解决,所以我们更是无所畏惧,更何况我们不仅有书店,而且有互联网,动动手脚就能找到需要的资料,我们只要认真研究就够了。   所以当遇到困难时,请静下心来,慢慢研究,因为只要用心,就没有学不会的东西。   适当地囫囵吞枣   如果囫囵吞枣仅仅是学习的一个过程而非终点,那么它并不一定就是坏事。大家都应该听说过鲁迅先生学习英语的故事,他建议在阅读的过程中遇到不懂的内容可以忽略,等到过一段时间之后,这些问题会自然解决。   在本书中,有时候可能先列出一段代码,告诉你它能完成什么,这时你也可以大致读过,因为下面会有对它详细的解释。第一遍读它的时候,你只要了解大概就够了。    本书的原则   1.宁可啰嗦一点,也不肯漏掉细节   在书中的有些地方,你可能觉得有些很“简单”的问题都被列了出来,甚至显得有些啰嗦,但笔者宁可让内容写得啰嗦点,因为笔者自己在读书的时候有一个体验,就是有时候一个问题怎么也想不通,经过很长时间终于弄明白的时候才发现原来是那么“简单”。可能作者认为它足够简单以至于可以跳过不提,但读者未必那么幸运一下子就弄清楚。   不过本书到后面的章节,如果涉及的细节是前面章节提到过的,就有意地略过了。举个非常简单的例子,开始时本书会提醒读者增加一个源文件之后不要忘记修改Makefile,到后来就假定读者已经熟悉了这个步骤,可能就不再提及了。   2.努力到平易近人   笔者更喜欢把本书称作一本笔记或者学习日志,不仅仅是因为它基本是真实的学习过程的再现,而且笔者不想让它有任何居高临下甚至是晦涩神秘的感觉。如果有一个地方你觉得书中没有说清楚以至于你没有弄明白,请你告诉我,我会在以后出改进。 3.代码注重可读性但不注重效率   本书的代码力求简单易懂,在此过程中很少考虑运行的效率。一方面因为书中的代码仅仅供学习之用,暂时并不考虑实际用途;另一方面笔者认为当我们对操作系统足够了解之后再考虑效率的问题也不迟。   本书附带光盘说明   本书附带光盘中有本书用到的所有源代码。值得一提的是,其中不止包含完整的操作系统代码,还包含各个步骤的中间产物。换句话说,开发中每一步骤的代码,都可在光盘中单独文件夹中找到。举例说明,书的开篇介绍引导扇区,读者在相应文件夹中就只看到引导扇区的代码;第 9章介绍文件系统,在相应文件夹中就不会包含第 10章内存管理的代码。在任何一个步骤对应的文件夹中,都包含一个完整可编译运行的代码树,以方便读者试验之用。这样在学习的任何一个阶段,读者都可彻底了解阶段性成果,且不必担心受到自己还未学习的内容的影响,从而使学习不留死角。   在书的正文中引用的代码会标注出出自哪个文件。以“chapter5/b/bar.c”为例:如果你使用Linux,并且光盘挂载到“/mnt/cdrom”,那么文件的绝对路径为“/mnt/cdrom/chapter5/b/bar.c”;如果你使用Windows,并且光盘是 X:盘,那么文件的绝对路径为“X:nchapter5nbnbar.c”。 目 录   上 篇   第1章 马上动手写一个最小的“操作系统” 2   1.1 准备工作 2   1.2 十分钟完成的操作系统 3   1.3 引导扇区 4   1.4 代码解释 4   1.5 水面下的冰山 6   1.6 回顾 7   第2章 搭建你的工作环境 8   2.1 虚拟计算机Bochs 8   2.1.1 Bochs初体验 8   2.1.2 Bochs的安装 9   2.1.3 Bochs的使用 10   2.1.4 用Bochs调试操作系统 12   2.2 QEMU 15   2.3 平台之争:Windows还是*nix 16   2.4 GNU/Linux下的开发环境 20   2.5 Windows下的开发环境 22   2.6 总结 23   第3章 保护模式(Protect Mode) 25   3.1 认识保护模式 25   3.1.1 保护模式的运行环境 29   3.1.2 GDT(Global Descriptor Table) 31   3.1.3 实模式到保护模式,不一般的jmp 33   3.1.4 描述符属性 35   3.2 保护模式进阶 38   3.2.1 海阔凭鱼跃 38   3.2.2 LDT(Local Descriptor Table) 44   3.2.3 特权级概述 48   3.2.4 特权级转移 51   3.2.5 关于“保护”二字的一点思考 65   3.3 页式存储 65   3.3.1 分页机制概述 66   3.3.2 编写代码启动分页机制 67   3.3.3 PDE和PTE 68   3.3.4 cr3 71   3.3.5 回头看代码 72   3.3.6 克勤克俭用内存 73   3.3.7 进一步体会分页机制 81   3.4 中断和异常 87   3.4.1 中断和异常机制 87   3.4.2 外部中断 90   3.4.3 编程操作8259A 91   3.4.4 建立IDT 94   3.4.5 实现一个中断 95   3.4.6 时钟中断试验 96   3.4.7 几点额外说明 98   3.5 保护模式下的I/O 100   3.5.1 IOPL 100   3.5.2 I/O许可位图(I/O Permission Bitmap) 100   3.6 保护模式小结 101   第4章 让操作系统走进保护模式 102   4.1 突破512字节的限制 102   4.1.1 FAT12 103   4.1.2 DOS可以识别的引导盘 108   4.1.3 一个最简单的Loader 108   4.1.4 加载Loader入内存 109   4.1.5 向Loader交出控制权 116   4.1.6 整理boot.asm 116   4.2 保护模式下的“操作系统” 117   第5章 内核雏形 119   5.1 在Linux下用汇编写Hello World 119   5.2 再进一步,汇编和C同步使用 120   5.3 ELF(Executable and Linkable Format) 123   5.4 从Loader到内核 127   5.4.1 用Loader加载ELF 127   5.4.2 跳入保护模式 131   5.4.3 重新放置内核 137   5.4.4 向内核交出控制权 142   5.5 扩充内核 143   5.5.1 切换堆栈和GDT 144   5.5.2 整理我们的文件夹 148   5.5.3 Makefile 149   5.5.4 添加中断处理 155   5.5.5 两点说明 168   5.6 小结 169   第6章 进程 171   6.1 迟到的进程 171   6.2 概述 171   6.2.1 进程介绍 172   6.2.2 未雨绸缪——形成进程的必要考虑 172   6.2.3 参考的代码 173   6.3 最简单的进程 174   6.3.1 简单进程的关键技术预测 175   6.3.2 第一步——ring0→ring1 178   6.3.3 第二步——丰富中断处理程序 189   6.4 多进程 200   6.4.1 添加一个进程体 200   6.4.2 相关的变量和宏 200   6.4.3 进程表初始化代码扩充 202   6.4.4 LDT 203   6.4.5 修改中断处理程序 203   6.4.6 添加一个任务的步骤总结 206   6.4.7 号外:Minix的中断处理 207   6.4.8 代码回顾与整理 212   6.5 系统调用 220   6.5.1 实现一个简单的系统调用 222   6.5.2 get_ticks的应用 227   6.6 进程调度 232   6.6.1 避免对称——进程的节奏感 232   6.6.2 优先级调度总结 240   第7章 输入/输出系统 242   7.1 键盘 242   7.1.1 从中断开始——键盘初体验 242   7.1.2 AT、PS/2键盘 243   7.1.3 键盘敲击的过程 244   7.1.4 用数组表示扫描码 248   7.1.5 键盘输入缓冲区 251   7.1.6 用新加的任务处理键盘操作 253   7.1.7 解析扫描码 254   7.2 显示器 263   7.2.1 初识TTY 264   7.2.2 基本概念 264   7.2.3 寄存器 267   7.3 TTY任务 270   7.3.1 TTY任务框架的搭建 272   7.3.2 多控制台 277   7.3.3 完善键盘处理 281   7.3.4 TTY任务总结 288   7.4 区分任务和用户进程 289   7.5 printf 291   7.5.1 为进程指定TTY 292   7.5.2 printf()的实现 292   7.5.3 系统调用write() 294   7.5.4 使用printf() 296   下 篇   第8章 进程间通信 300   8.1 微内核还是宏内核 300   8.1.1 Linux的系统调用 302   8.1.2 Minix的系统调用 303   8.1.3 我们的选择 305   8.2 IPC 306   8.3 实现IPC 306   8.3.1 assert()和panic() 309   8.3.2 msg_send()和msg_receive() 313   8.3.3 增加消息机制之后的进程调度 321   8.4 使用IPC来替换系统调用get_ticks 322   8.5 总结 324   第9章 文件系统 325   9.1 硬盘简介 325   9.2 硬盘操作的I/O 端口 326   9.3 硬盘驱动程序 327   9.4 文件系统 337   9.5 硬盘分区表 338   9.6 设备号 344   9.7 用代码遍历所有分区 347   9.8 完善硬盘驱动程序 352   9.9 在硬盘上制作一个文件系统 355   9.9.1 文件系统涉及的数据结构 356   9.9.2 编码建立文件系统 358   9.10 创建文件 366   9.10.1 Linux下的文件操作 366   9.10.2 文件描述符(file descriptor) 367   9.10.3 open() 369   9.11 创建文件所涉及的其他函数 377   9.11.1 strip_path() 377   9.11.2 search_file() 378   9.11.3 get_inode()和sync_inode() 379   9.11.4 init_fs() 381   9.11.5 read_super_block()和get_super_block() 382   9.12 关闭文件 383   9.13 查看已创建的文件 384   9.14 打开文件 386   9.15 读写文件 387   9.16 测试文件读写 390   9.17 文件系统调试 393   9.18 删除文件 395   9.19 插曲:奇怪的异常 401   9.20 为文件系统添加系统调用的步骤 403   9.21 将TTY纳入文件系统 404   9.22 改造printf 411   9.23 总结 413   第10章 内存管理 414   10.1 fork 414   10.1.1 认识fork 414   10.1.2 fork前要的工作(为fork所的准备) 417   10.1.3 fork()库函数 421   10.1.4 MM 421   10.1.5 运行 427   10.2 exit和wait 427   10.3 exec 432   10.3.1 认识exec 433   10.3.2 为自己的操作系统编写应用程序 434   10.3.3 “安装”应用程序 436   10.3.4 实现exec 442   10.4 简单的shell 447   10.5 总结 449   第11章 尾声 451   11.1 让mkfs()只执行一次 451   11.2 从硬盘引导 455   11.2.1 编写硬盘引导扇区和硬盘版loader 455   11.2.2 “安装”hdboot.bin和hdldr.bin 461   11.2.3 grub 461   11.2.4 小结 463   11.3 将OS安装到真实的计算机 465   11.3.1 准备工作 465   11.3.2 安装Linux 466   11.3.3 编译源代码 466   11.3.4 开始安装 467   11.4 总结 467   参考文献 470 解密《一个操作系统的实现》这本书 5 月 18 日见到了《 Orange'S :一个操作系统的实现》的样书,多少有些激动。想一想前一版本《自己动手写操作系统》是那么畅销,这一本一定不能含糊。整个出版过程我能看到作者于渊为此付出的努力,还在自己排版的过程有深入体会,通过于渊的讲座也让博文视点的员工分享到他在排版过程中的很多心得。 应该有几万个朋友读过《自己动手写操作系统》了,本书的第 2 版《 Orange'S :一个操作系统的实现》出来肯定有非常多的朋友想问,这两本书到底有何区别呢?就此博文视点对本书作者于渊进行了简单的采访。 * 提问:《 Orange'S :一个操作系统的实现》与《自己动手写操作系统》明显区别在哪些方面? * 于渊:作为《自己动手写操作系统》(以下简称《自》)的第二版,《 Orange'S :一个操作系统的实现》(以下简称“新版”)主要有以下变化: 1. 书中示例操作系统的名字改为 Orange'S 2. 书名改为《 Orange'S :一个操作系统的实现》 3. 增加了有关 IPC 、 FS 、 MM 等内容 4. 将默认开发平台改为 GNU/Linux ,同时兼顾 Windows 5. 更改了排版工具,并使用技术手段增加书的可读性,比如代码行号的运用 6. 建立专门网站以服务读者 7. 建立专门讨论区供读者交流 读过《自己动手写操作系统》的读者一定知道,其中默认使用 Windows 作为开发平台,同时使用虚拟机来编译及运行自己的 OS ,在新版中这一点发生了变化(如上述第 4 条所述),具体的变化原因在书中第二章有详细的叙述。虽然开发平台是第二位的事情,但书中的默认平台却不免影响到叙述细节,所以,如果读者基于自己的原因坚持在 Windows 上开发(可能的原因或许有对 Linux 不熟悉、需要边开发操作系统边登录某些网上银行等等),则可能对读到的内容进行一点点额外加工。当然,所需的额外加工是少量的,而且在第二章中也有专门的文字介绍如何在两种平台下搭建工作环境。此外,如果读者不介意花钱,还可以同时购买《自己动手写操作系统》和新版,相互参照阅读。 * 提问:《 Orange'S :一个操作系统的实现》与《自己动手写操作系统》相比是否有所增加吗?增加了多少内容量呢? 于渊:新版的内容是有增加的,新增文字约占整本书的三分之一,《 Orange'S :一个操作系统的实现》新增代码则是《自己动手写操作系统》中代码的数倍。这些新增的内容,读者只能从新版中获得。目前并未有将新增内容单独成书的打算,所以读者即便仅想阅读第八章以后的内容,也需要购买整本《 Orange'S :一个操作系统的实现》。已经购买了《自己动手写操作系统》的读者可能觉得有点浪费,但事实并不如此,因为《自己动手写操作系统》的内容经过了重新排版、修订和编辑(比如代码格式进行了重排,更方便与光盘中的文件对照阅读,以及其中所有的矢量图都用 pgf/TikZ 重新绘制等)笔者倾注的心血使得新版的感官已经大为不同,读者一看便知。 * 提问:在《自己动手写操作系统》大卖的时候,您是否想过会有第二版出版呢? * 于渊:坦白讲,我在写作《自》的时候,并没有想过今天会有一个第二版。原因在于,我希望这本书是用来填补空白的,而不是重复去别人已经得很好的事情。所谓填补空白,具体说就是让像我一样的操作系统爱好者在读完本书之后,能够有信心去读其他比较流行的开源的操作系统代码,有能力从零开始自己动手写操作系统,而这个任务第一版已经完成了。 * 提问:那么为什么又写作了第二版呢? * 于渊:原因有几个方面。第一,虽然第一版未曾涉及的进程间通信、文件系统等内容在许多书中都有讲解,但阅读的时候还是感觉有语焉不详的通病,作者本人可能很清楚原委,但写得太简略,以至于读者看来未必清晰。第二,我自己想把这个圈画圆。第一版的书虽然完成了它的使命,但毕竟到书的结尾,读者看到的不是一个真正的操作系统,它没有文件系统,没有内存管理,什么也干不了。在第二版中,你将会看到,你已经可以通过交叉编译的方式为我们的实验性 OS 编写应用程序了,也就是说,它已经具备操作系统的基本功能,虽然仍然极其简陋,但第一个圈,毕竟是已经圆起来了。第三,实践类的操作系统书籍还是太少了,以至于你要想看看别人是怎么的,除了读以《操作系统:设计与实现》为代表的极少数书籍之外,就是一头扎进源代码中,而结果有时相当令人气馁。我自己也气馁过,所以我在第二版中,仍然试图把话说细一点,把自己的经验拿出来分享。而且我选择我能想到的最精简的设计,以便让读者不至于陷入太多细节而无法看到全貌。我想这是本书可能具有的价值所在──简化的易懂的设计,还有尽量详细的文字。 * 提问:这本书为何不考虑用 WORD 排版? * 于渊:新版的排版是我用 LaTeX 自己完成的。在排版中我花了一些工夫,因为我希望读者购买的首先是一本易于阅读且赏心悦目的书,其次才是编写操作系统的方法。另外,书中列出的代码均由我自己编写的程序自动嵌入 LaTeX 源文件,从而严格保证书和光盘的一致性,读者可以根据文件名和行号方便地找到光盘中代码的准确位置。 * 提问:第二版还有哪些区别呢? Orange'S 这个名字很特别,有什么寓意吗? * 于渊:新版中还有一些小的变化。首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS 从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix (本意为 TryMinix )改成了新名字 Orange'S (这个名字来自于我的妻子),以表示它们的不同。另外,书中的代码风格,有些地方也了调整。 新版中,原先的叙述风格都尽量地得以贯彻,而在表现形式上,新版用了更多心思,我相信读者能在其中发现这些特点:关注动手细节,探寻代码背后的故事,结果与过程兼顾,内容与形式并重。加上专门为本书建立的网站和讨论区,我相信读者能更容易地阅读,更轻松地学习。
数字杂志的演变与第四代数字杂志技术 一、最“IN”的媒体 2006年年初,短短两个月不到的时间里,国内20多家大型数字杂志发行平台蜂拥上线。Acer、联想、IDG、凯雷等风投纷纷出手,在数字杂志上砸进十几个亿。电子杂志、互动杂志、数字杂志、数码杂志、网络杂志、多媒体杂志等名称并行不悖,频繁地出现在各种媒体上。一本酷酷的数字杂志,已不再是年轻网民的个别喜好,传统媒体纷纷推出电子版,企事业单位则将数字杂志技术广泛地应用于样本、图录、商刊、企刊等。由此,2006年被众多评论人士打上了“数字杂志年”的标签,数字杂志也被誉为最“IN”的媒体。 引爆这场产业革命的是一种基于Flash技术的通常被称作“多媒体杂志”的技术。只要您登陆目前国内的数字杂志发行平台,您几乎都能看到这种集音频、视频、动画、图文于一体,阅读就像翻阅真的书刊一样,还能发表评论、留言的杂志。精美的图文、悠扬的音乐、精彩的视频、翻书的效果、互动的功能……无不带给您强烈的感官刺激与由衷的惊羡,连平时唯恐避之不及的广告也变得可爱多了。 二、数字杂志的演变 “杂志”一词,源于法文,本意“仓库”,后指集束的出版方式,1931年被赋予期刊含义,在表现形态上被进一步解构。从本质上来说,“杂志”是一种信息的集束方式,超链接的互联网站也可被称是数字杂志。而事实上,第一代数字杂志就是以超链接的网页形式出现的,发展到多媒体杂志,已经是数字杂志的第三代了。 也许您现在打开电子邮箱还能经常收到诸如“某某证券杂志”之类的邮件列表,诸多网刊及曾经非常有名的ColdTea电子画刊等,都可归为第一代数字杂志。第一代数字杂志最著名的技术服务商当数至今还在运营的“邮件列表专家”——希网网络,“邮件列表”几乎成了第一代数字杂志的代名词。 第一代数字杂志因其实质就是一般的html网页,因此具有阅读上的便捷性,但人们概念中的“杂志”形态几乎无从体现,倒更像是“羊皮卷手抄本”。于是,hlp、chm、pdf、exe、ppt等电子书开始风行,网上就有人专门将国外电子图书馆里的资料拷贝出来,打包成exe电子书供人下载,“电子书”堪称第二代数字杂志的代名词。其中,由著名的Adobe公司开发的pdf电子书技术,由于得到北大方正电子排版编辑系统的支持,媒体出版机构采用较多。但人们最为熟悉的恐怕还是hlp或chm电子书,因为几乎每台电脑里都有hlp或chm格式的帮助文档。比较出色的电子书制作工具是QuickCHM、eBook Pack Express、Natata eBook Compiler。 第二代数字杂志虽则将文件“装订”到了一起,看上去不再七零八落,但差不多都是一幅静态的、僵死的面孔,且需要安装专门的软件或将杂志下载到本地后才能阅读。随后出现的第三代数字杂志技术,也就是通常被称作“多媒体杂志”的技术,才彻底改变数字杂志的面孔,奠定了数字杂志的基本形态。 多媒体杂志,一种制作精美、内容精萃、信息集束、书刊效果的图文、数据、音视频综合运用的电子出版方式。其逼真的书刊效果,翻动页面还会发出唰唰的声音;动感十足的图文,点击书上的小人还能开口说话;曼妙的背景音乐、精彩的视频、三维的图像……无不给人以惊艳的阅读体验。 多媒体杂志还具有无刊号之困扰、无印刷之耗费,内容更新便捷、杂志流传迅速,可以与网站整合、可以与读者互动,图文资料可以让人方便地拷贝、也可以较好地进行版权保护,还能准确反馈阅读次数、读者层次,设置阅读权限,等等,一系列的优势。 因此,声光色并茂、美轮美奂的多媒体杂志一进入人们的视野便受到广泛追捧,不仅成为新新人类的炫势力,而且迅速成为企事业单位营销拓展、品牌维护、客户服务、企业文化建设的利器,被广泛用于出版电子期刊、书刊、企刊、商刊、样本、图录、画册、相册等,涌现出了Zcom、Xplus、Poco、杂志中国等一大批数字杂志运营商,诺基亚、阳光导航、瑞丽等一大批精彩的数字杂志。“多媒体杂志”也就成了第三代数字杂志的代名词。 三、第三代数字杂志技术 第三代数字杂志在技术上有基于网站技术的,有基于应用软件技术的,但最为主流的还是基于Flash技术的。 基于网站技术的,可以说是第一代数字杂志的升级,比较典型的是QQ杂志与网易行业电子样本。网站技术具有强大的后台处理与系统架构能力,能轻松满足聚合、分发、阅读、统计、交流等各种需求,但前台就很难达到Flash那样的表现力了。因此,基于网站技术的数字杂志技术最后必然会与基于Flash技术的数字杂志技术糅合到一起,成为第四代数字杂志技术。 基于应用软件技术的,可以说是第二代数字杂志的升级,比较典型的是DeskTopAuthor电子书与FlipAlbum相册。虽然它们都表现非凡,但具有第二代数字杂志的通性,那就是需要专用软件并需要将杂志下载到本地,既不便于发行也不便于阅读。即使有朝一日微软IE支持直接阅读,网络环境也没法支持这些无法分解的“大块头”。由于技术上不可逆的先天不足,基于应用软件技术的数字杂志技术的生存空间将越来越有限。特别是随着第四代数字杂志“在线多线程分布式传输、离线自动打包成exe执行文件下载”技术的推出,它将彻底失去继续存在的必要性。 基于Flash技术的,其开山鼻祖是一个名叫陈涛的小伙子。无论是Zcom、Xplus、Poco,还是后来居上的杂志中国,推出的都是这种基于Flash技术的数字杂志。也正是这些携万千风投资本强势入市的企业,掀起了2005、2006年间蔚为壮观的数字杂志产业狂飙。权威部门在2006年年终发布的《中国互联网产业50个细分领域》报告中,“数字杂志”赫然在列。电子杂志、互动杂志、数码杂志、网络杂志、多媒体杂志等至此亦等于有了一个统一的叫法,它的名字叫“数字杂志”。 虽则基于Flash技术的第三代数字杂志技术开启了一个崭新的时代,数字杂志在形态上趋于成熟,但在技术上却基本上是一种较为孤立的开发思路,仅以“出杂志”为目标。因此,无论是Xplus、Poco、Zcom、杂志中国等杂志商推出的工具,还是陈涛开发的基于Flash工具的杂志模板,解决问题的能力都还相当有限。比如某集团需要在省级杂志帐户下面创建若干地市级杂志帐户,地市级下面再分别创建乡镇级帐户,每个帐户都需要分配若干杂志编辑的角色权限,编辑之间需要能够协同作业……这种分布式的架构是集团用户或行业网站的常规需求,却不是上面这些工具或模板所能解决的。即使以“出杂志”为考量,使用上述工具或模板,离“制作数字杂志像玩搏客那样简单、方便”的目标亦还有很长的一段距离。 第三代数字杂志技术的不足还表现在杂志性能的不够完善上。比如,无论是Xplus、Poco、Zcom还是杂志中国,一开始都曾刻意渲染P2P下载技术,把需要安装专用软件并需要将杂志下载到本地才能阅读说成是最佳的发行与订阅方式。如果当真出于发行与订阅考虑,那么试问,RSS(一种无需下载的发行、订阅方式)岂不更好?显然,这些杂志商都在撒谎。实际情况是,并非“P2P”订阅有多好,而是仅靠“组件+模版”这样的Flash技术还不能较好地支持即时阅读,才不得不祭出“P2P”。要改变这一点,必须使图文并茂、有声有色的Flash杂志能够被“打碎”,同时又能被“拼”回去……这需要Flash技术与网站技术相结合的杂志系统来解决。 四、第四代数字杂志技术 第四代数字杂志技术是Flash技术与网站技术充分结合的数字杂志系统,具有制作、发行、阅读、管理一体化的特点,具有较强的协作性、易用性和可扩展性,而不单单是第三代数字杂志技术那样的一个工具或模版。 首先,第四代数字杂志技术将使数字杂志的表现力与功能更加丰富。用户可自定义杂志界面与表现效果;可自定义即时通讯、在线支付等多种功能;并提供扩展接口,让用户可自己创作更丰富的效果、实现更多的功能;用户创作的效果与功能还能共享。 其次,制作数字杂志就像玩博客那样简单。无需任何专用工具,只要登陆网站,点点选选,然后点击“保存”,就能完成专业效果的数字杂志的制作与发布。对于专业用户,则还可以使用Flash等工具天马行空地自由创作。不管是图片、文字、视频还是动画效果,如果不满意,均可随时重新修改、编辑。更重要的是,还支持多方协作。大型的数字杂志往往需要多个栏目编辑协作完成,第四代数字杂志技术具有相应的权限分配机制。 第三,发行数字杂志基于一个庞大的共享的网络。数字杂志系统采用分布式架构,系统可以与任何企业、个人网站或门户网站友好地整合,每套系统既是独立的制作、发行、阅读平台,同时资源又可互相聚合、共享。打个比方,如果有一万个网站使用了这套系统,那么任何一个网站制作的杂志,都将在一万个网站上同时发布;登陆任何一个网站,都能阅读到其它一万个网站上的杂志;只要在其中任何一个网站上注册,就能订阅所有自己想要的杂志。 第四,集团部署的完美解决方案。系统具有多级帐户管理功能,这一点特别适合集团用户进行信息化部署或开设行业数字杂志门户。以某省电力集团公司为例,只需在省级系统建立一套数字杂志系统,就能划分出《企业简报》、《企业文化内刊》、《光荣榜》等若干部分,然后创建各地市级单位的帐户,再由地市级单位向镇乡一级发放帐户,就能实现内情上报下达,互为交通。 第五,阅读和订阅数字杂志就像浏览网页一样方便。第四代数字杂志采用文件分割与多线程预载技术,无需安装任何专用软件,登陆网站就能阅读杂志,而且前面阅读,后面预加载,确保了多媒体文件的流畅阅读。第四代数字杂志采用自动打包技术,服务器端能将杂志自动打包成一个exe执行文件,点击“下载”,就能将数字杂志下载到本地收藏。第四代数字杂志采用RSS订阅等技术,网站注册用户只需点击“订阅”,该杂志有新杂志出版时,站内短信或电子邮件就会自动通知该用户。 第六,系统具有强大的管理功能。杂志制作人员可对杂志设置不同的阅读权限,比如仅限注册用户阅读、仅限付费用户阅读、仅在本站发布、点击广告方能阅读等。系统管理员可对杂志进行过滤或推荐,比如仅选取本站杂志、选取所有共享杂志、仅选取汽车杂志等。系统还有广告管理、读者管理等一系列的强大功能。 以杭州潜龙动漫技术公司李小明、蒋桥、杨宜强等人为骨干的www.05m.com第五媒体发展联盟在第四代数字杂志技术的研发上已整整历时两年,目前已完成杂志生成、共享聚合、多线程预载、自动打包等全部核心技术的开发,并在杭报集团旗下《风景名胜》杂志社等单位进行了试用,效果良好。接下去,他们将着重在一些用户体验性的功能上进行深化、细化、优化。可以预见,该系统一旦大规模推广,必将对整个数字杂志产业的价值观与技术理念都产生深刻的影响,彻底颠覆目前Xplus、Poco、Zcom、杂志中国等运营商所主导的以运营商为中心的制作工具+推送平台的产业模式。

1,076

社区成员

发帖
与我相关
我的任务
社区描述
PowerBuilder 相关问题讨论
社区管理员
  • 基础类社区
  • WorldMobile
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧