<?xml version="1.0" encoding="GB2312"?>  
<rss version="2.0" 
xmlns:dc="http://purl.org/dc/elements/1.1/" 
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" 
xmlns:admin="http://webns.net/mvcb/" 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> 
  
<channel> 
<title><![CDATA[东方之子]]></title> 
<link>http://www21.bokee.com/index.html</link> 
<description><![CDATA[学习的最高境界是将学过的东西忘得一干二净！
剩下的便是精髓！]]></description> 
<dc:language>zh-cn</dc:language> 
<dc:creator>jianghan180@163.com</dc:creator> 
<dc:date>2007-03-03T17:07:04Z</dc:date> 
<admin:generatorAgent rdf:resource="http://blog.bokee.com.com" /> 

<item> 
<title><![CDATA[Linux Shell]]></title> 
<link>http://www21.bokee.com/6138007.html</link> 
<description><![CDATA[<font color="#0000ff">友好阅读版本 </font><a href="http://www.linuxsir.org/main/?q=node/135" target="_blank"><font color="#000000">http://www.linuxsir.org/main/?q=node/135</font></a><br /><br /><br />本文的内容来源于 MUO 的 Basics 部分，其原始英文版可以从这里获得<a href="http://www.mandrakeuser.org/docs/" target="_blank"><font color="#000000">http://www.mandrakeuser.org/docs/</font></a>。中文版来自吴晓光的CMUO <a href="http://dummy.linux.net.cn/~xgwu/cmuo/" target="_blank"><font color="#000000">http://dummy.linux.net.cn/~xgwu/cmuo/</font></a>。MUO 是 Mandrake Linux（<a href="http://www.mandrakelinux.com/" target="_blank"><font color="#000000">http://www.mandrakelinux.com/</font></a>）为用户提供的入门手册，其内容实用并且实时更新，非常适合初学者做入门参考。与常见的各种Linux教程不同，MUO介绍给Linux初学者的是学习Linux的方法而非对某个系统的描述，这对各种有着千差万别的Linux发行版的学习尤为重要。本文编译整理时对相关章节做了相应的删改处理，去掉了针对Mandrake Linux的部分内容。<br /><br />使用 Shell<br />以下将介绍并解释基本的 shell 命令和机制。<br />第一篇：超级工具／Terminals，xterms 和 Shells<br />超级工具<br />您或许听过这样的论调：命令行(the mommand line)早就已经过时了，那东西神秘兮兮的，等等。有些人甚至觉得操作系统中应该没有这些命令才好。<br />事实是上，您可以不懂任何 shell ，就能使用 Linux 。您启动系统后可以直接进入 X Window ，最后在 X Window 下关机。<br />我坚信，用 Linux 而不懂 shell ，就象开车只会用头档(first gear)一样。当然，最初看起来，直接而简单，在大多数情况下都管用。但速度慢，而且无法真正体验驾驶的乐趣。<br />对，命令行很有趣。就象用一大堆收集到的积木，竟可以完成许多意想不到的创举，一些极其复杂的工作，只需几行命令就可以解决。这是因为，在 Unix 中，shell 可不是简单的命令解释器（典型的有 Windows 中的 DOS ），而是一个全功能的编程环境。<br />这并不意味着 shell 非常容易学通，您知道，好事多磨，这还是要花点工夫的。;-) 但请相信我，这绝对值得。您在很短时间内，就能被一大帮门外汉吹捧为 Unix wizard（奇才） 。*grin*<br />为了说明 shell ，这里需要一些背景知识。<br />Terminals, xterms 与 Shells<br />追溯到 Unix 诞生的那个年代，当时还没有现在流行的&amp;quot;个人计算机&amp;quot;。被称为计算机的机器，还是吞吐磁带与 magnetic memory （用术语'core'来表示系统 memory）的庞然大物。DEC 公司（现在的 Compaq）推出的 PDP-11 ，体积小（被称为 mini）而且价格底，在大学中引起了巨大的反响，很多学校直到那时才买得起一台计算机（PDP-11 物美价廉，只有 10000$）。<br /><br />这些机器的操作系统由汇编语言、机器语言写成，所以运行起来效率很高，但都无法移植(unportable)。每家计算机公司都给自己的机器配上独有的操作系统，然后再销售。<br /><br />这种笨拙的作法很快就被人们意识到了，于是就开始兴建一个可以在不同品牌机器上运行的操作系统。1969 年，Ken Thompson 开始写后来成为 Unix 的第一行代码。（Thompson 曾经参加了一个项目：MULTICS，Unix 是与这有关的一个玩笑词） 其实，Dennis Ritchie 为这个新的操作系统设计了一种新的编程语言-- C 语言后，事情才真正开始。<br /><br />虽然 Unix 的效率不及原来的操作系统，但有三个突出的优点：可以任意移植到其他机器，其中的 C 语言大大简化了编程，而且这些都 free 。很快，全美国的大学都忙着开始为机器安装 Unix 。<br /><br />终端（Terminals）<br /><br />Unix 是可以在许多种机器上运行的操作系统，但人们又如何使用这些机器呢？他们是通过哑终端来连接到这些机器，也就是用键盘、显示器及足够的 electronics （电子元件）组成的机器与中央计算机(central computer)相连。在这些终端上，用户可以敲字符（teletypy），这就是字符串'tty'表示终端设备文件，和'getty'命令的名称来历。<br /><br />您可能会问，现在这些东西都在哪儿。 这些终端的厂家无法达成一项最终标准，这导致每种牌子的终端都有各自的键盘布局、各自的在屏幕上显示字符的方法、发送或接收什么信号表示什么字符、控制代码等等。<br /><br />为了避免这些混乱，就创建了一个含有所有不同终端特性的(capability)文件，这就是'termcap'。用一个工具打开'/etc/termcap'瞧瞧，可别吓着了 ;-) 。<br /><br />Linux 终端大多数用'vt100'或'linux'作为终端类型。<br />xterms<br /><br />在八十年代初期，产生了一个 Unix 的图形子系统-- the X Window System 。九十年代早期，为了更好地实现基于 Intel 的 Unix 类系统上（如FreeBSD、NetBSD、Linux）的应用，产生了一个系统分支-- XFree86 。<br /><br />X Window 中一个很大的好处是可以运行多个虚拟(virtual)终端。甚至在 X Window 下就有这么个应用程序--'xterm'。您将发现'xterm'和'virtual terminal'在很多情况下都是一样的。有的地方说'打开一个 xterm'，其实您不是非要用'xterm'程序，其他的终端模拟器(terminal emulator)，如 rxvt、konsole、aterm、eterm、wterm 等等，一样有效。<br /><br />终端模拟器（又称为虚拟终端）通过伪(pseudo) tty 设备-- pty 与系统相连，并且使用自己的显示标准-- xterm 。这导致不同的终端模拟器可能在一些按键或程序上存在细小的差别，这取决于模拟器多大程度上遵守了'xterm'的显示标准。<br /><br />Shells<br /><br />为了在终端中运行程序，需要 shell 。shell 是操作系统的一部分，用来与用户打交道，并且可以用来协调各个命令。<br /><br />第一个真正的 Unix shell -- 'sh'，亦称为'Bourne shell'，诞生于 1975 年，作者是 Steve Bourne 。很快，出现了其他 shell ，如基于原始'Bourne shell'的'ksh'、'zsh'，后者常用作专属 Unixes 系统中的标准 shell ；也有一些从 C 语言中衍生出来的 shell ，如'csh'或'tcsh'。<br /><br />在 Linux 中，标注的 shell 是'bash'，即 the GNU Bourne-Again Shell （有点玩笑的味道……）。这个 shell 功能非常强大（甚至有人觉得太庞大了），压缩的 man page 就有 50 KB 。<br /><br />Shell 起步<br /><br />首先，有一点小说明：在平常应用中，建议您不要用'root'帐号运行 shell ，如果您还是新手，这一点尤其要注意。作为普通用户，不管您有意还是无意，都无法破坏系统；但如果是'root'，那就不同了，只要敲几个字母，就可能导致灾难性后果。<br /><br />当您登入系统或打开一个 xterm 窗口，首先看到的是提示符(prompt)。Red Hat Linux 的标准提示符包括了您的用户名、登入的主机名（没有设置的话，是'localhost'）、当前所在的目录(working directory)、提示符号：<br /><br />[tom@belbo tom]$<br /><br />我以用户名'tom'登入名为'belbo'的主机，当前在我的 home 目录--'/home/tom'中。'root'的提示符：<br /><br />[root@belbo root]#<br /><br />除了不同的用户名外，提示符号由'$'变成了'#'。根据 Bourne shell 的传统，普通用户的提示符以'$'结尾，而超级用户用'#'。<br /><br />提示符的每个部分都可以定制，您在后面将有更深的了解。<br /><br />要运行命令的话，您只要在提示符后敲进命令，然后在按 &amp;lt;ENTER&amp;gt; 键。shell 将在其路径中（详情见后）搜索这个命令，找到以后就运行，并在终端里输出相应的结果（如果有的话），命令结束后，再给出新的提示符：<br /><br />[tom@belbo tom]$ whoami<br />tom<br />[tom@belbo tom]$<br /><br />顺带指出，当您敲 ENTER 时，光标(cursor)在哪里并不要紧，因为 shell 总是会整行地读取。<br /><br />基本的命令有：'ls'（list directory ，列出目录内容）、'cp'（copy ，复制）、'mv'（move / rename ，移动／重命名），'cd '（change directory ，改变目录），这些命令后面都可以跟上一帮可选项，这方面 man page 有详细的介绍（man ls, man mv 等等）。<br />在您动身前往 shell 领地前，这里有几个术语(terminology)的简短说明。命令可能带一些可选项（options）、参数（arguments）：<br /><br />mv -i file dir<br /><br />其中'-i'是命令'mv'的一个可选项，而'file'和'dir'则是参数。所有可选项在该命令的 man page 都中有详细的介绍（此例中用 man mv），而参数则由您提供。可选项决定命令如何工作，而参数则用于确定命令作用的目标。<br /><br />到目前为止，介绍得有点象许多人厌恶轻视的 DOS shell ，但伴随着下面的介绍，您将会有新的体验。<br /><br />第二篇：自动补齐／命令行的历史记录／编辑命令行／可用的 Shell 快捷方式<br /><br />Unix （及后继者 Linux）在命令行下面诞生，因此，Unix 中的命令行有许多非常实用的功能。在本篇中，我们将来作一些了解。<br /><br />自动补齐<br /><br />如何用'cd'（改变目录，change directory）最快地从您当前所在的 home 目录跳到'/usr/src/redhat/'呢？<br /><br />cd /u&amp;lt;TAB&amp;gt;sr&amp;lt;TAB&amp;gt;r&amp;lt;TAB&amp;gt;<br /><br />这称为'命令行自动补齐'(automatic command line completion)，这在平常应用中是不可缺少的。让我们仔细看看这个例子：<br /><br />cd /u&amp;lt;TAB&amp;gt;<br /><br />扩展成了 cd /usr/ ，很简单吧。下面的<br /><br />cd /u&amp;lt;TAB&amp;gt;sr&amp;lt;TAB&amp;gt;<br /><br />扩展为 cd /usr/src/ 。如果您只敲了cd /u&amp;lt;TAB&amp;gt;s&amp;lt;TAB&amp;gt;，'/usr'下匹配的（'cd /u*/s*'）三个子目录将列出供您选择：'/usr/sbin'、'/usr/share'和'/usr/src'。<br /><br />因此，&amp;lt;TAB&amp;gt; 键可以很方便地用于根据前几个字母，来查找匹配的文件或子目录。比如，ls /usr/bin/zip&amp;lt;TAB&amp;gt; 将列出所有'/usr/bin'下面，以字符串'zip'开头的文件或子目录。当然，完成这类任务还有更厉害的命令，但这个方法确实很管用。<br /><br />另外，碰到长文件名时就显得特别方便。假设您要安装一个名为'boomshakalakwhizbang-4.6.4.5-i586.rpm'的 RPM 包，您输入 rpm -i boom&amp;lt;TAB&amp;gt; ，如果目录下没有其他文件能够匹配，那 shell 就会自动帮忙补齐。<br /><br />cd /u&amp;lt;TAB&amp;gt;sr&amp;lt;TAB&amp;gt;l&amp;lt;TAB&amp;gt;<br /><br />将扩展成 cd /usr/src/linux ，并等待继续。'/usr/src'中有两个匹配的目录：'/usr/src/linux-[...]'、'/usr/src/linux'。如何告诉 shell 您想要后面的那个呢？只要跟一个斜线（/ ，slash），就可以选择后面的那个了。<br /><br />假如您不确定是'/usr/src/linux/Documentation'还是'/usr/src/linux/documentation'。而您知道，Linux 是区分大小写的。如果已经仔细读过前面部分的话，您想到可以用：<br /><br />cd /u&amp;lt;TAB&amp;gt;sr&amp;lt;TAB&amp;gt;l&amp;lt;TAB&amp;gt;/d&amp;lt;TAB&amp;gt;<br /><br />扩展成了'/usr/src/linux/drivers/'，因此应该是'Documentation'(大写的'D')。<br /><br />这种补齐对命令也有效：<br /><br />[tom@belbo tom]$ gre&amp;lt;TAB&amp;gt;<br /><br />grecord grefer grep<br /><br />[tom@belbo tom]$ gre<br /><br />在这里 shell 将列出所有以字符串'gre'开头的已知命令。<br /><br />命令行的历史记录<br /><br />通过按向上方向键，您可以向后遍历近来在该控制台下输入的命令。用向下方向键可以向前遍历。与 SHIFT 键连用的话，您还可以遍历以往在该控制台中的输出。您也可以编辑旧的命令，然后再运行。<br /><br />按 &amp;lt;CTRL r&amp;gt; 后，shell 就进入&amp;quot;reverse-i(ncremental)-search&amp;quot;（向后增量搜索）模式。现在输入您要找的命令的首字母：<br /><br />(reverse-i-search)`':. 敲入 'i'可能会变成：<br /><br />(reverse-i-search)`i': isdnctrl hangup ippp0<br /><br />如果您再按 &amp;lt;ENTER&amp;gt; 键，上面的命令将再次执行。而如果您按了向右、向左方向键或 &amp;lt;ESC&amp;gt; ，上面的命令将回到普通的命令行，这样您就可以进行适当编辑。<br /><br />编辑命令行<br /><br />通过光标和功能键（Home、End 等键），您可以浏览并编辑命令行，如果您需要，还可以用键盘的快捷方式来完成一般的编辑：<br /><br />l &amp;lt;CTRL k&amp;gt;：删除从光标到行尾的部分<br /><br />l &amp;lt;CTRL u&amp;gt;：删除从光标到行首的部分<br /><br />l &amp;lt;ALT d&amp;gt;：删除从光标到当前单词结尾的部分<br /><br />l &amp;lt;CTRL w&amp;gt;：删除从光标到当前单词开头的部分<br /><br />l &amp;lt;CTRL a&amp;gt;：将光标移到行首<br /><br />l &amp;lt;CTRL e&amp;gt;：将光标移到行尾<br /><br />l &amp;lt;ALT a&amp;gt;：将光标移到当前单词头部<br /><br />l &amp;lt;ALT e&amp;gt;：将光标移到当前单词尾部<br /><br />l &amp;lt;CTRL y&amp;gt;：插入最近删除的单词<br /><br />l &amp;lt;!$&amp;gt;：重复前一个命令最后的参数。<br /><br />例如：您用命令 mkdir peter/pan/documents/tinkerbell 新建了一个目录，现在您向用命令'cd'进入该目录，您可以用 cd !$，shell 将把前一个命令'mkdir'的参数添加到现在的'cd'后面。<br /><br />当您更深入了解Linux后，将看到这些快捷方式在其他应用程序下输入时，有时也有效，比如，在浏览器中的输入框中。<br /><br />可用的 Shell 快捷方式<br /><br />Red Hat Linux 带有不少快捷方式，其中一部分是 bash 原来就有的，而还有一些则是为您预先设置的（在后面您将看到如何设置）。<br /><br />由于 home 目录是每位用户的活动中心，许多 Unix 对此有特殊的快捷方式。<br /><br />'~'就是您的 home 目录的简写形式。我们假设您在其他目录，想把一个名为'sometext'的文件复制到您 home 目录下的 'docs'子目录中。除了输入：<br /><br />cp sometext /home/myusername/docs<br /><br />您还可以用简写：<br /><br />cp sometext ~/docs<br /><br />理论上，这也可以应用在命令'cd'上。无论当前路径在哪里，cd ~ 将回到您的 home 目录。其实还可以简化，只要键入 cd ，就可以返回 home 目录了。<br /><br />Red Hat Linux 为您提供了一些预先设置的快捷方式（称为'别名'，aliases），比如：<br /><br />l ll ：将执行'ls -l -k'（以长格式列出目录内容，包括一些文件属性，并以 KB 而不是 byte 为单位显示文件大小）<br /><br />l ls ：将执行'ls -F --color=auto'（列出目录内容，加上文件类型标识，并使用颜色）<br /><br />现在，您应该对 shell 及一些快捷方式有了进一步的了解，下面我们来看看除了应用一些简单的命令，shell 还能作什么。<br /><br />第三篇：命令的排列／命令的任务调度／命令的替换<br /><br />命令的排列<br /><br />现在您将看到一些常用的命令排列。您可能想在一行中给出所有命令，然后就可以把注意力转移到其他地方。没问题，shell 允许您在不同的命令之间，放上特殊的排列字符(queuing characters) 。这儿将介绍最常用的两种。<br /><br />请注意，为了看起来更清楚，我在这些字符两旁加了空格。而在实际应用中，您不一定要这么做，'ls -a ; du -hs'和'ls -a;du -hs'的效果是一样的。<br /><br />command1 ; command2<br /><br />先执行 command1 ，不管 command1 是否出错，接下来执行 command2 。<br /><br />例如：<br /><br />ls -a ; du -hs<br /><br />将先在屏幕上列出目录中的所有内容，然后列出所有目录及其子目录所占磁盘大小。<br /><br />command1 &amp;amp;&amp;amp; command2<br /><br />只有当 command1 正确运行完毕后，才执行 command2 。<br /><br />例如：<br /><br />ls -a bogusdir &amp;amp;&amp;amp; du -hs<br /><br />将返回 ls: bogusdir: No such file or directory ，而'du'则根本没有运行（这是因为您没有'bogusdir'目录）。如果您将符号换成了';'，'du'将被执行。<br /><br />为了进一步说明';'和'&amp;amp;&amp;amp;'的区别，及一般命令排列的用处，下面举一个经典的例子：Linux 内核的编译和安装。<br /><br />要编译、安装 Linux ，您需要执行一串命令：'make dep'、'make clean'、'make bzImage'、'make modules'、'make modules_install'和'make install'。如果要等一个命令完成后，再输入下一个，再等，再输入，……，那就太麻烦了。另一方面，每个命令只有当前面的命令都正确执行完毕后，才能开始执行。如果您用';'来排列命令，则即使有命令执行失败，后面的也照常运行，最后，您可能在'/boot'目录下得到一个有问题的内核映像(image)。而用'&amp;amp;&amp;amp;'：<br /><br />make dep &amp;amp;&amp;amp; make clean &amp;amp;&amp;amp; make bzImage &amp;amp;&amp;amp; make modules &amp;amp;&amp;amp; make modules_install &amp;amp;&amp;amp; make install<br /><br />不需要中途打断，就可以编译内核及其模块，并完成后面的安装。<br /><br />命令的任务调度<br /><br />当您在终端里运行一个命令或开启一个程序时，终端要等到命令或程序运行完毕后，才能再被使用。在 Unix 中，我们称这样的命令或程序在前台(foreground)运行。如果您想在终端下运行另一个命令，则需要再打开一个新的终端。<br /><br />但这里还有一个更优雅的办法，称为任务调度(jobbing)或后台(backgrounding)。当您运用任务的调度或将命令置于后台，终端就立即解放了，这样一来，终端立即就可以接受新的输入。为实现这样的目的，您只需在命令后面添加一个 &amp;amp; ：<br /><br />gqview &amp;amp;<br /><br />告诉 shell 将图片查看器'GQview'放到后台去执行（即当成 job 来运行）。<br /><br />命令 jobs 将告诉您，在这个终端窗口中，运行着哪些命令与程序：<br /><br />jobs<br /><br />[1]+ Running gqview &amp;amp;<br /><br />当您要关闭终端窗口时，这一点就很重要，因为关闭终端将导致所有在其中运行的任务都将被中止，在此例中，如果您关闭了终端，由这个终端开启的 GQview 程序也将被关闭。<br /><br />但如何将前台运行的一个程序放到后台去？没问题：<br /><br />gqview<br /><br />&amp;lt;CTRL z&amp;gt;<br /><br />[2]+ Stopped gqview<br /><br />bg<br /><br />[2]+ gqview &amp;amp;<br /><br />组合键 &amp;lt;CTRL z&amp;gt; 将挂起终端中正在运行的程序，然后您就可以用 bg 命令将其放到后台去执行。<br /><br />请注意，在后台运行图形应用程序有时候是有用处的，这样可以在终端下显示这个程序的出错信息，虽然这对您可能没有直接的帮助，当如果碰到了麻烦，向别人询问时，这些出错提示就有用武之地了。<br /><br />一些图形程序，很可能还处在测试期(Beta)，尽管在后台执行，也会在终端中输出一些信息。如果您对此不满，可以用下面命令：<br /><br />command &amp;amp;&amp;gt;/dev/null &amp;amp;<br /><br />这不仅将程序送到后台执行，还将其输出发到'/dev/null'文件。'/dev/null'是系统的&amp;quot;碎纸机&amp;quot; (shredder)，所有送到那里的信息都将消失殆尽。<br /><br />命令的替换<br /><br />命令替换(Command substitution)是一项很实用的功能。我们假设，您想看看 XFree86 文档中的 'README.mouse'文件，但您不知道这个文件的位置。但您是位机灵的用户，已经听说了'locate'命令，也安装了'slocate'包，您就可以用：<br /><br />locate README.mouse<br /><br />发现那个文件在'/usr/X11R6/lib/X11/doc'。现在您就可以在终端里用'less'或在文件管理器中进入那个目录然后读取文件。而命令替换可以给您带来一些便捷：<br /><br />less $(locate README.mouse)<br /><br />一步到位。命令'locate README.mouse'的输出(= /usr/X11R6/lib/X11/doc/README.mouse)作为'less'的参数，然后就可以显示文件内容了。<br /><br />这种机制的语法是：<br /><br />command1 $(command2)<br /><br />除了'$( )'，您还可以用后引号(backquote)：<br /><br />command1 `command2`<br /><br />这样虽然可以减少输入，但可读性差，而且很容易就和没有替换功能的一般单引号混淆。我更欣赏前一种方法，但这最终起决于您。<br /><br />这里有另外一个例子。我们假设，您打算结束一个名为'rob'的程序。您先得用命令'pidof'找出相应的进程号(Process ID)，然后以这个 PID 为参数，运行'kill'命令，这样就可以结束'rob'程序。除了用：<br /><br />pidof rob<br /><br />567<br /><br />kill 567<br /><br />您还可以试试：<br /><br />kill `pidof rob`<br /><br />怎么样，效率有所提高吧？<br /><br />在下一篇中，我将接着介绍 shell 的另外两种实用的机制：文件名匹配、输出重定向。<br /><br />第四篇：文件名匹配／输出重定向<br /><br />文件名匹配<br /><br />文件名匹配使得您不必一一写出名称，就可以指定多个文件。您将用到一些特殊的字符，称为通配符(wildcards)。<br /><br />假设您想用'rm'命令删除目录下所有以字符串'.bak'结尾的文件。除了在'rm'后跟上所有文件名作为参数，您还可以用通配符'*'：<br /><br />rm *.bak<br /><br />'*'可匹配一个或多个字符。在本例中，您告诉 shell 将命令'rm'的参数扩展到&amp;quot;所有以'*.bak'结尾的文件&amp;quot;，shell 就将扩展后的参数告诉'rm'命令。<br /><br />您将看到，shell 在命令执行前，就将读取并解释命令行。正是因为这个，您才可以将通配符用于 shell 命令的参数中。<br /><br />让我们更进一步地来认识通配符'*'。假定您有个目录，其中含文件'124.bak'、'346.bak'及'583.bak'。您想只保留文件'583.bak'，可以用：<br /><br />rm *4*.bak<br /><br />shell 就将'*4*.bak'扩展成&amp;quot;所有含'4'并以'.bak'结尾的字符串&amp;quot;。<br /><br />注意到 rm 4*.bak 无法工作，因为这匹配的是以'4'开头的文件。由于目录中没有这样的文件，shell 将这个模式扩展为空的字符串，故'rm'将返回出错信息：<br /><br />rm: cannot remove `4*.bak': No such file or directory<br /><br />如果您想保留文件'345.bak'，而删除'124.bak'和'583.bak'。这看起来有些难度，因为被删文件的名称除了后缀其他都不同。但幸运的是，您可以用不含有来指定文件：<br /><br />rm *[!6].bak<br /><br />这将被读为：除了以'6.bak'结尾的文件，删除其他所有以'.bak'结尾的文件。您必须将取反号(negation sign)与取反字符（这里是 6）放到括号中，不然的话，shell 会将惊叹号(exclamation mark)解释成历史记录替换的开始(the beginning of a history substitution)。取反号在本篇介绍的所有匹配模式中都有效。<br /><br />请注意：通配符'*'与取反号连用，很容易产生问题。猜猜<br /><br />rm *[!6]*.bak<br /><br />表示什么？这个命令将删除所有文件，甚至包括名称中包含'6'的文件。如果您将通配符'*'放到了取反号前面和后面，实际上取反号将失效，因为 shell 将其解释为&amp;quot;所有名称中任何位置都不含该字符的文件&amp;quot;。在我们的例子里，只有文件'666.bak'不符合该模式。<br /><br />第二个通配符是问号(question mark)：'?'。在匹配时，一个问号只能代表一个字符。为了示范其用途，我们在上例的假设中添加两个新文件：'311.bak~'和'some.text'。现在，列出所有在点号后有四个字符的文件：<br /><br />ls *.????<br /><br />问号通配符能够有效地避免上面提到的'取反号陷阱'(negation trap)：<br /><br />rm *[!4]?.*<br /><br />将扩展成&amp;quot;所有除了点号前倒数第二个字符为'4'的文件&amp;quot;，也就是只保留文件'346.bak'。<br /><br />您可能会问，有没有其他匹配方式？到目前为止，您只看到了在指定位置匹配唯一字符的方法。但其实您也可以这样：<br /><br />ls [13]*<br /><br />将列出所有以字符'1'或'3'开头的文件；在我们的例子中，文件'124.bak'、'311.bak~'和'346.bak'匹配。注意到您必须用中括号将匹配的模式括起来，否则模式只匹配以字符串'13'开头的文件。<br /><br />接下来，您将高兴地看到还可以定义匹配的范围：<br /><br />ls *[3-8]?.*<br /><br />将列出所有点号前倒数第二个字符落在'3'到'8'范围的文件。在我们的例子中，匹配的文件是'346.bak'和'583.bak'。<br /><br />引用 shell 的特殊字符<br /><br />但是，上面的那些机制存在一个缺点：shell 总在命令执行前，试着进行扩展。有时候，会变得很棘手：<br /><br />l 文件名包含特殊字符。假设您在那个目录中还有一个名为'!56.bak'的文件。下面试图进行模式匹配：<br /><br />rm !*<br /><br />rm<br /><br />rm: too few arguments<br /><br />shell 将'!*'解释成历史记录的替换（加入前一个命令的所有参数），而不是匹配方式。<br /><br />l 命令本身带特殊字符作参数。一些 Linux 下的命令行工具，比如 (e)grep、sed、awk、find 及 locate ，都使用自己的正则表达式(regular expressions)。这些表达式与模式匹配看起来惊人地相似，但在某些地方又有所不同。<br /><br />但为了使这些特殊命令生效，shell 就不能先将其当作模式匹配来解释：<br /><br />find . -name [1-9]* -print<br /><br />find: paths must precede expression<br /><br />应该是：<br /><br />find . -name '[1-9]*' -print<br /><br />./346.bak<br /><br />./124.bak<br /><br />./583.bak<br /><br />./311.bak~<br /><br />您可以通过反斜线(back slash)来引用特殊字符，比如 ! 、$ 、? 或空格：<br /><br />ls \!*<br /><br />!56.bak<br /><br />或者用（单）引号：<br /><br />ls '!'*<br /><br />!56.bak<br /><br />请注意，要看清楚引号应该放在什么位置。命令 ls '!*' 将查找名为'!*'的文件，这是由于通配符也在引号间，所以只能依照字面来解释。<br /><br />输出重定向<br /><br />Unix 的理念是汇集许多小程序，每个东东都有特殊的专长。复杂的任务不是由大型软件完成，而是运用 shell 的机制，组合许多小程序共同完成。重定向就在其中发挥着重要的作用。<br /><br />在多个命令间重定向<br /><br />这要通过管道(pipe)，由管道符号｜来标识。语法是：<br /><br />command1 | command2 | command3 等等<br /><br />这种格式您一定已经见到过了。管道经常将一个程序的输出送到'more'或'less'来阅读。<br /><br />ls -l | less<br /><br />其中，第一个命令提供目录内容，第二个则将其以翻页的方式显示。更复杂的例子如：<br /><br />rpm -qa | grep ^x | less<br /><br />第一个命令给出所有已安装的 RPM 包，第二个则将其过滤(filter：'grep')，只剩下以'^x'开头的包，第三个命令则将结果以翻页的方式显示。<br /><br />重定向至文件<br /><br />有时，您希望将命令的输出结果保存到文件中，或以文件内容作为命令的参数。这可以通过'&amp;gt;'和'&amp;lt;'来实现。<br /><br />command &amp;gt; file<br /><br />将 command 的输出保存到 file 中，这将覆盖 file 中的内容：<br /><br />ls &amp;gt; dirlist<br /><br />将当前目录的内容保存到'dirlist'文件。<br /><br />command &amp;lt; file<br /><br />将 file 内容作为 command 的输入：<br /><br />sort &amp;lt; dirlist &amp;gt; sdirlist<br /><br />将文件'dirlist'的内容送到命令'sort'，然后再将排序后的结果送到文件'sdirlist'。当然，您也可以一步到位：<br /><br />ls | sort &amp;gt; sdirlist<br /><br />一种特殊的方式是'command 2&amp;gt; file'。这将 command 执行的出错信息送到 file 中。这个您到时候会需要……<br /><br />另一种操作符是'&amp;gt;&amp;gt;'，这将输出添加到已存在的文件中：<br /><br />echo &amp;quot;string&amp;quot; &amp;gt;&amp;gt; file<br /><br />将 string 加到文件 file 中。这是不打开文件而完成编辑的好办法！<br /><br />但是，'&amp;lt;'和'&amp;gt;'操作符都有一个重要的限制：<br /><br />command &amp;lt; file1 &amp;gt; file1<br /><br />将删除 file1 的内容，而<br /><br />command &amp;lt; file1 &amp;gt;&amp;gt; file1<br /><br />却可以很好地工作，将加工过的 file1 内容加回到文件中。<br /><br />是不是有点多？;-) 不必惊慌，您完全可以按照自己的速度，一步步地来学习。别忘了，实践是最好的学习方法……<br /><br />熟知了许多 shell 的机制后， 您可能急着想知道如何来定制环境。在后面的两篇中，您将得到这方面的启示。在最后一篇中，还有一段如何处理 shell 出错信息的常见问答(FAQ)，及一些配置技巧。<br /><br />第五篇：bash 配置文件／提示符／改变 $PATH<br /><br />bash 配置文件<br /><br />在您的 home 目录下，运行<br /><br />ls .bash*<br /><br />您将看到这些文件：<br /><br />l .bash_history ：记录了您以前输入的命令，<br /><br />l .bash_logout ：当您退出 shell 时，要执行的命令，<br /><br />l .bash_profile ：当您登入 shell 时，要执行的命令，<br /><br />l .bashrc ：每次打开新的 shell 时，要执行的命令。<br /><br />请注意后两个的区别：'.bash_profile'只在会话开始时被读取一次，而'.bashrc'则每次打开新的终端（如新的 xterm 窗口）时，都要被读取。按照传统，您得将定义的变量，如 PATH ，放到'.bash_profile'中，而象 aliases（别名）和函数之类，则放在'.bashrc'。但由于'.bash_profile'经常被设置成先读取'.bashrc'的内容，您如果图省事的话，就把所有配置都放进'.bashrc'。<br /><br />这些文件是每一位用户的设置。系统级的设置存储在'/etc/profile'、'/etc/bashrc'及目录'/etc/profile.d'下的文件中。但您得习惯用各自的配置文件：编辑不需要'root'权限，还可以使您的设置更有个性。当系统级与用户级的设置发生冲突时，将采用用户的设置。<br /><br />读取'.bashrc'的内容，您如果要省点事的话，就把您所有的配置都放进'.bashrc'。<br /><br />上面的这些文件是每位用户的设置，系统级的设置存储在'/etc/profile'、'/etc/bashrc'及目录'/etc/profile.d'下的文件中。您最好习惯使用各自的配置文件：编辑不需要'root'权限，还可以使您的设置更具个性。当系统级与用户级的设置发生冲突时，将优先采用用户的设置。<br /><br />提示符<br /><br />每次当您打开一个控制台(console)或 xterm 时，最先看到的就是提示符(prompt)，类似于：<br /><br />account@hostname ~ $<br /><br />在默认设置下，提示符将显示您的用户名、主机名（默认是'localhost'）、当前所在目录（在 Unix 中，'~'表示您的 home 目录）。<br /><br />按照传统，最后一个字符可以标识您是普通用户（$），还是'root'（#）。<br /><br />您可以通过 $PS1 变量来设置提示符。命令<br /><br />echo $PS1<br /><br />将显示当前的设定。其中可用字符的含义在 man bash 的'PROMPTING'部分有说明。<br /><br />如何才能完成理想的设置呢？对于健忘的初学者来讲，默认设定有些不友好，因为提示符只显示当前目录的最后一部分。如果您看到象这样的提示符<br /><br />tom@localhost bin $<br /><br />您的当前目录可能是'/bin'、'/usr/bin'、'/usr/local/bin'及'/usr/X11R6/bin'。当然，您可以用<br /><br />pwd （输出当前目录，print working directory）<br /><br />能不能叫 shell 自动告诉您当前目录呢？<br /><br />当然可以。这里我将提到的设定，包括提示符，大都包含在文件'/etc/bashrc'中。您可以通过编辑各自 home 目录下的'.bash_profile'和'.bashrc'来改变设置。<br /><br />在 man bash 中的'PROMPTING'部分，对这些参数(parameter)有详细说明。您可以加入一些小玩意，如不同格式的当前时间，命令的历史记录号，甚至不同的颜色。<br /><br />在'~/.bashrc'中，我喜欢的设定是：<br /><br />PS1=&amp;quot;\[\033[1m\][\w]\[\033[0m\] &amp;quot;<br /><br />'root'在'~/.bashrc'中的设定 是：<br /><br />PS1=&amp;quot;\[\033[0;31m\][\w]\[\033[0m\] &amp;quot;<br /><br />这样我得到的提示符就是：<br /><br />[/usr/bin]<br /><br />当用'root'时，变成：<br /><br />[/usr/bin]<br /><br />我已经除掉了主机名和用户名，因为我用不着这些。但我首先想一眼就能看出我的身份是普通用户还是'root'。注意到，普通用户的提示符可以是黑底白字，或白底黑字。<br /><br />要在终端上获得恰当的颜色调配， 您可以编辑下面这个脚本color ，赋予执行权限（chmod +x color），然后再运行。<br /><br />#!/bin/bash<br /><br />#<br /><br /># This file echoes a bunch of color codes to the<br /><br /># terminal to demonstrate what's available. Each<br /><br /># line is the color code of one forground color,<br /><br /># out of 17 (default + 16 escapes), followed by a<br /><br /># test use of that color on all nine background<br /><br /># colors (default + 8 escapes).<br /><br />#<br /><br />T='gYw' # The test text<br /><br />echo -e &amp;quot;\n 40m 41m 42m 43m\<br /><br />44m 45m 46m 47m&amp;quot;;<br /><br />for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \<br /><br />'1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \<br /><br />' 36m' '1;36m' ' 37m' '1;37m';<br /><br />do FG=${FGs// /}<br /><br />echo -en &amp;quot; $FGs \033[$FG $T &amp;quot;<br /><br />for BG in 40m 41m 42m 43m 44m 45m 46m 47m;<br /><br />do echo -en &amp;quot;$EINS \033[$FG\033[$BG $T \033[0m&amp;quot;;<br /><br />done<br /><br />echo;<br /><br />done<br /><br />echo<br /><br />一种更适当的设定：<br /><br />PS1=&amp;quot;\u: \w\\$ &amp;quot;<br /><br />这样，提示符就变成：<br /><br />user_name: /usr/bin$<br /><br />您可以通过命令 export 来测试不同的设置（比如，export PS1=&amp;quot;\u: \w\\$ &amp;quot;）。如果找到了适合的提示符，就将设置放到您的'.bashrc''中。这样，每次打开控制台或终端窗口时，都会生效。<br /><br />您甚至可以给提示符设定主题(theme)，也就是搭配不同的颜色，使其看起来象很棒的 ol <br />的 C64 提示符。如果您对此感兴趣，可以看一下 <br />Bashish（<a href="http://hem.passagen.se/arnognulf/index2.html）。" target="_blank"><font color="#000000">http://hem.passagen.se/arnognulf/index2.html）。</font></a><br /><br />改变 $PATH<br /><br />'$PATH'与'$PS1'一样，也是环境变量。输入<br /><br />set<br /><br />将列出所有当前定义的环境变量。<br /><br />您看到的这些环境变量在 shell 的配置文件中定义，可能是用户自己的配置文件，也可能是由'root'通过'/etc'下面的系统级文件定义的。如果您使用 X ，更多的一些变量将由 X 、您的窗口管理器或桌面环境的启动文件配置。<br /><br />如果对这些设置不很清楚，您暂时最好不要随便改动。了解如何改变 $PATH 变量很有用，因为这个变量决定了 shell 将到哪些目录中寻找命令或程序。如果要执行的命令的目录在 $PATH 中，您就不必输入这个命令的完整路径，直接输入命令就可以了。一些第三方软件没有将可执行文件放到 Linux 的标准目录中。因此，将这些非标准的安装目录添加到 $PATH 是一种解决的办法。此外，您也将看到如何处理一般的环境变量。<br /><br />首先，作为惯例，所有环境变量名都是大写。由于 Linux 区分大小写，这点您要留意。当然，您可以自己定义一些变量，如'$path'、'$pAtH'，但 shell 不会理睬这些变量。<br /><br />第二点是变量名有时候以'$'开头，但有时又不是。当设置一个变量时，您直接用名称，而不需要加'$'：<br /><br />PATH=/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin<br /><br />要获取变量值的话，就要在变量名前加'$'：<br /><br />echo $PATH<br /><br />/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin<br /><br />否则的话，变量名就会被当作普通文本了：<br /><br />echo PATH<br /><br />PATH<br /><br />处理 $PATH 变量要注意的第三点是：您不能只替换变量，而是要将新的字符串添加到原来的值中。在大多数情况下，您不能用'PATH=/some/directory'，因为这将删除 $PATH 中其他的所有目录，这样您在该终端运行程序时，就不得不给出完整路径。所以，只能作添加：<br /><br />PATH=$PATH:/some/directory<br /><br />这样，PATH 被设成当前的值（以 $PATH 来表示）＋新添的目录。<br /><br />到目前为止，您只为当前终端设置了新的 $PATH 变量。如果您打开一个新的终端，运行 echo $PATH ，将返回旧的 $PATH 值，而看不到您刚才添加的新目录。因为您先前定义的是一个局部环境变量（仅限于当前的终端）。<br /><br />要定义一个全局变量，使在以后打开的终端中生效，您需要将局部变量输出(export)，可以用'export'命令：<br /><br />export PATH=$PATH:/some/directory<br /><br />现在如果您打开一个新的终端，输入 echo $PATH ，也能看到新设置的 $PATH 了。请注意，命令'export'只能改变当前终端及以后运行的终端里的变量。对于已经运行的终端没有作用。<br /><br />为了将目录永久添加到您的 $PATH ，只要将'export'的那行添加到您的'.bash_profile'文件中。<br /><br />请不要在'.bashrc'中设置 PATH ，否则会导致 PATH 中目录的意外增长。您每次打开一个新的 shell ，'.bashrc'都会作用。所以如果在该文件中添加目录，您每次打开一个终端，目录又会被添加。这将导致 PATH 变量由于目录复制，不断地增长。<br /><br />第六篇：命令的别名、Shell 函数／从这里出发／Shell 常见问题<br /><br />命令的别名、Shell 函数<br /><br />记住所有的命令及各自带的可选项，然后每次一一输入，这确实有点枯燥。但幸运的是，您可以为常用命令定义快捷方式。这些快捷方式可以用较简单的命令别名(alias)，或复杂一些的 shell 函数的语法来定义。<br /><br />命令的别名<br /><br />例如，我用下面的命令来上传 MUO 中的文件：<br /><br />rsync -e ssh -z -t -r -vv --progress /home/tom/web/muo/rsmuo/docs muo:/www/mandrakeuser/docs<br /><br />显然，如果每次都要逐一输入，那我早晚会变成木头。因此我在'~/.bashrc'中定义了别名：<br /><br />alias upmuo='rsync -e ssh -z -t -r -vv --progress /home/tom/web/muo/rsmuo/docs muo:/www/mandrakeuser/docs'<br /><br />现在，我只要输入 upmuo 就可以完成上传任务了。<br /><br />定义别名的语法是：<br /><br />alias shortcut='command'<br /><br />命令中有空格的话 ，就需要用引号（如在命令与可选项间就有空格）。请注意，您可以用单引号或双引号，但他们是有区别的。<br /><br />单引号将剥夺其中的所有字符的特殊含义，而双引号中的'$'（参数替换）和'`'（命令替换）是例外。这意味着，如果您想在别名中应用变量或命令的替换，就得用双引号。看一下上面的例子，我在'.bashrc'中定义了一个称为 MUOHOME 的变量：<br /><br />export MUOHOME=$HOME/web/muo/rsmuo/docs<br /><br />要在上面的别名中用上这个变量，我就必须用双引号：<br /><br />alias upmuo=&amp;quot;rsync -e ssh -z -t -r -vv --progress $MUOHOME muo:/www/mandrakeuser/docs&amp;quot;<br /><br />否则，别名将查找一个名为'$MUOHOME'的目录或文件。<br /><br />您可以用'alias'在命令行快速地创建别名，或将命令放到各自的'~/.bashrc'，或放到系统级的'/etc/profile.d/alias.sh'中（而在 Mandrake Linux 8 以前的版本里，用的是'/etc/bashrc'）。要删除一个别名，只要输入：unalias alias 。运行 alias 将列出您系统中所有定义的别名。<br /><br />如果看一下'~/.bashrc'和'/etc/profile.d/alias.sh'，您会发现系统已经定义了一些别名。您可以为同一个命令定义多个别名。当然，您得先确认别名与其他程序名不同，比如象 alias rm='ls -l' 这样的就不能工作。您可以在命令行输入这些快捷方式，测试一下。如果 shell 找不到相同名称的命令，那您就可以将其用作别名了。<br /><br />以下别名可能有用（不要忘了引号！） ：<br /><br />l alias rpmq='rpm -qa | grep' ：现在 rpmq string 就将列出所有名称中含有 string 的已安装 RPM 包，<br /><br />l alias ls='ls -ho --color | more' ：ls 将以彩色分页方式列出文件，文件大小以 KB为单位，<br /><br />l alias use='du --max-depth=1 | sort -n | more' ：use 将子目录按大小排好，并以分页方式列出，<br /><br />目录的别名也可以是可移动的介质：alias dlm='/mnt/cdrom/RedHat/RPMS/' 。<br /><br />提示：将有相似功能的别名以相同字母开头，比如将所有目录的别名以'd'作开头，这样有助于记忆。<br /><br />我相信，您将会用到这些功能。<br /><br />Shell 函数<br /><br />写 shell 函数涉及到了 shell 脚本，这超出了我们讨论的范围（也不在我的掌握范围之内 ;-)）。事实上，shell 函数属于 shell 脚本，但可以在同一 shell 下被预加载(preload)和执行（而一般的 shell 脚本至少要打开一个 sub-shell）。<br /><br />通过 shell 函数，您可以做很多 aliases 无法完成的事情。下面就是一个例子：<br /><br />function apros() { apropos $1 | egrep -v '(3|\(n\)'; }<br /><br />定义了一个新命令，称为'apros'。apros name 将先执行'apropos name'（即在 man page 中搜索命令），然后将得到的输出送到管道（|），接着用'egrep'过滤，排除第'3'和第'n'章节的 man page ，这个命令可能没什么大用处，但可以整理'apropos'命令的输出。<br /><br />函数允许您在函数内部任何位置，使用运行时的参数。而别名，则只允许在命令行尾放一个参数（比如前面的别名'rpmq'）。<br /><br />'$1'就是位置参数(positional parameter)，表示函数第一个参数的位置标识符。依此类推，还有'$2'等。<br /><br />function apros() { apropos $1 | egrep -v &amp;quot;\($2&amp;quot;; }<br /><br />如果您这样运行'apros'命令：<br /><br />apros name man_section_number<br /><br />这个命令将搜索标题中含 name 的 man pages ，但排除 man_section_number 部分：<br /><br />apros menu 3<br /><br />将搜索标题含'menu'的 man page ，但排除第三章节（关于编程的）。注意到您得引用（quote） 两次，而且还用到了双引号：<br /><br />l 您必须引用'egrep'的搜索模式，这样可以不至于被 shell 误解。<br /><br />l 您必须用双引号，这样第二个参数才能被正确解释。<br /><br />l 您必须引用圆括号，这样使'egrep'按字面意思对待对待参数。<br /><br />是不是有点意思？;-)<br /><br />shell 函数的处理类似于别名：将其放到您的'.bashrc'文件，这样就能永久生效了。<br /><br />从这里出发<br /><br />我们谈到的只是 shell 的一个开头。掌握了shell 脚本，您就可以做很多事情，比如将任务自动化，纠正别人脚本中的错误，按照您的习惯定制 Linux 系统。如果您打算学习某种复杂的编程语言，那 shell 脚本也是一个很好的开端，因为基本概念都是类似的。<br /><br />BASH Programming - Introduction HOW-TO：<br /><br /><a href="http://www.ibiblio.org/mdw/HOWTO/Bash-Prog-Intro-HOWTO.html" target="_blank"><font color="#000000">http://www.ibiblio.org/mdw/HOWTO/Bas...tro-HOWTO.html</font></a><br /><br />将更深入这些主题，并且将把您带到 shell 编程的世界。然后可以继续阅读我强烈推荐的 Advanced Bash-Scripting Guide（<a href="http://www.ibiblio.org/mdw/LDP/abs/html/index.html），作者是" target="_blank"><font color="#000000">http://www.ibiblio.org/mdw/LDP/abs/h...??，作者是</font></a> Mendel Cooper 。<br /><br />如果您偏好纸书，那我推荐 S. Veeraraghavan 的《Teach Yourself Shell Programming》，Sams 出版社。我倒觉得 O'Reilly 公司由 Newham/Rosenblatt 写的《Learning the bash Shell》，不过尔尔，但这可能只有我这么看 ;-) 。<br /><br />除了这些，就是练习，练习，再练习。阅读其他人写的 shell 脚本，看看他们在做什么，怎么做，为什么那样做。<br /><br />请不要用'root'测试您的脚本。Have fun 。]]></description> 
<guid isPermaLink="false">6138007@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-03-03T17:07:01Z</dc:date> 
</item> 
<item> 
<title><![CDATA[Linux初学者Patch使用指南]]></title> 
<link>http://www21.bokee.com/6132215.html</link> 
<description><![CDATA[<p>　 简介 </p><p>　　 本文的目的是向Linux新手介绍一种无价的资源，Larry Wall的patch程序。patch是用来查找文件之间差异的GNU diff命令的一个接口；diff有很多选项，但是该命令最常用的用途是用来生成一个文件，该文件中列出了内容发生改变的行，显示两个原始文件、修改过的行以及由于内容没有变化而忽略掉的行。patch典型地用于把一个目录下的源代码文件更新到新的版本，从而就避免了下载整个新的源代码档案的必要。下载一个有效的patch仅仅需要下载发生变化的那些代码行就可以了。 </p><p>　　 patch最初源自十年前，那时网络带宽的限制促进了patch的发展，然而和当时的很多Unix工具一样，直到现在，patch还在广泛应用。在Dr. Dobb之旅的2月份的程序员杂志中，Larry Wall对早期的patch做了一些很有趣的说明： </p><p>　　 DDJ:顺便问一下，patch和diff哪个出现的早？ </p><p>　　 LW:从很长一段时间来说，diff出现地比较早。我想diff大约比patch早10年出现，一回想起来，我就纳闷为什么没有人早些想到使用patch呢？ </p><p>　　 但是我想我知道这中间的原因。这很大程度上是心理因素使然。当开发出diff时，程序员增加了一个e选项，我想就是这个选项的原因，该选项后来滋生为一个ed脚本，因此大家都会对自己说，&amp;quot;嗯，如果我想自动使用diff，那么我就使用这个选项。&amp;quot;因此从来都没有人编写一个计算机程序来获取其它格式的输出并使用这些结果。或者是那些设计diff的人员，或者是那些使用diff格式而受益的人员太沉迷其中了，因为你可以对那些已经修改过的内容使用diff操作并让这些内容正常工作都是很容易的。 </p><p>　　 现在回想起来，这个问题是显而易见的。但是平心而论，与其说这是一个天才的灵感的闪现，还不如说这是自信心的体现。我开发出rn的第一个版本，然后继续为它编写补丁，这整个事情就是一团乱麻。你不可能强制用户使用补丁，因为他们可以手工完成这些工作。因此，他们就会省略一些自己认为不必要的工作，他们把新的修改加诸于原来的程序之上，因此而使得程序混乱。我编写补丁，这样就没有人找借口说这很难了。 </p><p>　　 我不清楚是否事实就是如此，但是多年以来，我一直对别人讲patch对于计算机文化的影响比rn和Perl的影响都要大。现在Internet的速度比原来有大幅度的提高，把整个发行版本分散到世界各地也变得更加简单，似乎只有在开发者之间才需要传送补丁。我已经很多年没有传送Perl的patch工具包了。我认为虽然patch整体上的重要性在逐渐降低，但是仍然是开发者交流思想的一种方法。但是就那一段时间而言，patch真正在相当大的程度上都影响了软件的开发方式。 </p><p>　　 Larry Wall针对patch对于计算机业界总体上重要性正在降低的评价可能是正确的，但是在自由软件世界中，patch仍然是一种必不可少的工具。无处不在的patch使得新手和非程序员能够简单地参与软件的alpha测试和beta测试，这对于整个计算机业界是十分有益的。 </p><p>　　 在我留意到在Linux内核邮件列表中会周期性的出现这样一件事情时就产生了写这篇文章的念头。大约每三个月就会有人张贴要求把Linux内核源代码的发行版本独立出来的文章，据说这是因为有些人只对i386的代码和IDE的磁盘驱动感兴趣，他们并不想为每个内核发行版本都下载Alpha、Sparc等等的文件和众多的SCSI驱动程序。这篇文章后面紧跟的是一些耐心的回复文章（有些文章则并没有耐心），大部分文章都是在讨论原来的使用有关patch来更新内核源代码。接着Linus Torvalds就会再次声明自己没有兴趣投身于这种把内核源程序切割成小块的繁杂的劳动，但是如果有人愿意，他们可以自由地开展这项独立的工程。到现在为止都没有志愿者出现。我并不想谴责那些内核黑客不能耐心等待，却把生活变得复杂；我猜想直接使用内核工作可能比检查整个内核的发行版本方案要更加有趣、更富有挑战性。下载11M的内核源程序包可是件非常耗费时间的事情（对于那些按照时间上网的人来说，这是很昂贵的），但是内核patch才只有几十K大小，很少会超过1M。我的硬盘上的2.1.99开发内核源程序经过patch的升级，已经升级到了2.1.119版本，我怀疑如果我紧随内核的发展而不断升级，那么也许我就要完整地下载每一个发行版本了。 </p><p /><p><br />　　 使用patch </p><p>　　 patch附带有一个很好的帮助，其中罗列了很多选项，但是99%的时间只要两个选项就能满足我们的需要： </p><p>　　 patch -p1 &amp;lt; [patchfile] </p><p>　　 patch -R &amp;lt; [patchfile] (used to undo a patch) </p><p>　　 -p1选项代表patchfile中文件名左边目录的层数，顶层目录在不同的机器上有所不同。要使用这个选项，就要把你的patch放在要被打补丁的目录下，然后在这个目录中运行path -p1 &amp;lt; [patchfile]。来自Linux内核patch的一个简短的引用可以这样实现： </p><p>　　 diff -u --recursive --new-file v2.1.118/linux/mm/swapfile.c linux/mm/swapfile. c--- v2.1.118/linux/mm/swapfile.c Wed Aug 26 11:37:45 1998 +++ linux/mm/swapfile.c Wed Aug 26 16:01:57 1998 @@ -489,7 +489,7 @@ </p><p>　　 int swap_header_version; </p><p>　　 int lock_map_size = PAGE_SIZE; </p><p>　　 int nr_good_pages = 0; - char tmp_lock_map = 0; + unsigned long tmp_lock_map = 0; </p><p>　　 应用来自本段中使用-p1开关拷贝的patch可以有效地减短patch定位的路径；patch会查找当前目录下一个名为/mm的子目录，接着应该会在这儿发现swapfile.c文件，然后等待打补丁。在这个过程中，以破折号（“-”号，译者注）开始的行会被一个以加号（“+”号，译者注）开始的行代替。一个典型的patch会包含对多个文件的更新，每个部分中都由对两个版本的文件运行diff -u命令的输出结果组成。 </p><p>　　 patch在操作时把自己的输出结果显示在屏幕上，但是这种输出通常都滚屏太快，来不及观看。原来准备patch的文件名为*.orig，新的patch文件会覆盖这个初始文件名。 </p><p>　　 打补丁的问题 </p><p>　　 使用不同版本的patch问题来源可能不同，所有的版本在网络上都是可用的。Larry Wall近年来已经不再做很多工作来更新patch了，这可能是由于他最后发行的一个版本在大部分情况下都能正常运行。最近几年以来，一直是GNU项目的FSF程序员发行新版本的patch。他们首先修订有问题的patch，但是我最近一直使用没有问题的2.5版本（这是Debian2.0的发行版本号）。过去，我的2.1版本也一直运行的很好。当前的GNU patch的版本可以从GNU FTP站点上获取，然而大部分人都只使用他们Linux发行版中所提供的版本。 </p><p>　　 让我们假定你已经对一个目录下的源程序文件进行了patch修补工作，但是patch并没有清晰地发挥作用。这可能会偶然发生，在打补丁的过程中会显示错误信息，其中带有行号，说明哪一个文件出现了问题。有时错误是很明显的，例如缺少了分号，这种错误可以不费多大力气就能改正。另外一种可能是从patch部分删除了产生问题的部分，但是这样根据所涉及到的文件的不同可能会正常工作，也可能不能正常工作了。 </p><p>　　 另外一种常见的错位为：假设你有一个未使用tar打包的内核源程序文件，在/linux/arch/下浏览各个子目录时你会发现各种机器体系结构子目录，例如alpah、sparc等等。如果你和大多数Linux用户一样，使用的是Intel的处理器（或者是Intel系列），你可以决定删除这些目录，这些目录对于编译你特殊的内核并不需要，只是白白占用了磁盘空间。一段时间之后发行了一个新的内核patch，此时试图进行patch操作，当它发现不能找到自己打补丁需要的Alpha或者PPC文件，就会停顿下来。幸运的是patch在这些地方允许用户参与，它会询问&amp;quot;Skip this patch?&amp;quot;回答&amp;quot;y&amp;quot;，patch就可以按照正确的路径继续执行。也许你需要回答这个问题很多次，因此允许自己不需要的目录保留在磁盘上是一种很好的方法。 </p><p>　　 给内核打补丁的技巧 </p><p>　　 很多Linux用户使用patch都主要是给内核源程序打补丁，因此有一些技巧可以使用。可能最简单的方法是使用shell脚本给内核打补丁，这可以在内核源程序树中的/scripts子目录中找到。这种方便的、编写良好的脚本是由Nick Holloway在1995年编写的；两年以后，Adam Sulmicki增加了多种压缩格式的支持，包括*.bz、*.bz2、compress、gzip和无格式文本（也就是已经解压的patch）。这个脚本假定在你使用新版本的patch时，你的内核源程序是在/usr/src/linux目录中。这些缺省值可以通过这种格式的命令行开关覆盖：patch-kernel [sourcedir [patchdir] ]。如果任何一部分的patch失败，对内核打补丁的过程都会失败，但是如果patch清晰地起作用，它就会调用find，这会删除所有的patch留下的*.orig文件。 </p><p>　　 如果你准备查看命令的输出，或者可能你希望保留*.orig文件直到你确定打过补丁的源程序编译已经通过，按照我的经验，直接运行patch（正如前面介绍的一样，patch位于内核源程序的最高目录）是很可靠的。为了避免对patch进行解压，在使用之前，可以使用这样一个技巧： </p><p>　　 gzip -cd patchXX.gz | patch -p1 </p><p>　　 或者 </p><p>　　 bzip2 -dc patchXX.bz2 | patch -p1 </p><p>　　 在使用patch之后，可以使用find程序来检测被拒绝的文件： </p><p>　　 find . -name *.rej </p><p>　　 第一次使用这个命令，语法可能有些不清楚。点号（“.”）说明find应该查找当前目录并递规查找当前目录之下的所有子目录。记住，点号前后都应该有一个空格。通配符&amp;quot;*&amp;quot;号前面的反斜线把星号转义出来，以免shell会搞混，星号是有其它意义的。如果find找到了任何的*.rej文件，它就会把文件名打印到屏幕上。如果没有任何输出find就退出了，那么就差不多能确定patch正确发挥作用了。 </p><p>　　 find的另外一个工作是删除*.orig文件： </p><p>　　 find . -name *.orig -print0 | xargs -0r rm -f </p><p>　　 这个命令敲起来相当麻烦，可以使用一个新的shell别名来代替这个命令。在你的~/.bashrc文件中类似这样的一行： </p><p>　　 alias findorig find . -name *.orig -print0 | xargs -0r rm -f </p><p>　　 可以允许你只输入findorig就可以调用前面的命令。如果别名命令的定义中包含空格，那么就必须使用单引号。为了不用先退出再重新登陆就可以使用一个新的别名，可以在命令行中敲如~/.bashrc。 </p><p>　　 附加内容和结束语 </p><p>　　 在撰写本文时，我刚好把自己的机器从2.1版本使用patch升级到了2.5版本。这两个版本都是来自现在的FSF/GNU维护人员。马上我就注意到2.5版本默认的输出已经改变了，屏幕上显示的信息变少了。原来在patch检测进行修补的行号时显示的Larry Wall的&amp;quot;...hmm&amp;quot;不见了。2.5版本的输出只剩下诸如&amp;quot;patching file [filename]&amp;quot;之类的信息了，而没有早期版本显示的那么多信息了。无可否认，信息滚屏太快，根本无法阅读，但是输出可以重定向到一个文件中供以后使用。这种变化不会影响程序的功能，但是减少了人为的成分。在我看来，使用诸如原来的&amp;quot;...hmm&amp;quot;信息和源代码中的注释一样，对于提醒用户程序是显示执行的工作的结果是很有价值的，这就像人在呼吸一样，而不应该使用一些毫无结果的位集合。通过对patch命令行增加--verbose开关可以恢复原来的显示内容，但是我相信很多用户既不会注意到这个选项，也不会不辞辛劳地输入这个选项。2.1和2.5版本的另外一个不同是除非patch给出了-b选项，否则不能创建*.orig备份文件。 </p><p>　　 对于那些对软件和内核&amp;quot;前沿&amp;quot;bug报告测试和提供测试报告不感兴趣的人来说，patch并不是必须的，但是通常大部分Linux世界里有趣的开发都是属于这个范畴的。获得patch的使用方式并不困难，这种努力可以得到充分的回报。&amp;nbsp; <br /></p><p />]]></description> 
<guid isPermaLink="false">6132215@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-02-28T21:56:02Z</dc:date> 
</item> 
<item> 
<title><![CDATA[FILE STORAGE HARDWARE AND DISK ORGANIZATION ]]></title> 
<link>http://www21.bokee.com/6126922.html</link> 
<description><![CDATA[<h2 align="center"><a name="Hard"><font size="6">Hard</font></a><font size="6"> Disk Drive Basics</font></h2><p>A hard disk is a sealed unit containing a number of platters in a stack. Hard disks may be mounted in a horizontal or a vertical position. In this description, the hard drive is mounted horizontally. </p><p>Electromagnetic read/write heads are positioned above and below each platter. As the platters spin, the drive heads move in toward the center surface and out toward the edge. In this way, the drive heads can reach the entire surface of each platter. </p><p>&amp;nbsp;</p><h3><a name="Making Tracks">Making Tracks</a></h3><p>On a hard disk, data is stored in thin, concentric bands. A drive head, while in one position can read or write a circular ring, or band called a track. There can be more than a thousand tracks on a 3.5-inch hard disk. Sections within each track are called sectors. A sector is the smallest physical storage unit on a disk, and is almost always 512 bytes (0.5 kB) in size.</p><p>The figure below shows a hard disk with two platters. </p><p><b>Figure 3-1</b> Parts of a Hard Drive </p><p><img height="248" src="http://www.ntfs.com/images/recover-hard-drive.gif" width="360" border="0" /></p><p>The structure of older hard drives (i.e. prior to Windows 95) will refer to a cylinder/ head/ sector notation. A cylinder is formed while all drive heads are in the same position on the disk. The tracks, stacked on top of each other form a cylinder. This scheme is slowly being eliminated with modern hard drives. All new disks use a translation factor to make their actual hardware layout appear continuous, as this is the way that operating systems from Windows 95 onward like to work. </p><p>To the operating system of a computer, tracks are logical rather than physical in structure, and are established when the disk is low-level formatted. Tracks are numbered, starting at 0 (the outermost edge of the disk), and going up to the highest numbered track, typically 1023, (close to the center). Similarly, there are 1,024 cylinders (numbered from 0 to 1023) on a hard disk. </p><p>The stack of platters rotate at a constant speed. The drive head, while positioned close to the center of the disk reads from a surface that is passing by more slowly than the surface at the outer edges of the disk. To compensate for this physical difference, tracks near the outside of the disk are less-densely populated with data than the tracks near the center of the disk. The result of the different data density is that the same amount of data can be read over the same period of time, from any drive head position. </p><p>The disk space is filled with data according to a standard plan. One side of one platter contains space reserved for hardware track-positioning information and is not available to the operating system. Thus, a disk assembly containing two platters has three sides available for data. Track-positioning data is written to the disk during assembly at the factory. The system disk controller reads this data to place the drive heads in the correct sector position. </p><p align="right"><span style="FONT-WEIGHT: 400"><a href="http://www.ntfs.com/hard-disk-basics.htm#Hard">Up</a></span></p><h3><a name="Sectors and Clusters">Sectors and Clusters</a></h3><p>A sector, being the smallest physical storage unit on the disk, is almost always 512 bytes in size because 512 is a power of 2 (2 to the power of 9). The number 2 is used because there are two states in the most basic of computer languages - on and off.</p><p>Each disk sector is labelled using the factory track-positioning data. Sector identification data is written to the area immediately before the contents of the sector and identifies the starting address of the sector. </p><p>The optimal method of storing a file on a disk is in a contiguous series, i.e. all data in a stream stored end-to-end in a single line. As many files are larger than 512 bytes, it is up to the file system to allocate sectors to store the file’s data. For example, if the file size is 800 bytes, two 512 k sectors are allocated for the file.</p><p>A cluster can consist of one or more consecutive sectors. The number of sectors is always an exponent of 2. A cluster could consist of 1 sector (2^0), or, more frequently, 8 sectors (2^3). The only odd number a of sectors a cluster could consist of is 1. It could not be 5 sectors or an even number that is not an exponent of 2. It would not be 10 sectors, but could be 8 or 16 sectors. </p><p>They are called clusters because the space is reserved for the data contents. This process protects the stored data from being over-written. Later, if data is appended to the file and its size grows to 1600 bytes, another two clusters are allocated, storing the entire file within four clusters. </p><p><b>Figure 3-2</b> Sectors and Clusters</p><p>&amp;nbsp;<img height="211" src="http://www.ntfs.com/images/recover-hard-drive-sectors-and-clusters.gif" width="360" border="0" /></p><p>If contiguous clusters are not available (clusters that are adjacent to each other on the disk), the second two clusters may be written elsewhere on the same disk or within the same cylinder or on a different cylinder - wherever the file system finds two sectors available. A file stored in this non-contiguous manner is considered to be <b>fragmented</b>. Fragmentation can slow down system performance if the file system must direct the drive heads to several different addresses to find all the data in the file you want to read. The extra time for the heads to travel to a number of addresses causes a delay before the entire file is retrieved. </p><p>Cluster size can be changed to optimize file storage. A larger cluster size reduces the potential for fragmentation, but increases the likelihood that clusters will have unused space. Using clusters larger than one sector reduces fragmentation, and reduces the amount of disk space needed to store the information about the used and unused areas on the disk. </p><p>Most disks used in personal computers today rotate at a constant angular velocity. The tracks near the outside of the disk are less densely populated with data than the tracks near the center of the disk. Thus, a fixed amount of data can be read in a constant period of time, even though the speed of the disk surface is faster on the tracks located further away from the center of the disk. </p><p>Modern disks reserve one side of one platter for track positioning information, which is written to the disk at the factory during disk assembly. It is not available to the operating system. The disk controller uses this information to fine tune the head locations when the heads move to another location on the disk. When a side contains the track position information, that side cannot be used for data. Thus, a disk assembly containing two platters has three sides that are available for data.</p><h2 align="center"><font size="6">Master Boot Record (MBR)</font>&amp;nbsp;</h2><p>The Master Boot Record, created when you create the first partition on the hard disk, is probably the most important data structure on the disk. It is the first sector on every disk. The location is always track (cylinder) 0, side (head) 0, and sector 1. </p><p>The Master Boot Record contains the Partition Table for the disk and a small amount of executable code. On x86-based computers, the executable code examines the Partition Table, and identifies the system partition. The Master Boot Record then finds the system partition's starting location on the disk, and loads an copy of its Partition Boot Sector into memory. The Master Boot Record then transfers execution to executable code in the Partition Boot Sector. </p><p><i><b><font color="#ffcc00">Note:</font></b> Although there is a Master Boot Record on every hard disk, the executable code in the sector is used only if the disk is connected to an x86-based computer and the disk contains the system partition. </i></p><p>The <a name="example">example</a> below shows a hex dump of the sector containing the Master Boot Record. The figure shows the sector in two parts: </p><span><ul><li>The first part is the Master Boot Record, which occupies the first 446 bytes of the sector. The disk signature (FD 4E F2 14) is at the end of the Master Boot Record code. </li><li>The second part is the Partition Table. </li></ul></span><pre>  Physical Sector:Cyl 0,Side 0,Sector 1  
  
  00000000:00 33 C0 8E D0 BC 00 7C -8B F4 50 07 50 1F FB FC .3.....|..P.P..  
  00000010:BF 00 06 B9 00 01 F2 A5 -EA 1D 06 00 00 BE BE 07 ................  
  00000020:B3 04 80 3C 80 74 0E 80 -3C 00 75 1C 83 C6 10 FE ...&amp;lt;.t..&amp;lt;.u.....  
  00000030:CB 75 EF CD 18 8B 14 8B -4C 02 8B EE 83 C6 10 FE .u......L.......  
  00000040:CB 74 1A 80 3C 00 74 F4 -BE 8B 06 AC 3C 00 74 0B .t..&amp;lt;.t.....&amp;lt;.t.  
  00000050:56 BB 07 00 B4 0E CD 10 -5E EB F0 EB FE BF 05 00 V.......^.......  
  00000060:BB 00 7C B8 01 02 57 CD -13 5F 73 0C 33 C0 CD 13 ..|...W.._s.3...  
  00000070:4F 75 ED BE A3 06 EB D3 -BE C2 06 BF FE 7D 81 3D Ou...........}.=  
  00000080:55 AA 75 C7 8B F5 EA 00 -7C 00 00 49 6E 76 61 6C U.u.....|..Inval  
  00000090:69 64 20 70 61 72 74 69 -74 69 6F 6E 20 74 61 62 id partition tab  
  000000A0:6C 65 00 45 72 72 6F 72 -20 6C 6F 61 64 69 6E 67 le.Error loading  
  000000B0:20 6F 70 65 72 61 74 69 -6E 67 20 73 79 73 74 65 operating syste  
  000000C0:6D 00 4D 69 73 73 69 6E -67 20 6F 70 65 72 61 74 m.Missing operat  
  000000D0:69 6E 67 20 73 79 73 74 -65 6D 00 00 80 45 14 15 ing system...E..  
  000000E0:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  000000F0:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000100:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000110:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000120:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000130:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000140:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000150:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000160:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000170:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000180:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  00000190:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  000001A0:00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 ................  
  000001B0:00 00 00 00 00 00 00 00 -FD 4E F2 14 00 00       .........N......  
                                                      80 01               ..  
  000001C0:01 00 06 0F 7F 96 3F 00 -00 00 51 42 06 00 00 00 .....?...QB....  
  000001D0:41 97 07 0F FF 2C 90 42 -06 00 A0 3E 06 00 00 00 A....,.B...&amp;gt;....  
  000001E0:C1 2D 05 0F FF 92 30 81 -0C 00 A0 91 01 00 00 00 .-....0......... 
  000001F0:C1 93 01 0F FF A6 D0 12 -0E 00 C0 4E 00 00 55 AA ...........N..U.</pre><h2 align="center"><font size="6">Hard Drive Partition. Partition Table.</font></h2><span><p>The information about primary partitions and an extended partition is contained in the Partition Table, a 64-byte data structure located in the same sector as the Master Boot Record (cylinder 0, head 0, sector 1). The Partition Table conforms to a standard layout that is independent of the operating system. Each Partition Table entry is 16 bytes long, making a maximum of four entries available. Each entry starts at a predetermined offset from the beginning of the sector, as follows: </p><ul><li>Partition 1 0x01BE (446) </li><li>Partition 2 0x01CE (462) </li><li>Partition 3 0x01DE (478) </li><li>Partition 4 0x01EE (494) </li></ul></span><p>The last two bytes in the sector are a signature word for the sector and are always 0x55AA. The next <a href="http://www.ntfs.com/mbr.htm#example">example</a> is a printout of the Partition Table for the disk shown in an example earlier in this chapter. When there are fewer than four partitions, the remaining fields are all zeros. </p><pre>                                                     80 01              .. 
 000001C0:01 00 06 0F 7F 96 3F 00 -00 00 51 42 06 00 00 00 .....?...QB....
 000001D0:41 97 07 0F FF 2C 90 42 -06 00 A0 3E 06 00 00 00 A....,.B...&amp;gt;....
 000001E0:C1 2D 05 0F FF 92 30 81 -0C 00 A0 91 01 00 00 00 .-....0......... 
 000001F0:C1 93 01 0F FF A6 D0 12 -0E 00 C0 4E 00 00 55 AA ...........N..U. </pre><p>The following table describes each entry in the Partition Table. The sample values correspond to the information for partition 1. </p><p>Partition Table Fields</p><center><table style="BORDER-COLLAPSE: collapse" bordercolor="#c0c0c0" cellspacing="0" cols="5" cellpadding="2" width="90%" border="1"><colgroup><col valign="top" width="10%" /><col valign="top" width="10%" /><col valign="top" width="10%" /><col valign="top" width="60%" /><col valign="top" /></colgroup><tbody><tr><th bgcolor="#ebebeb"><p>Byte Offset</p></th><th bgcolor="#ebebeb"><p>Field Length</p></th><th bgcolor="#ebebeb"><p>Sample Value</p></th><th bgcolor="#ebebeb"><p>Meaning</p></th></tr><tr><td><p>00</p></td><td><p>BYTE</p></td><td><p>0x80</p></td><td><p><a href="http://www.ntfs.com/partition-table.htm#Boot Indicator Field">Boot Indicator</a>. Indicates whether the partition is the system partition. Legal values are:<br />00 = Do not use for booting.<br />80 = System partition.</p></td></tr><tr><td><p>01</p></td><td><p>BYTE</p></td><td><p>0x01</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm">Starting Head</a>.</p></td></tr><tr><td><p>02</p></td><td><p>6 bits</p></td><td><p>0x01</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm">Starting Sector</a>. Only bits 0-5 are used. Bits 6-7 are the upper two bits for the Starting Cylinder field.</p></td></tr><tr><td><p>03</p></td><td><p>10 bits</p></td><td><p>0x00</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm">Starting Cylinder</a>. This field contains the lower 8 bits of the cylinder value. Starting cylinder is thus a 10-bit number, with a maximum value of 1023.</p></td></tr><tr><td><p>04</p></td><td><p>BYTE</p></td><td><p>0x06</p></td><td><p><a href="http://www.ntfs.com/partition-table.htm#sec1">System ID</a>. This byte defines the volume type. In Windows&amp;nbsp;NT, it also indicates that a partition is part of a volume that requires the use of the HKEY_LOCAL_MACHINE\SYSTEM\DISK Registry subkey.</p></td></tr><tr><td><p>05</p></td><td><p>BYTE</p></td><td><p>0x0F</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm">Ending Head</a>.</p></td></tr><tr><td><p>06</p></td><td><p>6 bits</p></td><td><p>0x3F</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm">Ending Sector</a>. Only bits 0-5 are used. Bits 6-7 are the upper two bits for the Ending Cylinder field.</p></td></tr><tr><td><p>07</p></td><td><p>10 bits</p></td><td><p>0x196</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm">Ending Cylinder</a>. This field contains the lower 8 bits of the cylinder value. Ending cylinder is thus a 10-bit number, with a maximum value of 1023.</p></td></tr><tr><td><p>08</p></td><td><p>DWORD</p></td><td><p>3F 00 00 00</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm#sec3">Relative Sector</a>.</p></td></tr><tr><td><p>12</p></td><td><p>DWORD</p></td><td><p>51 42 06 00</p></td><td><p><a href="http://www.ntfs.com/partition-table-heads.htm#sec3">Total Sectors</a>.</p></td></tr></tbody></table></center><p /><p>The remainder of this section describes the uses of these fields. Definitions of the fields in the Partition Table is the same for primary partitions, extended partitions, and logical drives in extended partitions.</p><h3><a name="Boot Indicator Field">Boot Indicator Field</a></h3><p>The Boot Indicator field indicates whether the volume is the system partition. On x-86-based computers, only one primary partition on the disk should have this field set. This field is used only on x86-based computers. On RISC-based computers, the NVRAM contains the information for finding the files to load.</p><p>On x86-based computers, it is possible to have different operating systems and different file systems on different volumes. For example, a computer could have MS-DOS on the first primary partition and Windows&amp;nbsp;95, UNIX, OS/2, or Windows&amp;nbsp;NT on the second. You control which primary partition (active partition in FDISK) to use to start the computer by setting the Boot Indicator field for that partition in the Partition Table.</p><h3><a name="sec1"></a>System ID Field</h3><p>For primary partitions and logical drives, the System ID field describes the file system used to format the volume. Windows&amp;nbsp;NT uses this field to determine what file system device drivers to load during startup. It also identifies the extended partition, if there is one defined.</p><p>These are the values for the System ID field:</p><p><b>Table 3-1 </b>System ID Field Values</p><div align="center"><center><table class="data" style="BORDER-COLLAPSE: collapse" bordercolor="#c0c0c0" cellspacing="0" cols="3" cellpadding="2" border="1"><colgroup><col valign="top" width="31" /><col valign="top" width="316" /><col valign="top" /></colgroup><tbody><tr><th bgcolor="#ebebeb"><p>Value</p></th><th bgcolor="#ebebeb"><p>Meaning</p></th></tr><tr><td><p>0x01</p></td><td><p>12-bit FAT primary partition or logical drive. The number of sectors in the volume is fewer than 32680.</p></td></tr><tr><td><p>0x04</p></td><td><p>16-bit FAT primary partition or logical drive. The number of sectors is between 32680 and 65535.</p></td></tr><tr><td><p>0x05</p></td><td><p>Extended partition. See section titled &amp;quot;<a href="http://www.ntfs.com/logdrives.htm">Logical Drives and Extended Partitions</a>,&amp;quot; presented later in this chapter, for more information.</p></td></tr><tr><td><p>0x06</p></td><td><p>BIGDOS FAT primary partition or logical drive.</p></td></tr><tr><td><p>0x07</p></td><td><p>NTFS primary partition or logical drive.</p></td></tr></tbody></table></center></div><p class="spacing"><br /></p><p /><p>Figure&amp;nbsp;presented earlier in this section, has examples of a BIGDOS FAT partition, an NTFS partition, an extended partition, and a 12-bit FAT partition.</p><p>If you install Windows&amp;nbsp;NT on a computer that has Windows 95 preinstalled, the FAT partitions might be shown as unknown. If you want to be able to use these partitions when running Windows&amp;nbsp;NT, your only option is to delete the partitions.</p><p>OEM versions of Windows 95 support the following four partition types for FAT file systems that Windows&amp;nbsp;NT cannot recognize. </p><p><b>Table 3-2 </b>Partition Types</p><div align="center"><center><table style="BORDER-COLLAPSE: collapse" bordercolor="#c0c0c0" cellspacing="0" cols="2" cellpadding="2" border="1"><colgroup><col valign="top" width="30" /><col valign="top" width="318" /></colgroup><tbody><tr><th bgcolor="#ebebeb"><p>Value</p></th><th bgcolor="#ebebeb"><p>Meaning</p></th></tr><tr><td><p>0x0B</p></td><td><p>Primary Fat32 partition, using interrupt 13 (INT 13) extensions.</p></td></tr><tr><td><p>0x0C</p></td><td><p>Extended Fat32 partition, using INT 13 extensions.</p></td></tr><tr><td><p>0x0E</p></td><td><p>Extended Fat16 partition, using INT 13 extensions.</p></td></tr><tr><td><p>0x0F</p></td><td><p>Primary Fat16 partition, using INT 13 extensions.</p></td></tr></tbody></table></center></div><p class="spacing"><br /></p><p /><p>When you create a volume set or a stripe set, Disk Administrator sets the high bit of the System ID field for each primary partition or logical drive that is a member of the volume. For example, a FAT primary partition or logical drive that is a member of a volume set or a stripe set has a System ID value of 0x86. An NTFS primary partition or logical drive has a System ID value of 0x87. This bit indicates that Windows&amp;nbsp;NT needs to use the HKEY_LOCAL_MACHINE\SYSTEM\DISK Registry subkey to determine how the members of the volume set or stripe set relate to each other. Volumes that have the high bit set can only be accessed by Windows&amp;nbsp;NT. </p><p>When a primary partition or logical drive that is a member of a volume set or a stripe set has failed due to write errors or cannot be accessed, the second most significant bit is set. The System ID byte is set to C6 in the case of a FAT volume, or C7 in the case of an NTFS volume. </p><p /><p class="note"><b><font color="#ffcc00">Note</font></b></p><p><i>If you start up MS-DOS, it can only access primary partitions or logical drives that have a value of 0x01, 0x04, 0x05, or 0x06 for the System ID. However, you should be able to delete volumes that have the other values. If you use a MS-DOS-based low-level disk editor, you can read and write any sector, including ones that are in NTFS volumes.</i></p><p>On Windows&amp;nbsp;NT Server, mirror sets and stripe sets with parity also require the use of the Registry subkey HKEY_LOCAL_MACHINE\SYSTEM\DISK to determine how to access the disks.</p>]]></description> 
<guid isPermaLink="false">6126922@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-02-26T15:22:43Z</dc:date> 
</item> 
<item> 
<title><![CDATA[深入浅出硬盘分区表 ]]></title> 
<link>http://www21.bokee.com/6126879.html</link> 
<description><![CDATA[<table style="TABLE-LAYOUT: fixed; WORD-BREAK: break-all" cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><div align="right"><font size="2">流星 发表于 2005-8-15 14:59:06</font></div></td></tr></tbody></table><br /><font size="2"><font face="宋体">&amp;nbsp;&amp;nbsp;&amp;nbsp; 人们在使用电脑时，有时由于异常操作，有时由于病毒侵袭，会导致某个分区消失或硬盘无法启动。究其原因，就是硬盘分区表受损。硬盘分区表可以说是支持硬盘正常工作的骨架.操作系统正是通过它把硬盘划分为若干个分区,然后再在每个分区里面创建文件系统,写入数据文件.本文主要讲述的是分区表的位置,结构以及各个分区表是如何链接起来的.当掌握了这些知识后,即使分区表受到破坏,一样也可以根据残存的数据手工修复分区表，从而修复分区。<br /><br /><b>一.分区表的位置及识别标志</b><br />&amp;nbsp;&amp;nbsp;&amp;nbsp; 分区表一般位于硬盘某柱面的0磁头 1扇区.而第1个分区表(也即主分区表)总是位于(0柱面,1磁头,1扇区),剩余的分区表位置可以由主分区表依次推导出来．分区表有64个字节,占据其所在扇区的[441-509]字节.要判定是不是分区表,就看其后紧邻的两个字节(也即[510-511])是不是 &amp;quot;55AA&amp;quot;,若是,则为分区表．<br /><br /><b>二.分区表的结构</b><br />分区表由4项组成，每项16个字节.共4×16 = 64个字节．每项描述一个分区的基本信息.每个字节的含义如下:<br />分区表项含义</font> </font><table height="151" cellspacing="0" cellpadding="0" width="88%" border="1"><tbody><tr><td align="center" width="50%" height="15"><font face="宋体" size="2">字节</font></td><td align="center" width="50%" height="15"><font face="宋体" size="2">含义</font></td></tr><tr><td align="center" width="50%" height="18"><font face="宋体" size="2">0</font></td><td width="50%" height="18"><font face="宋体" size="2">Activeflag.活动标志.若为0x80H,则表示该分区为活动分区.若为0x00H,则表示该分区为非活动分区.</font></td></tr><tr><td align="center" width="50%" height="18"><font face="宋体" size="2">1,2,3</font></td><td width="50%" height="18"><font face="宋体" size="2">该分区的起始磁头号,扇区号,柱面号磁头号 -- 1字节, 扇区号 -- 2字节低6位,柱面号 -- 2字节高2位 + 3字节</font></td></tr><tr><td align="center" width="50%" height="18"><font face="宋体" size="2">4</font></td><td width="50%" height="18"><font face="宋体" size="2">分区文件系统标志：<br />分区未用: 0x00H. <br />扩展分区: 0x05H, 0x0FH.<br />FAT16分区: 0x06H.<br />FAT32分区: 0x0BH, 0x1BH, 0x0CH, 0x1CH.<br />NTFS分区: 0x07H.</font></td></tr><tr><td align="center" width="50%" height="18"><font face="宋体" size="2">5,6,7</font></td><td width="50%" height="18"><font face="宋体" size="2">该分区的结束磁头号,扇区号,柱面号，含义同上.</font></td></tr><tr><td align="center" width="50%" height="18"><font face="宋体" size="2">8,9,10,11</font></td><td width="50%" height="18"><font face="宋体" size="2">逻辑起始扇区号。表示分区起点之前已用了的扇区数.</font></td></tr><tr><td align="center" width="50%" height="18"><font face="宋体" size="2">12,13,14,15</font></td><td width="50%" height="18"><font face="宋体" size="2">该分区所占用的扇区数.</font></td></tr></tbody></table><br /><font face="宋体" size="2">分区表项有几个字节比较重要，下面分别阐述之： </font><pre><font face="宋体" size="2">1、（1，2，3）字节
    磁头号由（1）字节8位表示，其范围为（0 -- 28 - 1），也即（0 磁头-- 254磁头）。   
扇区号由（2）字节低6位表示，其范围为（0 -- 26 - 1），由于扇区号从1开始，所以其范围是</font></pre><pre><font size="2"><font face="宋体">（1扇区-</font><font face="宋体">63扇区）。柱面号由（2）字节高2位 + （3）字节，共10位表示，其范围为</font></font></pre><pre><font size="2"><font face="宋体">（0 --2 10 - 1），也即</font><font face="宋体">（0 柱面-- 1023柱面）。当柱面号超过1023时，这10位依然表示成1023，</font></font></pre><pre><font face="宋体" size="2">需要注意。（5，6，7）字节含义同上。
</font></pre><pre><font face="宋体" size="2">2、（8, 9, 10, 11）字节  
    如果是主分区表，则这4 个字节表示该分区起始逻辑扇区号与逻辑0扇区（0柱面，0磁头，1扇区）</font></pre><pre><font size="2"><font face="宋体">之差。</font><font face="宋体">如果非主分区表,则这4 个字节要么表示该分区起始逻辑扇区号与扩展分区起始逻辑扇区号之差，</font></font></pre><pre><font face="宋体" size="2">要么为63。</font><font size="2"><font face="宋体">详细情况在后面有所阐述。  
</font><font face="宋体">注意： </font></font></pre><pre><font face="宋体" size="2">1、<font color="#ff0000">扇区上的字节是按左边低位，右边高位的顺序排列的</font>。所以在取值时，需要把字节再反一下，</font></pre><pre><font face="宋体" size="2">让高位字节在左边，低位字节在右边，这一点在读取逻辑起始扇区号和分区大小时需要注意。举个例子:</font></pre><pre><font face="宋体" size="2">第一项的逻辑起始扇区为(3F 00 00 00)，转换为十进制前要先反一下字节顺序，为（00 00 00 3F）</font></pre><pre><font face="宋体" size="2">然后在转换为十进制，即63 .同理分区大小为（3F 04 7D 00），先反为（00 7D 04 3F）再转换为</font></pre><pre><font face="宋体" size="2">十进制，</font><font face="宋体" size="2">即8193087。
</font></pre><pre><font face="宋体" size="2">2、逻辑扇区号与（柱面，磁头，扇区）的相互转换：
令L = 逻辑扇区号，C = 柱面号，H = 磁头号，S = 扇区号。
每道扇区数 =  63
每柱面磁头数 = 255
每柱面扇区数 = 每道扇区数* 每柱面磁头数= 63 × 255= 16065
柱面号下标从0开始。磁头号[0 -- 254]，扇区号[1 -- 63]。
逻辑扇区号下标也从0开始。
(柱面，磁头，扇区)转换成逻辑扇区号的公式为：
<font color="#ff3300">L = C×16065 + H ×63 + S - 1 ;</font>
比如（1柱面，1磁头，1扇区），其逻辑扇区号为：
L = 1×16065 + 1×63 + 1 - 1
= 16128
逻辑扇区号转换成(柱面，磁头，扇区) 公式为：
C = L / 16065
H = (L % 16065) / 63
S = (L % 16065) % 63 + 1
比如逻辑扇区号 16127：
C = 16127 / 16065 = 1
H = (16127 % 16065) / 63 = 0
S = (16127 % 16065) % 63 + 1 = 63
即（1柱面，0磁头，63扇区）
</font></pre><pre><font face="宋体" size="2">3、分区表上有四项，每一项表示一个分区，所以一个分区表最多只能表示4个分区。主分
区表上的4项用来表示主分区和扩展分区的信息。因为扩展分区最多只能有一个，所以硬盘 
最多可以有四个主分区或者三个主分区，一个扩展分区。余下的分区表是表示逻辑分区的。 
这里有必要阐述一点：逻辑区都是位于扩展分区里面的，并且逻辑分区的个数没有限制。
 </font></pre><pre><font face="宋体" size="2">4、分区表所在扇区通常在（0磁头，1扇区），而该分区的开始扇区通常位于（1磁头，1扇区），中间</font></pre><pre><font face="宋体" size="2">隔了</font><font face="宋体" size="2">63 个隐藏扇区。
  </font></pre><font face="宋体"><font size="2"><b>三.分区表链的查找</b><br />&amp;nbsp;　分区表链实际上相当于一个单向链表结构。第一个分区表，也即主分区表，可以有一项描述扩展分区。而这一项就相当于指针，指向扩展分区。然后我们根据该指针来到扩展分区起始柱面的0头1扇区，找到第二个分区表。对于该分区表，通常情况下：第一项描述了扩展分区中第一个分区的信息，第二项描述下一个分区,而这第二项就相当于指向第二个分区的指针，第三项，第四项一般均为0。我们可以根据该指针来到扩展分区中第二个分区起始柱面的0头1扇区，找到第三个分区表。以此类推，只到最后一个分区表。而最后一个分 区表只有第一项有信息,余下三项均为0.相当于其指针为空.所以只要找到了一个分区表就可 以推导找出其后面所有分区表。不过该分区表前面的分区表就不好推导出来了。但令人高兴的是这个链表的头节点，也即主分区表的位置是固定的位于（0柱面, 0磁头, 1扇区）处，我们可以很轻易的找到它，然后把剩下的所有分区表一一找到。 <br />以笔者的硬盘为例:一个主分区（C盘）, 一个扩展分区.扩展分区中有两个逻辑分区（D盘,E盘）其分区表链示意图如下:<br /><img src="http://www21.bokee.com/inc/disk.gif" border="0" /> <br />图一 分区表链示意图 <br /><br />(一).读取（0柱面，0磁头，1扇区）处C盘的主分区表： </font></font><pre><font face="宋体" size="2">[80 01 01 00 0B FE 7F FD 3F 00 00 00 3F 04 7D 00 ]	                                  	  
[00 00 41 FE 0F FE FF FF 7E 04 7D 00 1F 2C B4 00 ]
 
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]

[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]</font></pre><pre><font face="宋体" size="2">第一项：
（80）（01 01 00）（0B）（FE 7F FD ）（3F 00 00 00 ）（3F 04 7D 00）
描述的是C盘的情况。
1.（80）：表示C盘为活动分区。即系统会从C盘启动。
2.（01 01 00）：表示C盘的起始扇区为（0柱面，0磁头，1扇区）。
3.（0B）：表示C盘的文件系统为FAT32。
4．（FE 7F FD）：
(FE) 16  =  (254) 10  (7F) 16  =  (0111 1111) 2  (FD) 16  =  (1111 1101) 2
磁头号：(254) 10；
扇区号：(11 1111) 2  =  (63) 10.
柱面号：(01 1111 1101) 2  =  (509) 10
故C盘结束扇区为（509柱面，254磁头，63扇区）。
5.（3F 00 00 00）：
反向，(00 00 00 3F) 16  =  (63) 10,为C盘起始逻辑扇区号与逻辑0扇区号之差。表示C盘前面已</font></pre><pre><font face="宋体" size="2">有63个</font><font face="宋体" size="2">扇区，这63个扇区为系统隐藏扇区。
6. (3F 04 7D 00)：
反向，(00 7D 04 3F) 16  =  (8193087) 10。表明C盘有8193087个扇区。即（0柱面，1磁头，1扇区）</font></pre><pre><font face="宋体" size="2">至</font><font face="宋体" size="2">（509柱面，254磁头，63扇区）共有8193087个扇区。
</font></pre><pre><font face="宋体" size="2">第二项：
(00）（00 41 FE）（0F）（FE FF FF）（7E 04 7D 00）（1F 2C B4 00）
描述的是扩展分区的情况。
1. (00): 表示该分区不是活动分区。
2. (00 41 FE):
(00) 16  =  (0) 10　 (41) 16  =  (0100 0001) 2  (FE) 16  =  (1111 1110) 2
磁头号：(0) 10；
扇区号：(00 0001) 2  =  (1) 10.
柱面号：(01 1111 1110) 2  =  (510) 10
所以扩展分区的起始扇区为（510柱面，0磁头，1扇区）。
3. (0F): 表示该分区为扩展分区。
4. (FE FF FF):
(FE) 16  =  (254) 10  (FF) 16  =  (1111 1111) 2  (FF) 16  =  (1111 1111) 2;
磁头号：(254) 10；
扇区号：(11 1111) 2  =  (63) 10.
柱面号：(11 1111 1111) 2  =  (1023) 10
但这是不准确的，因为当柱面号的真实值超过1023时，表示柱面号的10位也依然是1023。

5. (7E 04 7D 00):
反向，(00 7D 04 7E) 16  =  (8193150) 10. 表示扩展分区的起始扇区号为8193150，即</font></pre><pre><font face="宋体" size="2">(510 柱面，0磁头，1扇区)。这是真实准确的，我一般都用这一项来定位分区起点。
6. (1F 2C B4 00):
反向, (00 B4 2C 1F) 16  =  (11807775) 10. 表示扩展分区共有11807775个扇区。通过上面得到</font></pre><pre><font size="2"><font face="宋体">的起点和</font><font face="宋体">分区的大小，可以推导出扩展分区的结束位置：8193150 + 11807775 = 20000925号扇区，</font></font></pre><pre><font face="宋体" size="2">即</font><font face="宋体" size="2">（1244 柱面，254磁头，63扇区）。
</font></pre><p><font face="宋体" size="2">二．查找D盘分区表 　根据上面的信息，第二个分区表，也即D盘分区表在（510柱面，0磁头，1扇区）</font></p><p><font face="宋体" size="2">处。读取该扇区，得到分区表如下： </font></p><pre><font face="宋体" size="2">[00 01 41 FE 0B FE FF 7B 3F 00 00 00 BF A3 5D 00 ]
[00 00 C1 7C 05 FE FF FF FE A3 5D 00 21 88 56 00 ]
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
</font></pre><pre><font face="宋体" size="2">第一项：
（00）（01 41 FE）（0B）（FE FF 7B）（3F 00 00 00 ）（BF A3 5D 00）
  描述的是D盘的情况。
1.（00）：表示D盘不是活动分区。
2.（01 41 FE）：
  (01) 16  =  (1) 10  (41) 16  =  (0100 0001) 2  (FE) 16  =  (1111 1110) 2.
磁头号：(1) 10；
扇区号：(00 0001) 2  =  (1) 10.
柱面号：(01 1111 1110) 2  =  (510) 10;
故D盘开始扇区为（510柱面，1磁头，1扇区）。
3.（0B）：表示D盘的文件系统为FAT32。
4．（FE FF 7B）：
(FE) 16  =  (254) 10 。 (FF) 16  =  (1111 1111) 2  (7B) 16  =  (0111 1011) 2.
磁头号：(254) 10；
扇区号：(11 1111) 2  =  (63) 10.
柱面号：(11 0111 1011) 2  =  (891) 10
故D盘结束扇区为（891柱面，254磁头，63扇区）。
5.（3F 00 00 00）：
反向，(00 00 00 3F)16  =  (63)10,为D盘起始逻辑扇区号（510柱面，1磁头，1扇区）与扩展分区</font></pre><pre><font size="2"><font face="宋体">起始逻</font><font face="宋体">辑扇区号（510柱面，0磁头，1扇区）之差。表示D盘前面已有63个扇区，这63个扇区为系统</font></font></pre><pre><font face="宋体" size="2">隐藏扇区。
6. (BF A3 5D 00)：
反向，(00 5D A3 BF) 16  =  (6136767) 10。表明D盘有6136767个扇区。
通过上面得到的起点和分区的大小，可以推导出D盘的结束位置：8193150 + 63 + 6136767 =</font></pre><pre><font face="宋体" size="2">14329980号</font><font face="宋体" size="2">扇区。即（891柱面，254磁头，63扇区）。与上面的正好吻合。
</font></pre><pre><font face="宋体" size="2">第二项：
(00)（00 C1 7C）（05）（FE FF FF）（FE A3 5D 00）（21 88 56 00）
描述的是E盘的情况。
1. (00)： 表示E盘不是活动分区。
2. (00 C1 7C)：
(00) 16  =  (0) 10  (C1) 16  =  (1100 0001) 2  (7C) 16  =  (0111 1100) 2
磁头号：(0) 10
扇区号：(00 0001) 2  =  (1) 10
柱面号：(11 0111 1100) 2  =  (892) 10
所以E盘的起始扇区为（892柱面，0磁头，1扇区）。
3. (05): 表示E盘的在扩展分区里面。
4．(FE FF FF)：
(FE) 16  =  (254) 10  (FF) 16  =  (1111 1111) 2  (FF) 16  =  (1111 1111) 2
磁头号：(254) 10
扇区号：(11 1111) 2  =  (63) 10
柱面号：(11 1111 1111) 2  =  (1023) 10
但这是不准确的，原因同上。

5．(FE A3 5D 00):
 反向，(00 5D A3 FE) 16  =  (6136830) 10. 这一项非常重要，它定位了E盘分区表所在扇区。</font></pre><pre><font face="宋体" size="2">其值为E盘</font><font face="宋体" size="2">分区表所在扇区号与扩展分区起始扇区号之差。所以，E盘分区表所在扇区号为：
8193150 + 6136830 = 14329980。即（892柱面，0磁头，1扇区）。

6．(21 88 56 00):
反向，(00 56 88 21) 16  =  (5670945) 10.表示E盘共有11807775个扇区。通过上面得到的起点</font></pre><pre><font size="2"><font face="宋体">和分区的</font><font face="宋体">大小，可以推导出E盘的结束位置：14329980 + 5670945 = 20000925号扇区，即</font></font></pre><pre><font face="宋体" size="2">（1244 柱面，254磁头，63扇区）。
</font></pre><p><font face="宋体" size="2">三．查找E盘分区表 根据上面的信息，第三个分区表，也即E盘分区表在（892柱面，0磁头，1扇区）</font></p><p><font face="宋体" size="2">处。读取该扇区，得到分区表如下： </font></p><pre><font face="宋体" size="2">[00 01 C1 7C 0B FE FF FF 3F 00 00 00 E2 87 56 00]
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
[00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]

该分区表第二项全为0，说明没有下一个分区表了。该分区表就是分区表链的最后一个节点。
</font></pre><pre><font face="宋体" size="2">第一项：
（00）（01 C1 7C）（0B）（FE FF FF）（3F 00 00 00 ）（E2 87 56 00）
该项与D盘分区表的第二项描述的都是E盘的情况，但它们在某些细节上又有所区别。
1.（00）：表示E盘不是活动分区。
2.（01 C1 7C）：
  (01) 16  =  (1) 10  (C1) 16  =  (1100 0001) 2  (7C) 16  =  (0111 1100) 2.
磁头号：(1) 10
扇区号：(00 0001) 2  =  (1) 10
柱面号：(11 0111 1100) 2  =  (892) 10
故E盘起始扇区为（892柱面，1磁头，1扇区）。
3.（0B）：表示E盘的文件系统为FAT32。
4．（FE FF FF）：
(FE) 16  =  (254) 10 。 (FF) 16  =  (1111 1111) 2  (FF) 16  =  (1111 1111) 2.
磁头号：(254) 10；
扇区号：(11 1111) 2  =  (63) 10.
柱面号：(11 1111 1111) 2  =  (1023) 10
但这是不准确的，原因同上。
5.（3F 00 00 00）：
反向，(00 00 00 3F) 16  =  (63) 10.这一项与D盘分区表相应项有所不同.为E盘起始逻辑
扇区号（892柱面，1磁头，1扇区）与（892柱面，0磁头，1扇区）之差。表示E盘前面已有63个扇区, </font></pre><pre><font face="宋体" size="2">这63个扇区为系统隐藏扇区。
操作系统无法对这些扇区进行读写,所以可以把自己的秘密信息写在这里.
6. (E2 87 56 00): 
反向，(00 56 87 E2) 16  =  (5670882) 10。表明E盘有5670882个扇区。而D盘分区表相应项为</font></pre><pre><font size="2"><font face="宋体">5670945.</font><font face="宋体">5670945 - 5670882 = 63.正好等于63个隐藏扇区.这是因为D盘分区表描述的是</font></font></pre><pre><font size="2"><font face="宋体">(892柱面,0磁头，1扇区) </font><font face="宋体">到 (1244 柱面，254磁头，63扇区) 之间的扇区数。而E盘分区表</font></font></pre><pre><font face="宋体" size="2">描述的是(892柱面, 1磁头,1扇区) 到</font><font face="宋体" size="2">(1244 柱面，254磁头，63扇区) 之间的扇区数。
</font><a><font face="宋体" size="2">　</font></a></pre></td></tr></tbody></table>]]></description> 
<guid isPermaLink="false">6126879@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-02-26T14:53:23Z</dc:date> 
</item> 
<item> 
<title><![CDATA[php中Cookie及其使用]]></title> 
<link>http://www21.bokee.com/6091270.html</link> 
<description><![CDATA[<p><font size="2">Cookie技术是一个非常有争议的技术，自经诞生它就成了广大网络用户和Web开发人员的<br />一个争论焦点。有一些网络用户，甚至包括一些资深的Web专家也对它的产生和推广感到不满，这倒不是因为<br />Cookie技术的功能太弱或别的技术性能上的原因，而仅仅是因为他们觉得Cookie&amp;nbsp;的使用，对网络用户的隐私<br />构成了危害。因为Cookie是由Web服务器保存在用户浏览器上的小文本文件，它包含有关用户的信息（如身份<br />识别号码、密码、用户在Web站点上购物的方式或用户访问该站点的次数）。&amp;nbsp; </font></p><p><font size="2">　　那么Cookie&amp;nbsp;技术究竟怎样呢？是否真的给网络用户带来了个人隐私的危害呢？还是让我们看了下面的内<br />容，再做回答吧。&amp;nbsp;</font></p><p><font size="2">　　（1）Cookie技术简介&amp;nbsp;</font></p><p><font size="2">　　&amp;nbsp;在WEB技术发展史上，Cookie技术的出现是一个重大的变革。最先是Netscape在它的Netscape&amp;nbsp;Navigator<br />浏览器中引入了Cookie技术，从那时起，World&amp;nbsp;Wide&amp;nbsp;Web&amp;nbsp;协会就开始支持Cookie标准。以后又经过微软的大<br />力推广（因为微软的IIS&amp;nbsp;Web服务器所采用的ASP技术很大程度的使用了Cookie技术），即在微软的Internet<br />Explorer浏览器中完全支持Cookie技术。到现在，绝大多数的浏览器都支持Cookie技术，或者至少兼容Cookie<br />技术的使用。&amp;nbsp;</font></p><p><font size="2">　　1）什么是Cookie？&amp;nbsp;</font></p><p><font size="2">　　按照Netscape官方文档中的定义，Cookie是在HTTP协议下，服务器或脚本可以维护客户工作站上信息的<br />一种方式。Cookie&amp;nbsp;是由Web服务器保存在用户浏览器上的小文本文件，它可以包含有关用户的信息（如身份<br />识别号码、密码、用户在Web站点购物的方式或用户访问该站点的次数）。无论何时用户链接到服务器，Web<br />站点都可以访问Cookie信息。&amp;nbsp;</font></p><p><font size="2">　　通俗地讲，浏览器用一个或多个限定的文件来支持Cookie。这些文件在使用Windows操作系统的机器上叫<br />做Cookie&amp;nbsp;文件，在Macintosh机器上叫做magic&amp;nbsp;Cookie&amp;nbsp;文件，这些文件被网站用来在上面存储Cookie数据。<br />网站可以在这些Cookie&amp;nbsp;文件中插入信息，这样对有些网络用户就有些副作用。有些用户认为这造成了对个人<br />隐私的侵犯，更糟的是，有些人认为Cookie是对个人空间的侵占，而且会对用户的计算机带来安全性的危害。&amp;nbsp;</font></p><p><font size="2">　　目前有些Cookie&amp;nbsp;是临时的，另一些则是持续的。临时的Cookie只在浏览器上保存一段规定的时间，一旦<br />超过规定的时间该Cookie就会被系统清除。例如在PHP中Cookie被用来跟踪用户进程直到用户离开网站。持续<br />的Cookie则保存在用户的Cookie文件中，下一次用户返回时，仍然可以对它进行调用。&amp;nbsp;</font></p><p><font size="2">　　在Cookie文件中保存Cookie，一些用户会过分地认为这将带来很大的问题。主要是有些用户担心Cookie<br />会跟踪用户网上冲浪的习惯，譬如用户喜爱到那些类型的站点、爱从事些什么活动等。害怕这种个人信息一<br />旦落入一些别有用心的家伙手中，那么个人也就可能成为一大堆广告垃圾的对象，甚至遭到意外的损害。不<br />过，这种担心压根儿不会发生，因为网站以外的用户是无法跨过网站来获得Cookie信息的。所以想以这种目<br />的来应用Cookie是不可能的。不过，由于一些用户错误的理解以及“以讹传讹”，一些浏览器开发商别无选<br />择，只好作出相识的响应（例如Netscape&amp;nbsp;Navigator4.0和Internet&amp;nbsp;Explorer3.0都提供了屏蔽Cookie&amp;nbsp;的选<br />项）。&amp;nbsp;</font></p><p><font size="2">　　对Cookie技术期待了这么久的结果是，迫使许多浏览器开发商在它们的浏览器中提供了对Cookie的灵活<br />性控制功能。例如，目前的两大主流浏览器Netscape&amp;nbsp;Navigator&amp;nbsp;和&amp;nbsp;Internet&amp;nbsp;Explorer是这样处理Cookie<br />的:Netscape&amp;nbsp;Navigator4.0不但可以接受Cookie进行警告，而且还可以屏蔽掉Cookie；InternetExplorer3.0<br />也可以屏蔽Cookie，但在Internet&amp;nbsp;Explorer4.0中就只能进行接受警告而没有提供屏蔽选项，不过在Internet<br />Explorer4.0之后的更新版本中又加入了屏蔽Cookie的功能选项。&amp;nbsp;</font></p><p><font size="2">　　此外，很多最新的技术甚至已经可以在不能屏蔽Cookie的浏览器上进行Cookie的屏蔽了。例如，可以通<br />过将Cookie文件设置成不同的类型来限制Cookie的使用。但是，非常不幸地是，要是你想完全屏蔽Cookie的<br />话，肯定会因此拒绝许多的站点页面。因为当今已经有许多Web站点开发人员爱上了Cookie技术的强大功能，<br />例如Session对象的使用就离不开Cookie的支持。&amp;nbsp;</font></p><p><font size="2">　　尽管今天仍有一些网络用户对于Cookie的争论乐此不倦，但是对于绝大多数的网络用户来说还是倾向于<br />接受Cookie的。因此，我们尽可以放心地使用Cookie技术来开发我们的WEB页面。&amp;nbsp;</font></p><p><font size="2">　　2）Cookie是怎样工作的？&amp;nbsp;</font></p><p><font size="2">　　要了解Cookie，必不可少地要知道它的工作原理。一般来说，Cookie通过HTTP&amp;nbsp;Headers从服务器端返回<br />到浏览器上。首先，服务器端在响应中利用Set-Cookie&amp;nbsp;header来创建一个Cookie&amp;nbsp;，然后，浏览器在它的请<br />求中通过Cookie&amp;nbsp;header包含这个已经创建的Cookie，并且反它返回至服务器，从而完成浏览器的论证。&amp;nbsp;</font></p><p><font size="2">　　例如，我们创建了一个名字为login的Cookie来包含访问者的信息，创建Cookie时，服务器端的Header&amp;nbsp;<br />如下面所示，这里假设访问者的注册名是“Michael&amp;nbsp;Jordan”，同时还对所创建的Cookie的属性如path、<br />domain、expires等进行了指定。&amp;nbsp;</font></p><p><font size="2">　　Set-Cookie:login=Michael&amp;nbsp;Jordan;path=/;domain=msn.com;&amp;nbsp;<br />　　expires=Monday,01-Mar-99&amp;nbsp;00:00:01&amp;nbsp;GMT&amp;nbsp;</font></p><p><font size="2">　　上面这个Header会自动在浏览器端计算机的Cookie文件中添加一条记录。浏览器将变量名为“login”<br />的Cookie赋值为“Michael&amp;nbsp;Jordon”。注意，在实际传递过程中这个Cookie的值是经过了URLEncode方法的<br />URL编码操作的。&amp;nbsp;这个含有Cookie值的HTTP&amp;nbsp;Header被保存到浏览器的Cookie文件后，Header就通知浏览器<br />将Cookie通过请求以忽略路径的方式返回到服务器，完成浏览器的认证操作。&amp;nbsp;</font></p><p><font size="2">　　此外，我们使用了Cookie的一些属性来限定该Cookie的使用。例如Domain属性能够在浏览器端对Cookie<br />发送进行限定，具体到上面的例子，该Cookie只能传达室到指定的服务器上，而决不会跑到其他的如<br />www.hp.com的Web站点上去。Expires属性则指定了该Cookie保存的时间期限，例如上面的Cookie在浏览器上<br />只保存到1999年3月1日1秒。当然，如果浏览器上Cookie&amp;nbsp;太多，超过了系统所允许的范围，浏览器将自动对<br />它进行删除。至于属性Path，用来指定Cookie将被发送到服务器的哪一个目录路径下。&amp;nbsp;</font></p><p><font size="2">　　说明：浏览器创建了一个Cookie后，对于每一个针对该网站的请求，都会在Header中带着这个Cookie；<br />不过，对于其他网站的请求Cookie是绝对不会跟着发送的。而且浏览器会这样一直发送，直到Cookie过期为止。&amp;nbsp;</font></p><p><font size="2">　　上一部分讲了有关Cookie的技术背景，这部分来说说在PHP里如何设置、使用、删除Cookie，及Cookie<br />的一些限制。PHP对Cookie支持是透明的，用起来非常方便。&amp;nbsp;</font></p><p><font size="2">　　1、设置Cookie</font></p><p><font size="2">　　PHP用SetCookie函数来设置Cookie。必须注意的一点是：Cookie是HTTP协议头的一部分，用于浏览器和<br />服务器之间传递信息，所以必须在任何属于HTML文件本身的内容输出之前调用Cookie函数。SetCookie&amp;nbsp;函数<br />定义了一个Cookie，并且把它附加在HTTP头的后面，SetCookie函数的原型如下：</font></p><p><font size="2">int&amp;nbsp;SetCookie(string&amp;nbsp;name,&amp;nbsp;string&amp;nbsp;value,&amp;nbsp;int&amp;nbsp;expire,&amp;nbsp;string&amp;nbsp;path,&amp;nbsp;<br />string&amp;nbsp;domain,&amp;nbsp;int&amp;nbsp;secure);&amp;nbsp;</font></p><p><font size="2">　　除了name之外所有的参数都是可选的。value,path,domain&amp;nbsp;三个参数可以用空字符串代换，表示没有设<br />置；expire和&amp;nbsp;secure两个参数是数值型的，可以用0表示。expire参数是一个标准的Unix时间标记，可以用<br />time()或mktime()&amp;nbsp;函数取得，以秒为单位。secure参数表示这个Cookie是否通过加密的HTTPS协议在网络上<br />传输。&amp;nbsp;</font></p><p><font size="2">　　当前设置的Cookie&amp;nbsp;不是立即生效的，而是要等到下一个页面时才能看到.这是由于在设置的这个页面里<br />Cookie由服务器传递给客户浏览器，在下一个页面浏览器才能把Cookie从客户的机器里取出传回服务器的原<br />因。在同一个页面设置Cookie，实际是从后往前，所以如果要在插入一个新的Cookie之前删掉一个，你必须<br />先写插入的语句，再写删除的语句，否则可能会出现不希望的结果。&amp;nbsp;</font></p><p><font size="2">　　来看几个例子：</font></p><p><font size="2">　　简单的：</font></p><p><font size="2">SetCookie(&amp;quot;MyCookie&amp;quot;,&amp;nbsp;&amp;quot;Value&amp;nbsp;of&amp;nbsp;MyCookie&amp;quot;);&amp;nbsp;</font></p><p><font size="2">　　带失效时间的：&amp;nbsp;</font></p><p><font size="2">SetCookie(&amp;quot;WithExpire&amp;quot;,&amp;nbsp;&amp;quot;Expire&amp;nbsp;in&amp;nbsp;1&amp;nbsp;hour&amp;quot;,&amp;nbsp;time()+3600);//3600秒=1小时&amp;nbsp;</font></p><p><font size="2">　　什么都有的：&amp;nbsp;</font></p><p><font size="2">SetCookie(&amp;quot;FullCookie&amp;quot;,&amp;nbsp;&amp;quot;Full&amp;nbsp;cookie&amp;nbsp;value&amp;quot;,&amp;nbsp;time()+3600,&amp;nbsp;&amp;quot;/forum&amp;quot;,&amp;nbsp;&amp;quot;.phpuser.com&amp;quot;,&amp;nbsp;1);&amp;nbsp;</font></p><p><font size="2">　　这里还有一点要说明的，比如你的站点有几个不同的目录，那么如果只用不带路径的Cookie的话，在一<br />个目录下的页面里设的Cookie在另一个目录的页面里是看不到的，也就是说，Cookie是面向路径的。实际上，<br />即使没有指定路径，WEB&amp;nbsp;服务器会自动传递当前的路径给浏览器的，指定路径会强制服务器使用设置的路径。<br />解决这个问题的办法是在调用SetCookie时加上路径和域名，域名的格式可以是“www.phpuser.com”，也可<br />是“.phpuser.com”。&amp;nbsp;</font></p><p><font size="2">　　SetCookie函数里表示value的部分，在传递时会自动被encode，也就是说，如果value的值是“test&amp;nbsp;<br />value”在传递时就变成了“test%20value”，跟URL的方法一样。当然，对于程序来说这是透明的，因为在<br />PHP接收Cookie的值时会自动将其decode。&amp;nbsp;</font></p><p><font size="2">　　如果要设置同名的多个Cookie，要用数组，方法是：&amp;nbsp;</font></p><p><font size="2">SetCookie(&amp;quot;CookieArray[]&amp;quot;,&amp;nbsp;&amp;quot;Value&amp;nbsp;1&amp;quot;);&amp;nbsp;<br />SetCookie(&amp;quot;CookieArray[]&amp;quot;,&amp;nbsp;&amp;quot;Value&amp;nbsp;2&amp;quot;);&amp;nbsp;</font></p><p><font size="2">　　或&amp;nbsp;</font></p><p><font size="2">SetCookie(&amp;quot;CookieArray[0]&amp;quot;,&amp;nbsp;&amp;quot;Value&amp;nbsp;1&amp;quot;);&amp;nbsp;<br />SetCookie(&amp;quot;CookieArray[1]&amp;quot;,&amp;nbsp;&amp;quot;Value&amp;nbsp;2&amp;quot;);&amp;nbsp;</font></p><p><font size="2">　　2、接收和处理Cookie&amp;nbsp;</font></p><p><font size="2">　　PHP对Cookie的接收和处理的支持非常好，是完全自动的，跟FORM变量的原则一样，特别简单。比如设<br />置一个名为MyCookier的Cookie，PHP会自动从WEB服务器接收的HTTP头里把它分析出来，并形成一个与普通<br />变量一样的变量，名为$myCookie，这个变量的值就是Cookie的值。数组同样适用。另外一个办法是引用PHP<br />的全局变量$HTTP_COOKIE_VARS数组。&amp;nbsp;</font></p><p><font size="2">　　分别举例如下：（假设这些都在以前的页面里设置过了，并且仍然有效）&amp;nbsp;</font></p><p><font size="2">echo&amp;nbsp;$MyCookie;&amp;nbsp;<br />echo&amp;nbsp;$CookieArray[0];&amp;nbsp;<br />echo&amp;nbsp;count($CookieArray);&amp;nbsp;<br />echo&amp;nbsp;$HTTP_COOKIE_VARS[&amp;quot;MyCookie&amp;quot;];&amp;nbsp;</font></p><p><font size="2">　　就这么简单。&amp;nbsp;</font></p><p><font size="2">　　3、删除Cookie&amp;nbsp;</font></p><p><font size="2">　　要删除一个已经存在的Cookie，有两个办法：&amp;nbsp;</font></p><p><font size="2">　　一是调用只带有name参数的SetCookie，那么名为这个name的Cookie&amp;nbsp;将被从关系户机上删掉；另一个办<br />法是设置Cookie的失效时间为time()或time()-1，那么这个Cookie在这个页面的浏览完之后就被删除了（其<br />实是失效了）。&amp;nbsp;</font></p><p><font size="2">　　要注意的是，当一个Cookie被删除时，它的值在当前页在仍然有效的。&amp;nbsp;</font></p><p><font size="2">　　4、使用Cookie的限制&amp;nbsp;</font></p><p><font size="2">　　首先是必须在HTML文件的内容输出之前设置；&amp;nbsp;<br />　　其次不同的浏览器对Cookie的处理不一致，且有时会出现错误的结果。比如：MS&amp;nbsp;IE+SERVICE&amp;nbsp;PACK&amp;nbsp;1<br />不能正确处理带域名和路径的Cookie&amp;nbsp;，Netscape&amp;nbsp;Communicator&amp;nbsp;4.05和MS&amp;nbsp;IE&amp;nbsp;3.0不能正确处理不带路径和<br />时间的Cookie。至于MS&amp;nbsp;IE&amp;nbsp;5&amp;nbsp;好象不能处理带域名、路径和时间的Cookie。这是我在设计本站的页面时发现<br />的。&amp;nbsp;<br />　　第三个限制是在客户端的。一个浏览器能创建的Cookie数量最多为30个，并且每个不能超过4KB，每个WEB<br />站点能设置的Cookie总数不能超过20个。&amp;nbsp;</font></p><p><font size="2">　　关于Cookie的话题，就说到这儿了。&amp;nbsp;</font></p><p><font size="2">　　（由于Cookie最初由Netscape定义的，所以附上Netscape公司关于Cookie的官方原始定义的网址：<br />_spec.html&amp;quot; target=_blank&amp;gt;</font><font size="2"><font color="#0000ff">http://www.netscape.com/newsref<br />/std/cookie_spec.html</font></a />）</font></p><p><font size="2">Cookie技术是一个非常有争议的技术，自经诞生它就成了广大网络用户和Web开发人员的<br />一个争论焦点。有一些网络用户，甚至包括一些资深的Web专家也对它的产生和推广感到不满，这倒不是因为<br />Cookie技术的功能太弱或别的技术性能上的原因，而仅仅是因为他们觉得Cookie&amp;nbsp;的使用，对网络用户的隐私<br />构成了危害。因为Cookie是由Web服务器保存在用户浏览器上的小文本文件，它包含有关用户的信息（如身份<br />识别号码、密码、用户在Web站点上购物的方式或用户访问该站点的次数）。</font></p>]]></description> 
<guid isPermaLink="false">6091270@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-02-05T12:54:54Z</dc:date> 
</item> 
<item> 
<title><![CDATA[css定位（position）属性]]></title> 
<link>http://www21.bokee.com/6077320.html</link> 
<description><![CDATA[要点如下：<br />1、绝对定位的参照位置是上层最近的position不是static的元素，其实就是说具有position:relative/absolute/fixed属性的上层元素。如果没有，就以body为定位标准。<br />2、如果想把某个上层作成下层绝对定位的参照位置，可以把上层的position设定为relative偏移为0就可以了<br />3、position:fixed 为固定定位，参照位置不是父层而是浏览器视窗。所以可以用fixed属性来设定类似传统框架布局，或者飘固定广告或者固定导航都可以。<br />4、相对定位属性中的正值可以理解为从上层元素边缘向中间移动，而负值可以理解为从边缘向外部移动。<br />5、相对定位的元素只是从正常的位置上移开，但是它占有的页面位置并不消失而变成空白。<br />5、visibility可以设置成hidden，这时候元素看不见但是仍旧占有页面位置。display：none；则根本就完全消失。 ]]></description> 
<guid isPermaLink="false">6077320@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-01-29T23:23:42Z</dc:date> 
</item> 
<item> 
<title><![CDATA[css对各浏览器的兼容问题]]></title> 
<link>http://www21.bokee.com/6074728.html</link> 
<description><![CDATA[区分三款浏览器简单方法:<br />#example&amp;nbsp;{&amp;nbsp;color:&amp;nbsp;#333;&amp;nbsp;}&amp;nbsp;/*&amp;nbsp;Moz&amp;nbsp;FF&amp;nbsp;*/<br />*&amp;nbsp;html&amp;nbsp;#example&amp;nbsp;{&amp;nbsp;color:&amp;nbsp;#f0f;&amp;nbsp;}&amp;nbsp;/*&amp;nbsp;IE6&amp;nbsp;*/<br />*+html&amp;nbsp;#example&amp;nbsp;{&amp;nbsp;color:&amp;nbsp;#0ff;&amp;nbsp;}&amp;nbsp;/*&amp;nbsp;IE7&amp;nbsp;*/<br /><br />马上试了一下，效果很好，不过有句要补充一下！<br /><span style="COLOR: blue">在兼容IE7的*+html的hack一定要在顶部加入DTD声明，否则无效</span><br />将下面这句声明加入下面可运行的html的顶部，就可以看到效果拉~当然要保证你的浏览器是IE7<br />&amp;lt;!DOCTYPE&amp;nbsp;HTML&amp;nbsp;PUBLIC&amp;nbsp;&amp;quot;-//W3C//DTD&amp;nbsp;HTML&amp;nbsp;4.01&amp;nbsp;Transitional//EN&amp;quot;　&amp;quot;<a href="http://www.w3.org/TR/html4/loose.dtd" target="_blank">http://www.w3.org/TR/html4/loose.dtd</a>&amp;quot;&amp;gt;<br /><br /><div class="UBBPanel"><div class="UBBTitle"><strong>1.为什么在不同的浏览器显示效果不一样？</strong><br />因为不同浏览器对于css样式表的解析不一样，所以导致样式乃至层布局发生变化。例如，ff中设置padding属性时，div会相应增加height和width，而ie的解析是不会的，再例如ff对盒模型的解析和ie相差两个象素。<br /><br /><strong>2.设计时要做到所有浏览器都兼容吗？</strong><br />我的答案是即使能做到也没有必要去做，科技是在进步的，用户总是在推陈出新的使用这新版本的浏览器，根据“设计诉说”的站点统计小样本结果显示，<span style="COLOR: navy">6225个访问者中有72.1%使用IE6.0；12.7%使用IE7.0；7.9%在使用FF2.0，剩余的不同版本的浏览器占的百分比都不到1%&amp;nbsp;</span>所以我认为只要做到IE6&amp;nbsp;FF2.0&amp;nbsp;以及新出的IE7.0兼容即可，顶多向下兼容一下IE5.5，完全没有必要为了那些个小数点费劲脑子。如果有必要可以另外设计css文件，然后通过js判断浏览器版本进行选择相应的文件。<br /><br /><strong>3.css样式的优先级是怎么样的？</strong><br />这个是个好问题，当你弄明白这个，我想应该可以很自如的运用一些兼容样式表的技巧了。在正常的IE中，如果你在css中重复定义一个属性时，浏览器解析的是后面的属性，举个例子<br />box&amp;nbsp;{<br />height:100px;<br />height:200px;<br />height:400px;<br />height:300px;<br />}<br />重复定义盒模型的高度属性，越后面优先级越高，所以浏览器解析出的结果就是高度为300px。<br /><br /><strong>4.如何做到让IE6.0与FF兼容？</strong><br />最常用的一种方法了，也是屡试不爽的——“!important”，这个字段是用来提高优先级的，而IE6.0对于找个字段是无法识别的，于是FF与IE6.0就可以分开解析了。例如，在IE下显示red，FF下显示blue，只需要这么写&amp;nbsp;<br />color&amp;nbsp;{<br />background-color:blue&amp;nbsp;!important;<br />background-color:red;<br />}<br />“!important”FF可以识别，blue那行提高优先级，因此在FF中blue优先级高于red，显示为蓝色<br /><br />IE6.0将上面的样式识别成<br />color&amp;nbsp;{<br />background-color:blue;<br />background-color:red;<br />}<br />red优先级高，所以显示为红色。<br /><br />切记，上下两句的位置一定不能颠倒。问为什么的再好好看看上两个问题，再不明白就面壁去....<br /><br /><strong>5.如何做到让更低版本IE兼容？</strong><br />其实我认为做到IE6.0与FF2.0已经足够，5.5的兼容用“&amp;nbsp;/**/”&amp;nbsp;5.0的兼容用“&amp;gt;”，具体我就不说了，说实在我也不大懂，大家可以去<a href="http://www.google.com/" target="_blank">google</a>一下<br /><br /><strong>6.如何做到IE7.0兼容？</strong><br />这个问题我也要问大家，大家有答案的告诉我，因为新版的IE7.0对于“!important”具有识别能力，可是对于盒以及padding等的解析却和IE6.0差不多，于是乎，完全兼容了IE6.0和FF2.0的就似乎兼容不了IE7.0，捣腾了好久，还是不知道怎么办。请大家帮帮忙！<br /><br /><strong>7.css对浏览器兼容应做到完全一致吗？</strong><br />个人认为在满足可读性的原则和不影响整体布局的前提下，界面有些许的位置不同是可以允许的，要在不同浏览器下做到一模一样，那真是太费劲了。</div></div>]]></description> 
<guid isPermaLink="false">6074728@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-01-28T23:42:42Z</dc:date> 
</item> 
<item> 
<title><![CDATA[CSS浏览器兼容问题]]></title> 
<link>http://www21.bokee.com/6074573.html</link> 
<description><![CDATA[E6.0,ie7.0与Firefox的CSS兼容性问题<br />&amp;#160;&amp;#160;&amp;#160; &amp;#160; 1.DOCTYPE&amp;#160;影响&amp;#160;CSS&amp;#160;处理<br />　　2.FF:&amp;#160;div&amp;#160;设置&amp;#160;margin-left,&amp;#160;margin-right&amp;#160;为&amp;#160;auto&amp;#160;时已经居中,&amp;#160;IE&amp;#160;不行<br />　　3.FF:&amp;#160;body&amp;#160;设置&amp;#160;text-align&amp;#160;时,&amp;#160;div&amp;#160;需要设置&amp;#160;margin:&amp;#160;auto(主要是&amp;#160;margin-left,margin-right)&amp;#160;方可居中<br />　　4.FF:&amp;#160;设置&amp;#160;padding&amp;#160;后,&amp;#160;div&amp;#160;会增加&amp;#160;height&amp;#160;和&amp;#160;width,&amp;#160;但&amp;#160;IE&amp;#160;不会,&amp;#160;故需要用&amp;#160;!important&amp;#160;多设一个&amp;#160;height&amp;#160;和&amp;#160;width<br />　　5.FF:&amp;#160;支持&amp;#160;!important,&amp;#160;IE&amp;#160;则忽略,&amp;#160;可用&amp;#160;!important&amp;#160;为&amp;#160;FF&amp;#160;特别设置样式，值得注意的是，一定要将xxxx&amp;#160;!important&amp;#160;这句放置在另一句之上<br />　　6.div&amp;#160;的垂直居中问题:&amp;#160;vertical-align:middle;&amp;#160;将行距增加到和整个DIV一样高&amp;#160;line-height:200px;&amp;#160;然后插入文字，就垂直居中了。缺点是要控制内容不要换行<br />　　7.cursor:&amp;#160;pointer&amp;#160;可以同时在&amp;#160;IE&amp;#160;FF&amp;#160;中显示游标手指状，&amp;#160;hand&amp;#160;仅&amp;#160;IE&amp;#160;可以<br />　&amp;#160;&amp;#160;8.FF:
&amp;#160;链接加边框和背景色，需设置&amp;#160;display:&amp;#160;block,&amp;#160;同时设置&amp;#160;float:&amp;#160;left&amp;#160;保证不换行。参照&amp;#160;menubar,&amp;#160;给&amp;#160;a&amp;#160;和
&amp;#160;menubar&amp;#160;设置高度是为了避免底边显示错位,&amp;#160;若不设&amp;#160;height,&amp;#160;可以在&amp;#160;menubar&amp;#160;中插入一个空格。<br />　　9.在mozilla&amp;#160;firefox和IE中的BOX模型解释不一致导致相差2px解决方法：div{margin:30px!important;margin:28px;}<br />　　注意这两个margin的顺序一定不能写反，据阿捷的说法!important这个属性IE不能识别，但别的浏览器可以识别。所以在IE下其实解释成这样：div{maring:30px;margin:28px}<br />　　重复定义的话按照最后一个来执行，所以不可以只写margin:XXpx!important;<br />　　10.IE5&amp;#160;和IE6的BOX解释不一致<br />　　IE5下div{width:300px;margin:0&amp;#160;10px&amp;#160;0&amp;#160;10px;}<br />　
　div的宽度会被解释为300px-10px(右填充)-10px(左填充)最终div的宽度为280px，而在IE6和其他浏览器上宽度则是以
300px+10px(右填充)+10px(左填充)=320px来计算的。这时我们可以做如下修改div{width:300px!
important;width&amp;#160;/**/:340px;margin:0&amp;#160;10px&amp;#160;0&amp;#160;10px}<br />　　关于这个/**/是什么我也不太明白，只知道IE5和firefox都支持但IE6不支持，如果有人理解的话，请告诉我一声，谢了！：）<br />　　11.ul标签在Mozilla中默认是有padding值的,而在IE中只有margin有值所以先定义ul{margin:0;padding:0;}就能解决大部分问题<br /><br />　　<br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;注意事项：<br /><br />　　<span style="font-weight: bold;">1、float的div一定要闭合。</span><br /><br />　　例如：(其中floatA、floatB的属性已经设置为float:left;)&amp;lt;#div&amp;#160;id=\&amp;quot;floatA\&amp;quot;&amp;#160;&amp;gt;<br />&amp;lt;#div&amp;#160;id=\&amp;quot;floatB\&amp;quot;&amp;#160;&amp;gt;<br />&amp;lt;#div&amp;#160;id=\&amp;quot;NOTfloatC\&amp;quot;&amp;#160;&amp;gt;<br />　　这里的NOTfloatC并不希望继续平移，而是希望往下排。<br />　　这段代码在IE中毫无问题，问题出在FF。原因是NOTfloatC并非float标签，必须将float标签闭合。<br />　　在&amp;lt;#div&amp;#160;class=\&amp;quot;floatB\&amp;quot;&amp;gt;<br />&amp;lt;#div&amp;#160;class=\&amp;quot;NOTfloatC\&amp;quot;&amp;gt;<br />　　之间加上&amp;lt;#div&amp;#160;class=\&amp;quot;clear\&amp;quot;&amp;gt;<br />　　这个div一定要注意声明位置，一定要放在最恰当的地方，而且必须与两个具有float属性的div同级，之间不能存在嵌套关系，否则会产生异常。<br />　　并且将clear这种样式定义为为如下即可：.clear{<br />clear:both;}<br />　　此外，为了让高度能自动适应，要在wrapper里面加上overflow:hidden;<br />　　当包含float的box的时候，高度自动适应在IE下无效，这时候应该触发IE的layout私有属性(万恶的IE啊！)用zoom:1;可以做到，这样就达到了兼容。<br />　　例如某一个wrapper如下定义：.colwrapper{<br />overflow:hidden;<br />zoom:1;<br />margin:5px&amp;#160;auto;}<br /><br />　　<span style="font-weight: bold;">2、margin加倍的问题。</span><br /><br />　　设置为float的div在ie下设置的margin会加倍。这是一个ie6都存在的bug。<br />　　解决方案是在这个div里面加上display:inline;<br />例如：<br />&amp;lt;#div&amp;#160;id=\&amp;quot;imfloat\&amp;quot;&amp;gt;<br /><br /><br />　　相应的css为<br />#IamFloat{<br />float:left;<br />margin:5px;/*IE下理解为10px*/<br />display:inline;/*IE下再理解为5px*/}<br /><br />　　<span style="font-weight: bold;">3、关于容器的包涵关系</span><br /><br />　　很多时候，尤其是容器内有平行布局，例如两、三个float的div时，宽度很容易出现问题。在IE中，外层的宽度会被内层更宽的div挤破。一定要用Photoshop或者Firework量取像素级的精度。<br /><br />　　<span style="font-weight: bold;">4、关于高度的问题</span><br /><br />　　如果是动态地添加内容，高度最好不要定义。浏览器可以自动伸缩，然而如果是静态的内容，高度最好定好。（似乎有时候不会自动往下撑开，不知道具体怎么回事）<br /><br />　　<span style="font-weight: bold;">5、最狠的手段&amp;#160;-&amp;#160;!important;</span><br /><br />　　如果实在没有办法解决一些细节问题,可以用这个方法.FF对于&amp;quot;!important&amp;quot;会自动优先解析,然而IE则会忽略.如下.tabd1{<br />background:url(/res/images/up/tab1.gif)&amp;#160;no-repeat&amp;#160;0px&amp;#160;0px&amp;#160;!important;&amp;#160;/*Style&amp;#160;for&amp;#160;FF*/<br />background:url(/res/images/up/tab1.gif)&amp;#160;no-repeat&amp;#160;1px&amp;#160;0px;&amp;#160;/*&amp;#160;Style&amp;#160;for&amp;#160;IE&amp;#160;*/}<br />　　值得注意的是，一定要将xxxx&amp;#160;!important&amp;#160;这句放置在另一句之上，上面已经提过 IE7.0出来了，对CSS的支持又有新问题。浏览器多了，网页兼容性更差了，疲于奔命的还是我们&amp;#160;，为解决IE7.0的兼容问题，找来了下面这篇文章：<br /><br />现
在我大部分都是用!important来hack，对于ie6和firefox测试可以正常显示，但是ie7对!important可以正确解释，会导致
页面没按要求显示！搜索了一下，找到一个针对IE7不错的hack方式就是使用“*+html”，现在用IE7浏览一下，应该没有问题了。<br /><br />现在写一个CSS可以这样：<br />#example&amp;#160;{&amp;#160;color:&amp;#160;#333;&amp;#160;}&amp;#160;/*&amp;#160;Moz&amp;#160;*/<br />*&amp;#160;html&amp;#160;#example&amp;#160;{&amp;#160;color:&amp;#160;#666;&amp;#160;}&amp;#160;/*&amp;#160;IE6&amp;#160;*/<br />*+html&amp;#160;#example&amp;#160;{&amp;#160;color:&amp;#160;#999;&amp;#160;}&amp;#160;/*&amp;#160;IE7&amp;#160;*/<br /><br />那么在firefox下字体颜色显示为#333，IE6下字体颜色显示为#666，IE7下字体颜色显示为#999，他们都互不干扰。
]]></description> 
<guid isPermaLink="false">6074573@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-01-28T22:39:31Z</dc:date> 
</item> 
<item> 
<title><![CDATA[XHTML+CSS兼容性解决方案小集]]></title> 
<link>http://www21.bokee.com/6074565.html</link> 
<description><![CDATA[使用XHTML＋CSS构架好处不少，但也确实存在一些问题，不论是因为使用不熟练还是思路不清晰，我就先把一些我遇到的问题写在下面，省的大家四处找。<div id="artcontent">
<p>1.在mozilla firefox和IE中的BOX模型解释不一致导致相差2px解决方法：</p>
<pre><code>div{margin:30px!important;margin:28px;}</code></pre>
<p>注意这两个margin的顺序一定不能写反，据阿捷的说法!important这个属性IE不能识别，但别的浏览器可以识别。所以在IE下其实解释成这样：</p>
<pre> <code>div{maring:30px;margin:28px}</code></pre>
<p>重复定义的话按照最后一个来执行，所以不可以只写margin:XXpx!important;</p>
<p>2.IE5和IE6的BOX解释不一致IE5下div{width:300px;margin:0 10px 0
10px;}div的宽度会被解释为300px-10px(右填充)-10px(左填充)最终div的宽度为280px，而在IE6和其他浏览器上宽度则
是以300px+10px(右填充)+10px(左填充)=320px来计算的。这时我们可以做如下修改：</p>
<pre> <code>div{width:300px!important;width&amp;#160; /**/:340px;margin:0&amp;#160; 10px&amp;#160; 0&amp;#160; 10px}</code></pre>
<p>关于这个/**/是什么我也不太明白，只知道IE5和firefox都支持但IE6不支持，如果有人理解的话，请告诉我一声，谢了！：）</p>
<p>3.ul标签在Mozilla中默认是有padding值的,而在IE中只有margin有值所以先定义：</p>
<pre> <code>ul{margin:0;padding:0;}</code></pre>
<p>就能解决大部分问题。</p>
<p>4.关于脚本，在xhtml1.1中不支持language属性，只需要把代码改为：</p>
<pre><code>&amp;lt;script&amp;#160; type=&amp;quot;text/javascript&amp;quot;&amp;gt;</code></pre>
<p>就可以了。</p>
<p>5.如果你在BOX容器里使float和text-align的方向设为一致：</p>
<pre><code>{float:left;text-align:left;margin:0 0 0 200px;}</code></pre>
<p>我们可做如下修改：</p>
<pre><code>{float:left;text-align:left;margin:0 0 0 200px;display:inline;}</code></pre>


</div>
]]></description> 
<guid isPermaLink="false">6074565@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-01-28T22:37:04Z</dc:date> 
</item> 
<item> 
<title><![CDATA[XHTML教程]]></title> 
<link>http://www21.bokee.com/6074232.html</link> 
<description><![CDATA[现在都讲究标准建站，而标准建站使用的技术主要是XHTML+CSS，而现在我们普遍使用的是HTML代码，那么我该如何转换呢？以及HTML和XHTML有什么不同呢？在这个教程里，你将学到HTML和XHTML之间的不同，以及如何将HTML转换为XHTML。毕竟XHTML是发展的方向，所以我觉得该教程有必要在本站上发布。我感觉要是你想使用标准还是最好先学HTML，因为比较简单，然后再来看该教程。<p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　<font color="#0000ff">XHTML介绍：</font></p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　XHTML是 EXtensible HyperText Markup Language(可扩展超文本标记语言) 的英文缩写，而HTML则是 HyperText Markup Language(超文本标记语言) ，这是名字的不同。其实我们说得标准应该是XML，那为什么要学习XHTML呢？因为现在的HTML代码烦琐，危机四伏，但是XML使用环境还不成熟，所以推出了一个过度的产品就是XHTML，它起着呈上起下的作用。也有人认为XHTML是HTML的一个升级版本，其实也是正确的，我的理解是XHTML把HTML做得更加规范的一个标记语言，使HTML变得功能强大，减少了代码的烦琐尤其是表格。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　XHTML是在2000年1月26日被国际标准组织机构W3C(World Wide web Consortium)定为一个标准的，认为是HTML的一个最新版本，并且将逐渐替换HTML。现在所有的浏览器都支持XHTML，XHTML兼容 HTML 4.0。也有人认为XHTML就是HTML4.01。如果你在学习过程中自己编写了一个符合标准的站，你可以通过W3C的验证，验证通过后你将会得到一个标志，通常是XHTML1.0认证和CSS验证。我也不清楚目前国内有多少个网站同时通过了这两个验证。大家可以去<font color="#000000">http://www.w3.org/这个站点去验证你的站，如果符合那两个规则则会分别给我们两段代码加到你的网页上向别人展示说明你采用了标准建站啊，牛啊！</font></p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">&amp;nbsp;&amp;nbsp;&amp;nbsp; XHTML是The Extensible HyperText Markup Language(可扩展标识语言)的缩写。HTML是一种基本的WEB网页设计语言，XHTML是一个基于XML的置标语言，看起来与HTML有些相象，只有一些小的但重要的区别，XHTML就是一个扮演着类似HTML的角色的XML，所以，本质上说，XHTML是一个过渡技术，结合了部分XML的强大功能及大多数HTML的简单特性。<br />　　2000年底，国际W3C组织(World Wide Web Consortium)组织公布发行了XHTML 1.0版本。XHTML 1.0是一种在HTML 4.0基础上优化和改进的的新语言，目的是基于XML应用。XHTML是一种增强了的HTML,它的可扩展性和灵活性将适应未来网络应用更多的需求。XML虽然数据转换能力强大，完全可以替代HTML，但面对成千上万已有的基于HTML语言设计的网站，直接采用XML还为时过早。因此，在HTML4.0的基础上，用XML的规则对其进行扩展，得到了XHTML。所以，建立XHTML的目的就是实现HTML向XML的过渡。目前国际上在网站设计中推崇的WEB标准就是基于XHTML的应用（即通常所说的CSS＋DIV）。<br />　</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　<font color="#0000ff">为什么我们使用XHTML</font> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　XHTML是HTML升级为XML的过度产品，被定为一个标准，XHTML完全兼容HTML4.01，并且具有XML的语法。下面我们来看一个含有错误代码的HTML，如下：<br />&amp;lt;html&amp;gt;<br />　　&amp;lt;head&amp;gt;<br />　　&amp;lt;title&amp;gt;This is bad HTML&amp;lt;/title&amp;gt;<br />　　&amp;lt;body&amp;gt;<br />　　&amp;lt;h1&amp;gt;Bad HTML<br />　　&amp;lt;/body&amp;gt; </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　虽然含有错误代码，但是当我们在浏览器中浏览时还能正常显示。XML是一个标记语言，但是它要求在网页中出现的任何元素都应该被标记出来，XML是用来描述网页中的数据的，而HTML用来显示网页中的元素的。目前我们上网使用的各种浏览器技术，包括手提电脑、手机上网浏览等等，都要求浏览的一些内容都要被正确标记，如果有错误的标记可能会使显示特别混乱、甚至不能正常显示。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　因此联合 HTML 和XML , 还有其他的一些技术，我们得到了一种现在有用的而且在将来也有用的语言 - XHTML。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　当在将来都规范的时候我们就要用的 XHTML 正确格式的标记了,使所有的浏览器都能正确的执行，所以我们现在有必要开始学习XHTML了。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　<font color="#0000ff">XHTML和HTML之间的区别：</font></p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　XHTML是一项新技术，在浏览器和一些其他的软件都支持它之前，我们应该有必要熟悉一下这项技术。为了我们更好的学习XHTML之前我们应该熟悉一下HTML4.0，我们可以去下载一个参考手册来熟悉一下。以便于我们学起XHTML来更简单，换句话说我们现在使用HTML编写代码时应该尽力少写错误代码，如：都要使用小写的字符来编写HTML，每个标记之后都要加上标记的结束如：&amp;lt;p&amp;gt;网页教学网欢迎您的光临&amp;lt;/p&amp;gt; 结束一定要有，我们要保持这种规则。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　它们之间最大的区别在于：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　<font color="#ff0000">1.XHTML 元素一定要被正确的嵌套使用。</font></p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　在HTML里一些元素可以不正确嵌套也能正常显示，如：<br />　　&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;This text is bold and italic&amp;lt;/b&amp;gt;&amp;lt;/i&amp;gt; <br />　　而在XHTML必须要正确嵌套之后才能正常使用，如：<br />　　&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;This text is bold and italic&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;<br />　　注意：这个错误通常发生在当嵌套多层之后的标签里面。如：<br />　　&amp;lt;ul&amp;gt;<br />　　　&amp;lt;li&amp;gt;Coffee&amp;lt;/li&amp;gt;<br />　　　&amp;lt;li&amp;gt;Tea<br />　　　&amp;lt;ul&amp;gt;<br />　　　　&amp;lt;li&amp;gt;Black tea&amp;lt;/li&amp;gt;<br />　　　　&amp;lt;li&amp;gt;Green tea&amp;lt;/li&amp;gt;<br />　　　&amp;lt;/ul&amp;gt;<br />　　　&amp;lt;li&amp;gt;Milk&amp;lt;/li&amp;gt;<br />　　&amp;lt;/ul&amp;gt;<br />　　正确的应该是：<br />　　&amp;lt;ul&amp;gt;<br />　　　&amp;lt;li&amp;gt;Coffee&amp;lt;/li&amp;gt;<br />　　　&amp;lt;li&amp;gt;Tea<br />　　　&amp;lt;ul&amp;gt;<br />　　　　&amp;lt;li&amp;gt;Black tea&amp;lt;/li&amp;gt;<br />　　　　&amp;lt;li&amp;gt;Green tea&amp;lt;/li&amp;gt;<br />　　　&amp;lt;/ul&amp;gt;<br />　　　&amp;lt;/li&amp;gt;<br />　　　&amp;lt;li&amp;gt;Milk&amp;lt;/li&amp;gt;<br />　　&amp;lt;/ul&amp;gt;<br />　　观察上述的两段代码我们可以看到正确的里面我们在 &amp;lt;/ul&amp;gt;之后插入 &amp;lt;/li&amp;gt; 标签。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　<font color="#ff0000">XHTML 文件一定要有正确的组织格式。</font></p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　所有的XHTML应该正确的被嵌套在以&amp;lt;html&amp;gt;开始以&amp;lt;/html&amp;gt;结束的元素里面，其他的元素可以有子元素，并且子元素也要被正确的嵌套在他们的父元素内。如：<br />&amp;lt;html&amp;gt;<br />　　&amp;lt;head&amp;gt; ... &amp;lt;/head&amp;gt;<br />　　&amp;lt;body&amp;gt; ... &amp;lt;/body&amp;gt;<br />　　&amp;lt;/html&amp;gt; <br />　　<font color="#ff0000">标签名字一定要用小写字母。<br /></font>　　因为 XHTML文档是XML应用程序， XML 对大小写是敏感的。象 &amp;lt;br&amp;gt; 和 &amp;lt;BR&amp;gt; 是两个不同的标记。如错误代码：<br />　　&amp;lt;BODY&amp;gt;<br />　　&amp;lt;P&amp;gt;This is a paragraph&amp;lt;/P&amp;gt;<br />　　&amp;lt;/BODY&amp;gt; <br />　　正确格式为：<br />　　&amp;lt;body&amp;gt;<br />　　&amp;lt;p&amp;gt;This is a paragraph&amp;lt;/p&amp;gt;<br />　　&amp;lt;/body&amp;gt;</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　<font color="#ff0000">所有的 XHTML 元素一定要关闭</font></p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　不能有没有关闭的空的元素存在我们的代码中，其实对于这点我们是比较好结束的，有开始就应该有结束吗？例如错误代码：<br />　　&amp;lt;p&amp;gt;This is a paragraph<br />　　&amp;lt;p&amp;gt;This is another paragraph<br />　　正确的为：<br />　　&amp;lt;p&amp;gt;This is a paragraph&amp;lt;/p&amp;gt;<br />　　&amp;lt;p&amp;gt;This is another paragraph&amp;lt;/p&amp;gt;<br />　　<font color="#ff0000">独立的一个标签我们也要结束用 /&amp;gt;来结束。<br /></font>　　例如：错误代码<br />　　This is a break&amp;lt;br&amp;gt;<br />　　Here comes a horizontal rule:&amp;lt;hr&amp;gt;<br />　　Here's an image &amp;lt;img src=&amp;quot;happy.gif&amp;quot; alt=&amp;quot;Happy face&amp;quot;&amp;gt;<br />　　正确代码：<br />　　This is a break&amp;lt;br /&amp;gt;<br />　　Here comes a horizontal rule:&amp;lt;hr /&amp;gt;<br />　　Here's an image &amp;lt;img src=&amp;quot;happy.gif&amp;quot; alt=&amp;quot;Happy face&amp;quot; /&amp;gt;<br />　　通过上面的几个例子我们基本上看出了HTML和XHTML之间的不同，那么我们应该从现在起应该试着改变我们现在的HTML，例如都使用小写的标记、在标记之后加上结束标记的符号 /&amp;gt;。<br />　　<font color="#0000ff">XHTML 的语法<br /></font>　　简单的说写 XHTML 要用干净的 HTML 语法。<br />　　XHTML的一些其他语法要求：<br />　　<font color="#ff0000">属性名字必须小写。</font>如：<br />　　错误代码：<br />　　&amp;lt;table WIDTH=&amp;quot;100%&amp;quot;&amp;gt;<br />　　正确的代码：<br />　　&amp;lt;table width=&amp;quot;100%&amp;quot;&amp;gt; <br />　　<font color="#ff0000">属性值必须要被引用。</font>如：<br />　　错误的代码：<br />　　&amp;lt;table width=100%&amp;gt;<br />　　正确的代码：<br />　　&amp;lt;table width=&amp;quot;100%&amp;quot;&amp;gt; <br />　　<font color="#ff0000">属性的缩写被禁止。</font>如：<br />　　错误的代码：<br />　　&amp;lt;dl compact&amp;gt;<br />　　&amp;lt;input checked&amp;gt;<br />　　&amp;lt;input readonly&amp;gt;<br />　　&amp;lt;input disabled&amp;gt;<br />　　&amp;lt;option selected&amp;gt;<br />　　&amp;lt;frame noresize&amp;gt;<br />　　正确的代码：<br />　　&amp;lt;dl compact=&amp;quot;compact&amp;quot;&amp;gt;<br />　　&amp;lt;input checked=&amp;quot;checked&amp;quot; /&amp;gt;<br />　　&amp;lt;input readonly=&amp;quot;readonly&amp;quot; /&amp;gt;<br />　　&amp;lt;input disabled=&amp;quot;disabled&amp;quot; /&amp;gt;<br />　　&amp;lt;option selected=&amp;quot;selected&amp;quot; /&amp;gt;<br />　　&amp;lt;frame noresize=&amp;quot;noresize&amp;quot; /&amp;gt;<br />　　列出一个表让大家知道：<br />　　HTML　　　　　　　　　　XHTML <br />　　compact　　　　　　　compact=&amp;quot;compact&amp;quot; <br />　　checked　　　　　　　checked=&amp;quot;checked&amp;quot; <br />　　declare　　　　　　　declare=&amp;quot;declare&amp;quot; <br />　　readonly　　　　　　 readonly=&amp;quot;readonly&amp;quot; <br />　　disabled　　　　　　　disabled=&amp;quot;disabled&amp;quot; <br />　　selected　　　　　　selected=&amp;quot;selected&amp;quot; <br />　　defer　　　　　　　　defer=&amp;quot;defer&amp;quot; <br />　　ismap　　　　　　　　ismap=&amp;quot;ismap&amp;quot; <br />　　nohref　　　　　　　nohref=&amp;quot;nohref&amp;quot; <br />　　noshade　　　　　　　noshade=&amp;quot;noshade&amp;quot; <br />　　nowrap　　　　　　　nowrap=&amp;quot;nowrap&amp;quot; <br />　　multiple　　　　　　multiple=&amp;quot;multiple&amp;quot; <br />　　noresize　　　　　　noresize=&amp;quot;noresize&amp;quot; <br /><br />　　<font color="#ff0000">用id属性代替name属性。</font>如：<br />　　HTML 4.01 中为a，applet, frame, iframe, img 和 map定义了一个name属性.在 XHTML 里name属性是不能被使用的，应该用id 来替换它。如：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　　错误代码：<br />　　&amp;lt;img src=&amp;quot;picture.gif&amp;quot; name=&amp;quot;picture1&amp;quot; /&amp;gt; <br />&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;正确的代码：<br />　　&amp;lt;img src=&amp;quot;picture.gif&amp;quot; id=&amp;quot;picture1&amp;quot; /&amp;gt; <br />　　注意：我们为了使旧浏览器也能正常的执行该内容我们也可以在标签中同时使用id和name属性。如：<br />　　&amp;lt;img src=&amp;quot;picture.gif&amp;quot; id=&amp;quot;picture1&amp;quot; name=&amp;quot;picture1&amp;quot; /&amp;gt; <br />　　为了适应新的浏览器浏览我们在上述代码中的最后我加了/来结束标签。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　</p><table class="newsmain" id="table4" cellspacing="0" cellpadding="4" width="99%" align="center" bgcolor="#ffffff" border="0"><tbody><tr><td class="newscontent"><p style="LINE-HEIGHT: 150%"><font color="#0000ff">XHTML DTD定义文档的类型。<br /></font>　　在XHTML中我们必须声明文档的类型，以便于浏览器知道你的文档是什么类型的，而且声明部分要加在文档的head之前。如：<br />　　&amp;lt;!DOCTYPE Doctype goes here&amp;gt;<br />　　&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;<br />　　&amp;lt;head&amp;gt;<br />　　&amp;lt;title&amp;gt;Title goes here&amp;lt;/title&amp;gt;<br />　　&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;<br />　　Body text goes here<br />　　&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;<br />　　注:DOCTYPE声明不是 XHTML 文档的一部分，它也不是文档的一个元素，所以我们没必要加上结束标签。<br />　　注:XHTML属性都是在&amp;lt;html&amp;gt;标签里面。然而当我们在w3.org验证时，并不解释我们的文档有没有声明类型。这是因为&amp;quot;xmlns=http://www.w3.org/1999/xhtml&amp;quot;是一个固定的值，如果你没声明的话，它也会被自动的加到&amp;lt;html&amp;gt;标签前。<br /><br />　　我们使用DOCTYPE时的基本机构：<br />　　&amp;lt;!DOCTYPE ...&amp;gt;<br />　　&amp;lt;html&amp;gt;<br />　　&amp;lt;head&amp;gt;<br />　　&amp;lt;title&amp;gt;... &amp;lt;/title&amp;gt;<br />　　&amp;lt;/head&amp;gt;<br />　　&amp;lt;body&amp;gt; ... &amp;lt;/body&amp;gt;<br />　　&amp;lt;/html&amp;gt; <br /><br />　　DOCTYPE是document type(文档类型)的简写，用来说明你用的XHTML或者HTML是什么版本。</p><p style="LINE-HEIGHT: 150%">　　其中的DTD(例如xhtml1-transitional.dtd)叫文档类型定义，里面包含了文档的规则，浏览器就根据你定义的DTD来解释你页面的标识，并展现出来。</p><p style="LINE-HEIGHT: 150%">　　要建立符合标准的网页，DOCTYPE声明是必不可少的关键组成部分；除非你的XHTML确定了一个正确的DOCTYPE，否则你的标识和CSS都不会生效。</p><p style="LINE-HEIGHT: 150%">　　XHTML 1.0 提供了三种DTD声明可供选择：</p><p style="LINE-HEIGHT: 150%">　　过渡的(Transitional):要求非常宽松的DTD，它允许你继续使用HTML4.01的标识(但是要符合xhtml的写法)。完整代码如下：</p><p style="LINE-HEIGHT: 150%">　　&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;</p><p style="LINE-HEIGHT: 150%">　　严格的(Strict):要求严格的DTD，你不能使用任何表现层的标识和属性，完整代码如下：<br /><br />&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Strict//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&amp;quot;&amp;gt;</p><p style="LINE-HEIGHT: 150%">　　框架的(Frameset):专门针对框架页面设计使用的DTD，如果你的页面中包含有框架，需要采用这种DTD。完整代码如下：</p><p style="LINE-HEIGHT: 150%">　　&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Frameset//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd&amp;quot;&amp;gt;</p><p style="LINE-HEIGHT: 150%">　　<font color="#0000ff">如何转换现有的结构为XHTML</font></p><p style="LINE-HEIGHT: 150%">　　我们选择什么样的DOCTYPE？理想情况当然是严格的DTD，但对于我们大多数刚接触web标准的设计师来说，过渡的DTD(XHTML 1.0 Transitional)是目前理想选择(包括本站，使用的也是过渡型DTD)。因为这种DTD还允许我们使用表现层的标识、元素和属性，也比较容易通过W3C的代码校验。</p><p style="LINE-HEIGHT: 150%">　　我们从现在的HTML转换为XHTML注意以下几点： <br />　</p><p style="LINE-HEIGHT: 150%">　　一、在每个页面的首部都加上文档类型的说明。如：</p><p style="LINE-HEIGHT: 150%">　　&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;</p><p style="LINE-HEIGHT: 150%">　　当然可以选择其他类型的。</p><p style="LINE-HEIGHT: 150%">　　二、标记和name 要都用小写。</p><p style="LINE-HEIGHT: 150%">　　我们可以自己编写一个替换程序，将你的HTML文档中的所有的标记都换为小写字母，还有name属性也要变为小写。</p><p style="LINE-HEIGHT: 150%">　　三、所有的属性值都要用引号引起来。</p><p style="LINE-HEIGHT: 150%">　　四、单独的标签，如: &amp;lt;hr&amp;gt; , &amp;lt;br&amp;gt; and &amp;lt;img&amp;gt;，都要在后面加/来结束。在这里不建议使用诸如：&amp;lt;img&amp;gt;和&amp;lt;/img&amp;gt;形式的方式，直接在其后面加/就可以了，如&amp;lt;br /&amp;gt;。</p><p style="LINE-HEIGHT: 150%">　　五、我们打开W3C DTD 的官方网站：<font color="#000000">http://validator.w3.org/check/referer，验证时一般错误可能会出现在你的标签嵌套里。也可以用官方网站提供的转换工具tidy来实现转换：http://www.w3.org/People/Raggett/tidy/，我不建议大家直接来使用该工具来验证，因为我们毕竟是新学XHTML我们还是自己转换，这样我们可以熟悉XHTML啊，再者说我们还要学习tidy工具的使用，那样也是比较麻烦的。</font></p><p style="LINE-HEIGHT: 150%">　　六、我们直接打开下面的页面可以直接输入网址来验证我们的程序了：</p><p style="LINE-HEIGHT: 150%">　　<font color="#0000ff">XHTML 的模块化</font></p><p style="LINE-HEIGHT: 150%">　　为什么要模块化设计XHTML呢？XHTML虽然简单，但是它的内容很多，包括了一个网络设计师需要的绝大多数功能。XHTML一方面内容繁多复杂，但是从另一个角度来看它却是非常简单的。为了将XHTML分割成小的模块，W3C已经建立起了小型的已经定义好了的一系列XHTML元素，他们独立的能被与其他XML标准合并成的大型的更复杂的程序的简单设备所使用。</p><p style="LINE-HEIGHT: 150%">　　通过XHTML模型，程序设计师能够做如下的事情：</p><p style="LINE-HEIGHT: 150%">　　1.选择那些能够被使用XHTML构建块标准的设备所支持的元素。<br />　　2.在遵循XHTML标准的同时使用XML可以对XHTML扩展。<br />　　3.简单化的XHTML可以应用于像掌上电脑、移动电话、电视和家用电器等设备。<br />　　4.通过加入心的XML功能（像声音、多媒体的）将XHTML延续到复杂程序的设计上。<br />　　5.像XHTML基本（XHTML对于移动设备的一个子集）那样来定义XHTML的轮廓。 </p><p style="LINE-HEIGHT: 150%">　</p><table id="table5" cellspacing="0" width="560" border="1"><tbody><tr><th valign="top" align="left" width="35%"><p style="LINE-HEIGHT: 150%" align="center">模块名</p></th><th valign="top" align="left" width="65%"><p style="LINE-HEIGHT: 150%" align="center">描述</p></th></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Applet Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%"><b>*</b> applet元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Base Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义基本元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Basic Forms Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义基本的表单元素</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Basic Tables Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义基本的表格元素</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Bi-directional Text Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 bdo 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Client Image Map Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义浏览器的 image map 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Edit Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">Defines the editing elements del and ins.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Forms Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">Defines all elements used in forms.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Frames Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义框架集元素</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Hypertext Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 a 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Iframe Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 iframe 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Image Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 img 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Intrinsic Events Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义事件改变属性元素</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Legacy Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">Defines deprecated<b>*</b> elements and attributes.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Link Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义link 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">List Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 list 元素 ol, li, ul, dd, dt, dl.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Metainformation Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 meta 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Name Identification Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">Defines the deprecated<b>*</b> name attribute.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Object Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义object 和param 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Presentation Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义表现元素如 b 和 i.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Scripting Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 script and noscript 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Server Image Map Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 server side image map 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Structure Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义结构 html, head, title and body.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Style Attribute Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 style 属性.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Style Sheet Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义style 元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Tables Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义表内应用的元素.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Target Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 target 属性.</p></td></tr><tr><td valign="top"><p style="LINE-HEIGHT: 150%">Text Module</p></td><td valign="top"><p style="LINE-HEIGHT: 150%">定义 text container 元素如： p and h1.</p></td></tr></tbody></table><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><b>XHTML代码规范</b></p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">　</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">我们必须先了解一下web标准有关代码的规范。了解这些规范可以帮助你少走弯路,尽快通过代码校验。</p><h3 style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">1.所有的标记都必须要有一个相应的结束标记</h3><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">以前在HTML中，你可以打开许多标签，例如&amp;lt;p&amp;gt;和&amp;lt;li&amp;gt;而不一定写对应的&amp;lt;/p&amp;gt;和&amp;lt;/li&amp;gt;来关闭它们。但在XHTML中这是不合法的。XHTML要求有严谨的结构，所有标签必须关闭。如果是单独不成对的标签，在标签最后加一个&amp;quot;/&amp;quot;来关闭它。例如:</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;br /&amp;gt;&amp;lt;img height=&amp;quot;80&amp;quot; alt=&amp;quot;网页设计师&amp;quot; src=&amp;quot;../images/logo_w3cn_200x80.gif&amp;quot; width=&amp;quot;200&amp;quot; /&amp;gt;</span> </p><h3 style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">2.所有标签的元素和属性的名字都必须使用小写</h3><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">与HTML不一样，XHTML对大小写是敏感的，&amp;lt;title&amp;gt;和&amp;lt;TITLE&amp;gt;是不同的标签。XHTML要求所有的标签和属性的名字都必须使用小写。例如：&amp;lt;BODY&amp;gt;必须写成&amp;lt;body&amp;gt; 。大小写夹杂也是不被认可的，通常dreamweaver自动生成的属性名字&amp;quot;onMouseOver&amp;quot;也必须修改成&amp;quot;onmouseover&amp;quot;。</p><h3 style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">3.所有的XML标记都必须合理嵌套</h3><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">同样因为XHTML要求有严谨的结构，因此所有的嵌套都必须按顺序，以前我们这样写的代码：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&amp;lt;/p&amp;gt;/b&amp;gt;</span> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">必须修改为：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&amp;lt;/b&amp;gt;/p&amp;gt;</span> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">就是说，一层一层的嵌套必须是严格对称。</p><h3 style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">4.所有的属性必须用引号&amp;quot;&amp;quot;括起来</h3><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">在HTML中，你可以不需要给属性值加引号，但是在XHTML中，它们必须被加引号。例如:</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;height=80&amp;gt;</span> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">必须修改为：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;height=&amp;quot;80&amp;quot;&amp;gt;</span> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">特殊情况，你需要在属性值里使用双引号，你可以用&amp;quot;，单引号可以使用&amp;amp;apos;，例如：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;alt=&amp;quot;say&amp;amp;apos;hello&amp;amp;apos;&amp;quot;&amp;gt;</span> </p><h3 style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">5.把所有&amp;lt;和&amp;amp;特殊符号用编码表示</h3><ul><li><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">任何小于号（&amp;lt;），不是标签的一部分，都必须被编码为<span class="code">&amp;amp; l t ;</span> </p></li><li><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">任何大于号（&amp;gt;），不是标签的一部分，都必须被编码为<span class="code">&amp;amp; g t ;</span> </p></li><li><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">任何与号（&amp;amp;），不是实体的一部分的，都必须被编码为<span class="code">&amp;amp; a m p;</span> </p></li></ul><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">注：以上字符之间无空格。</p><h3 style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">6.给所有属性赋一个值</h3><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">XHTML规定所有属性都必须有一个值，没有值的就重复本身。例如：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;td nowrap&amp;gt;</span> <span class="code">&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;shirt&amp;quot; value=&amp;quot;medium&amp;quot; checked&amp;gt;</span> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">必须修改为：</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;td nowrap=&amp;quot;nowrap&amp;quot;&amp;gt;</span> <span class="code">&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;shirt&amp;quot; value=&amp;quot;medium&amp;quot; checked=&amp;quot;checked&amp;quot;&amp;gt;</span> </p><h3 style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">7.不要在注释内容中使“--”</h3><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">“--”只能发生在XHTML注释的开头和结束，也就是说，在内容中它们不再有效。例如下面的代码是无效的:</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;!--这里是注释-----------这里是注释--&amp;gt;</span> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">用等号或者空格替换内部的虚线。</p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%"><span class="code">&amp;lt;!--这里是注释============这里是注释--&amp;gt;</span> </p><p style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; LINE-HEIGHT: 150%">以上这些规范有的看上去比较奇怪，但这一切都是为了使我们的代码有一个统一、唯一的标准，便于以后的数据再利用。</p></td></tr></tbody></table>]]></description> 
<guid isPermaLink="false">6074232@http://www21.bokee.com/</guid> 
<dc:subject>学习资料</dc:subject> 
<dc:date>2007-01-28T20:34:51Z</dc:date> 
</item> 

</channel> 
</rss> 
