关于作者

姓名:

性别:男

出生日期:--

地区:江西-南昌

联系电话:

QQ:--

婚否:保密
用户名:www21
笔名:东方之子
地区: 江西-南昌
行业:本科

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言


最新评论

网址收藏夹

资料收藏夹

酷站欣赏

访问统计:
文章个数:65
评论个数:1
留言条数:0




Powered by BlogDriver 2.1

东方之子

 

学习的最高境界是将学过的东西忘得一干二净! 剩下的便是精髓!

文章

Linux Shell
友好阅读版本 http://www.linuxsir.org/main/?q=node/135


本文的内容来源于 MUO 的 Basics 部分,其原始英文版可以从这里获得http://www.mandrakeuser.org/docs/。中文版来自吴晓光的CMUO http://dummy.linux.net.cn/~xgwu/cmuo/。MUO 是 Mandrake Linux(http://www.mandrakelinux.com/)为用户提供的入门手册,其内容实用并且实时更新,非常适合初学者做入门参考。与常见的各种Linux教程不同,MUO介绍给Linux初学者的是学习Linux的方法而非对某个系统的描述,这对各种有着千差万别的Linux发行版的学习尤为重要。本文编译整理时对相关章节做了相应的删改处理,去掉了针对Mandrake Linux的部分内容。

使用 Shell
以下将介绍并解释基本的 shell 命令和机制。
第一篇:超级工具/Terminals,xterms 和 Shells
超级工具
您或许听过这样的论调:命令行(the mommand line)早就已经过时了,那东西神秘兮兮的,等等。有些人甚至觉得操作系统中应该没有这些命令才好。
事实是上,您可以不懂任何 shell ,就能使用 Linux 。您启动系统后可以直接进入 X Window ,最后在 X Window 下关机。
我坚信,用 Linux 而不懂 shell ,就象开车只会用头档(first gear)一样。当然,最初看起来,直接而简单,在大多数情况下都管用。但速度慢,而且无法真正体验驾驶的乐趣。
对,命令行很有趣。就象用一大堆收集到的积木,竟可以完成许多意想不到的创举,一些极其复杂的工作,只需几行命令就可以解决。这是因为,在 Unix 中,shell 可不是简单的命令解释器(典型的有 Windows 中的 DOS ),而是一个全功能的编程环境。
这并不意味着 shell 非常容易学通,您知道,好事多磨,这还是要花点工夫的。;-) 但请相信我,这绝对值得。您在很短时间内,就能被一大帮门外汉吹捧为 Unix wizard(奇才) 。*grin*
为了说明 shell ,这里需要一些背景知识。
Terminals, xterms 与 Shells
追溯到 Unix 诞生的那个年代,当时还没有现在流行的"个人计算机"。被称为计算机的机器,还是吞吐磁带与 magnetic memory (用术语'core'来表示系统 memory)的庞然大物。DEC 公司(现在的 Compaq)推出的 PDP-11 ,体积小(被称为 mini)而且价格底,在大学中引起了巨大的反响,很多学校直到那时才买得起一台计算机(PDP-11 物美价廉,只有 10000$)。

这些机器的操作系统由汇编语言、机器语言写成,所以运行起来效率很高,但都无法移植(unportable)。每家计算机公司都给自己的机器配上独有的操作系统,然后再销售。

这种笨拙的作法很快就被人们意识到了,于是就开始兴建一个可以在不同品牌机器上运行的操作系统。1969 年,Ken Thompson 开始写后来成为 Unix 的第一行代码。(Thompson 曾经参加了一个项目:MULTICS,Unix 是与这有关的一个玩笑词) 其实,Dennis Ritchie 为这个新的操作系统设计了一种新的编程语言-- C 语言后,事情才真正开始。

虽然 Unix 的效率不及原来的操作系统,但有三个突出的优点:可以任意移植到其他机器,其中的 C 语言大大简化了编程,而且这些都 free 。很快,全美国的大学都忙着开始为机器安装 Unix 。

终端(Terminals)

Unix 是可以在许多种机器上运行的操作系统,但人们又如何使用这些机器呢?他们是通过哑终端来连接到这些机器,也就是用键盘、显示器及足够的 electronics (电子元件)组成的机器与中央计算机(central computer)相连。在这些终端上,用户可以敲字符(teletypy),这就是字符串'tty'表示终端设备文件,和'getty'命令的名称来历。

您可能会问,现在这些东西都在哪儿。 这些终端的厂家无法达成一项最终标准,这导致每种牌子的终端都有各自的键盘布局、各自的在屏幕上显示字符的方法、发送或接收什么信号表示什么字符、控制代码等等。

为了避免这些混乱,就创建了一个含有所有不同终端特性的(capability)文件,这就是'termcap'。用一个工具打开'/etc/termcap'瞧瞧,可别吓着了 ;-) 。

Linux 终端大多数用'vt100'或'linux'作为终端类型。
xterms

在八十年代初期,产生了一个 Unix 的图形子系统-- the X Window System 。九十年代早期,为了更好地实现基于 Intel 的 Unix 类系统上(如FreeBSD、NetBSD、Linux)的应用,产生了一个系统分支-- XFree86 。

X Window 中一个很大的好处是可以运行多个虚拟(virtual)终端。甚至在 X Window 下就有这么个应用程序--'xterm'。您将发现'xterm'和'virtual terminal'在很多情况下都是一样的。有的地方说'打开一个 xterm',其实您不是非要用'xterm'程序,其他的终端模拟器(terminal emulator),如 rxvt、konsole、aterm、eterm、wterm 等等,一样有效。

终端模拟器(又称为虚拟终端)通过伪(pseudo) tty 设备-- pty 与系统相连,并且使用自己的显示标准-- xterm 。这导致不同的终端模拟器可能在一些按键或程序上存在细小的差别,这取决于模拟器多大程度上遵守了'xterm'的显示标准。

Shells

为了在终端中运行程序,需要 shell 。shell 是操作系统的一部分,用来与用户打交道,并且可以用来协调各个命令。

第一个真正的 Unix shell -- 'sh',亦称为'Bourne shell',诞生于 1975 年,作者是 Steve Bourne 。很快,出现了其他 shell ,如基于原始'Bourne shell'的'ksh'、'zsh',后者常用作专属 Unixes 系统中的标准 shell ;也有一些从 C 语言中衍生出来的 shell ,如'csh'或'tcsh'。

在 Linux 中,标注的 shell 是'bash',即 the GNU Bourne-Again Shell (有点玩笑的味道……)。这个 shell 功能非常强大(甚至有人觉得太庞大了),压缩的 man page 就有 50 KB 。

Shell 起步

首先,有一点小说明:在平常应用中,建议您不要用'root'帐号运行 shell ,如果您还是新手,这一点尤其要注意。作为普通用户,不管您有意还是无意,都无法破坏系统;但如果是'root',那就不同了,只要敲几个字母,就可能导致灾难性后果。

当您登入系统或打开一个 xterm 窗口,首先看到的是提示符(prompt)。Red Hat Linux 的标准提示符包括了您的用户名、登入的主机名(没有设置的话,是'localhost')、当前所在的目录(working directory)、提示符号:

[tom@belbo tom]$

我以用户名'tom'登入名为'belbo'的主机,当前在我的 home 目录--'/home/tom'中。'root'的提示符:

[root@belbo root]#

除了不同的用户名外,提示符号由'$'变成了'#'。根据 Bourne shell 的传统,普通用户的提示符以'$'结尾,而超级用户用'#'。

提示符的每个部分都可以定制,您在后面将有更深的了解。

要运行命令的话,您只要在提示符后敲进命令,然后在按 <ENTER> 键。shell 将在其路径中(详情见后)搜索这个命令,找到以后就运行,并在终端里输出相应的结果(如果有的话),命令结束后,再给出新的提示符:

[tom@belbo tom]$ whoami
tom
[tom@belbo tom]$

顺带指出,当您敲 ENTER 时,光标(cursor)在哪里并不要紧,因为 shell 总是会整行地读取。

基本的命令有:'ls'(list directory ,列出目录内容)、'cp'(copy ,复制)、'mv'(move / rename ,移动/重命名),'cd '(change directory ,改变目录),这些命令后面都可以跟上一帮可选项,这方面 man page 有详细的介绍(man ls, man mv 等等)。
在您动身前往 shell 领地前,这里有几个术语(terminology)的简短说明。命令可能带一些可选项(options)、参数(arguments):

mv -i file dir

其中'-i'是命令'mv'的一个可选项,而'file'和'dir'则是参数。所有可选项在该命令的 man page 都中有详细的介绍(此例中用 man mv),而参数则由您提供。可选项决定命令如何工作,而参数则用于确定命令作用的目标。

到目前为止,介绍得有点象许多人厌恶轻视的 DOS shell ,但伴随着下面的介绍,您将会有新的体验。

第二篇:自动补齐/命令行的历史记录/编辑命令行/可用的 Shell 快捷方式

Unix (及后继者 Linux)在命令行下面诞生,因此,Unix 中的命令行有许多非常实用的功能。在本篇中,我们将来作一些了解。

自动补齐

如何用'cd'(改变目录,change directory)最快地从您当前所在的 home 目录跳到'/usr/src/redhat/'呢?

cd /u<TAB>sr<TAB>r<TAB>

这称为'命令行自动补齐'(automatic command line completion),这在平常应用中是不可缺少的。让我们仔细看看这个例子:

cd /u<TAB>

扩展成了 cd /usr/ ,很简单吧。下面的

cd /u<TAB>sr<TAB>

扩展为 cd /usr/src/ 。如果您只敲了cd /u<TAB>s<TAB>,'/usr'下匹配的('cd /u*/s*')三个子目录将列出供您选择:'/usr/sbin'、'/usr/share'和'/usr/src'。

因此,<TAB> 键可以很方便地用于根据前几个字母,来查找匹配的文件或子目录。比如,ls /usr/bin/zip<TAB> 将列出所有'/usr/bin'下面,以字符串'zip'开头的文件或子目录。当然,完成这类任务还有更厉害的命令,但这个方法确实很管用。

另外,碰到长文件名时就显得特别方便。假设您要安装一个名为'boomshakalakwhizbang-4.6.4.5-i586.rpm'的 RPM 包,您输入 rpm -i boom<TAB> ,如果目录下没有其他文件能够匹配,那 shell 就会自动帮忙补齐。

cd /u<TAB>sr<TAB>l<TAB>

将扩展成 cd /usr/src/linux ,并等待继续。'/usr/src'中有两个匹配的目录:'/usr/src/linux-[...]'、'/usr/src/linux'。如何告诉 shell 您想要后面的那个呢?只要跟一个斜线(/ ,slash),就可以选择后面的那个了。

假如您不确定是'/usr/src/linux/Documentation'还是'/usr/src/linux/documentation'。而您知道,Linux 是区分大小写的。如果已经仔细读过前面部分的话,您想到可以用:

cd /u<TAB>sr<TAB>l<TAB>/d<TAB>

扩展成了'/usr/src/linux/drivers/',因此应该是'Documentation'(大写的'D')。

这种补齐对命令也有效:

[tom@belbo tom]$ gre<TAB>

grecord grefer grep

[tom@belbo tom]$ gre

在这里 shell 将列出所有以字符串'gre'开头的已知命令。

命令行的历史记录

通过按向上方向键,您可以向后遍历近来在该控制台下输入的命令。用向下方向键可以向前遍历。与 SHIFT 键连用的话,您还可以遍历以往在该控制台中的输出。您也可以编辑旧的命令,然后再运行。

按 <CTRL r> 后,shell 就进入"reverse-i(ncremental)-search"(向后增量搜索)模式。现在输入您要找的命令的首字母:

(reverse-i-search)`':. 敲入 'i'可能会变成:

(reverse-i-search)`i': isdnctrl hangup ippp0

如果您再按 <ENTER> 键,上面的命令将再次执行。而如果您按了向右、向左方向键或 <ESC> ,上面的命令将回到普通的命令行,这样您就可以进行适当编辑。

编辑命令行

通过光标和功能键(Home、End 等键),您可以浏览并编辑命令行,如果您需要,还可以用键盘的快捷方式来完成一般的编辑:

l <CTRL k>:删除从光标到行尾的部分

l <CTRL u>:删除从光标到行首的部分

l <ALT d>:删除从光标到当前单词结尾的部分

l <CTRL w>:删除从光标到当前单词开头的部分

l <CTRL a>:将光标移到行首

l <CTRL e>:将光标移到行尾

l <ALT a>:将光标移到当前单词头部

l <ALT e>:将光标移到当前单词尾部

l <CTRL y>:插入最近删除的单词

l <!$>:重复前一个命令最后的参数。

例如:您用命令 mkdir peter/pan/documents/tinkerbell 新建了一个目录,现在您向用命令'cd'进入该目录,您可以用 cd !$,shell 将把前一个命令'mkdir'的参数添加到现在的'cd'后面。

当您更深入了解Linux后,将看到这些快捷方式在其他应用程序下输入时,有时也有效,比如,在浏览器中的输入框中。

可用的 Shell 快捷方式

Red Hat Linux 带有不少快捷方式,其中一部分是 bash 原来就有的,而还有一些则是为您预先设置的(在后面您将看到如何设置)。

由于 home 目录是每位用户的活动中心,许多 Unix 对此有特殊的快捷方式。

'~'就是您的 home 目录的简写形式。我们假设您在其他目录,想把一个名为'sometext'的文件复制到您 home 目录下的 'docs'子目录中。除了输入:

cp sometext /home/myusername/docs

您还可以用简写:

cp sometext ~/docs

理论上,这也可以应用在命令'cd'上。无论当前路径在哪里,cd ~ 将回到您的 home 目录。其实还可以简化,只要键入 cd ,就可以返回 home 目录了。

Red Hat Linux 为您提供了一些预先设置的快捷方式(称为'别名',aliases),比如:

l ll :将执行'ls -l -k'(以长格式列出目录内容,包括一些文件属性,并以 KB 而不是 byte 为单位显示文件大小)

l ls :将执行'ls -F --color=auto'(列出目录内容,加上文件类型标识,并使用颜色)

现在,您应该对 shell 及一些快捷方式有了进一步的了解,下面我们来看看除了应用一些简单的命令,shell 还能作什么。

第三篇:命令的排列/命令的任务调度/命令的替换

命令的排列

现在您将看到一些常用的命令排列。您可能想在一行中给出所有命令,然后就可以把注意力转移到其他地方。没问题,shell 允许您在不同的命令之间,放上特殊的排列字符(queuing characters) 。这儿将介绍最常用的两种。

请注意,为了看起来更清楚,我在这些字符两旁加了空格。而在实际应用中,您不一定要这么做,'ls -a ; du -hs'和'ls -a;du -hs'的效果是一样的。

command1 ; command2

先执行 command1 ,不管 command1 是否出错,接下来执行 command2 。

例如:

ls -a ; du -hs

将先在屏幕上列出目录中的所有内容,然后列出所有目录及其子目录所占磁盘大小。

command1 && command2

只有当 command1 正确运行完毕后,才执行 command2 。

例如:

ls -a bogusdir && du -hs

将返回 ls: bogusdir: No such file or directory ,而'du'则根本没有运行(这是因为您没有'bogusdir'目录)。如果您将符号换成了';','du'将被执行。

为了进一步说明';'和'&&'的区别,及一般命令排列的用处,下面举一个经典的例子:Linux 内核的编译和安装。

要编译、安装 Linux ,您需要执行一串命令:'make dep'、'make clean'、'make bzImage'、'make modules'、'make modules_install'和'make install'。如果要等一个命令完成后,再输入下一个,再等,再输入,……,那就太麻烦了。另一方面,每个命令只有当前面的命令都正确执行完毕后,才能开始执行。如果您用';'来排列命令,则即使有命令执行失败,后面的也照常运行,最后,您可能在'/boot'目录下得到一个有问题的内核映像(image)。而用'&&':

make dep && make clean && make bzImage && make modules && make modules_install && make install

不需要中途打断,就可以编译内核及其模块,并完成后面的安装。

命令的任务调度

当您在终端里运行一个命令或开启一个程序时,终端要等到命令或程序运行完毕后,才能再被使用。在 Unix 中,我们称这样的命令或程序在前台(foreground)运行。如果您想在终端下运行另一个命令,则需要再打开一个新的终端。

但这里还有一个更优雅的办法,称为任务调度(jobbing)或后台(backgrounding)。当您运用任务的调度或将命令置于后台,终端就立即解放了,这样一来,终端立即就可以接受新的输入。为实现这样的目的,您只需在命令后面添加一个 & :

gqview &

告诉 shell 将图片查看器'GQview'放到后台去执行(即当成 job 来运行)。

命令 jobs 将告诉您,在这个终端窗口中,运行着哪些命令与程序:

jobs

[1]+ Running gqview &

当您要关闭终端窗口时,这一点就很重要,因为关闭终端将导致所有在其中运行的任务都将被中止,在此例中,如果您关闭了终端,由这个终端开启的 GQview 程序也将被关闭。

但如何将前台运行的一个程序放到后台去?没问题:

gqview

<CTRL z>

[2]+ Stopped gqview

bg

[2]+ gqview &

组合键 <CTRL z> 将挂起终端中正在运行的程序,然后您就可以用 bg 命令将其放到后台去执行。

请注意,在后台运行图形应用程序有时候是有用处的,这样可以在终端下显示这个程序的出错信息,虽然这对您可能没有直接的帮助,当如果碰到了麻烦,向别人询问时,这些出错提示就有用武之地了。

一些图形程序,很可能还处在测试期(Beta),尽管在后台执行,也会在终端中输出一些信息。如果您对此不满,可以用下面命令:

command &>/dev/null &

这不仅将程序送到后台执行,还将其输出发到'/dev/null'文件。'/dev/null'是系统的"碎纸机" (shredder),所有送到那里的信息都将消失殆尽。

命令的替换

命令替换(Command substitution)是一项很实用的功能。我们假设,您想看看 XFree86 文档中的 'README.mouse'文件,但您不知道这个文件的位置。但您是位机灵的用户,已经听说了'locate'命令,也安装了'slocate'包,您就可以用:

locate README.mouse

发现那个文件在'/usr/X11R6/lib/X11/doc'。现在您就可以在终端里用'less'或在文件管理器中进入那个目录然后读取文件。而命令替换可以给您带来一些便捷:

less $(locate README.mouse)

一步到位。命令'locate README.mouse'的输出(= /usr/X11R6/lib/X11/doc/README.mouse)作为'less'的参数,然后就可以显示文件内容了。

这种机制的语法是:

command1 $(command2)

除了'$( )',您还可以用后引号(backquote):

command1 `command2`

这样虽然可以减少输入,但可读性差,而且很容易就和没有替换功能的一般单引号混淆。我更欣赏前一种方法,但这最终起决于您。

这里有另外一个例子。我们假设,您打算结束一个名为'rob'的程序。您先得用命令'pidof'找出相应的进程号(Process ID),然后以这个 PID 为参数,运行'kill'命令,这样就可以结束'rob'程序。除了用:

pidof rob

567

kill 567

您还可以试试:

kill `pidof rob`

怎么样,效率有所提高吧?

在下一篇中,我将接着介绍 shell 的另外两种实用的机制:文件名匹配、输出重定向。

第四篇:文件名匹配/输出重定向

文件名匹配

文件名匹配使得您不必一一写出名称,就可以指定多个文件。您将用到一些特殊的字符,称为通配符(wildcards)。

假设您想用'rm'命令删除目录下所有以字符串'.bak'结尾的文件。除了在'rm'后跟上所有文件名作为参数,您还可以用通配符'*':

rm *.bak

'*'可匹配一个或多个字符。在本例中,您告诉 shell 将命令'rm'的参数扩展到"所有以'*.bak'结尾的文件",shell 就将扩展后的参数告诉'rm'命令。

您将看到,shell 在命令执行前,就将读取并解释命令行。正是因为这个,您才可以将通配符用于 shell 命令的参数中。

让我们更进一步地来认识通配符'*'。假定您有个目录,其中含文件'124.bak'、'346.bak'及'583.bak'。您想只保留文件'583.bak',可以用:

rm *4*.bak

shell 就将'*4*.bak'扩展成"所有含'4'并以'.bak'结尾的字符串"。

注意到 rm 4*.bak 无法工作,因为这匹配的是以'4'开头的文件。由于目录中没有这样的文件,shell 将这个模式扩展为空的字符串,故'rm'将返回出错信息:

rm: cannot remove `4*.bak': No such file or directory

如果您想保留文件'345.bak',而删除'124.bak'和'583.bak'。这看起来有些难度,因为被删文件的名称除了后缀其他都不同。但幸运的是,您可以用不含有来指定文件:

rm *[!6].bak

这将被读为:除了以'6.bak'结尾的文件,删除其他所有以'.bak'结尾的文件。您必须将取反号(negation sign)与取反字符(这里是 6)放到括号中,不然的话,shell 会将惊叹号(exclamation mark)解释成历史记录替换的开始(the beginning of a history substitution)。取反号在本篇介绍的所有匹配模式中都有效。

请注意:通配符'*'与取反号连用,很容易产生问题。猜猜

rm *[!6]*.bak

表示什么?这个命令将删除所有文件,甚至包括名称中包含'6'的文件。如果您将通配符'*'放到了取反号前面和后面,实际上取反号将失效,因为 shell 将其解释为"所有名称中任何位置都不含该字符的文件"。在我们的例子里,只有文件'666.bak'不符合该模式。

第二个通配符是问号(question mark):'?'。在匹配时,一个问号只能代表一个字符。为了示范其用途,我们在上例的假设中添加两个新文件:'311.bak~'和'some.text'。现在,列出所有在点号后有四个字符的文件:

ls *.????

问号通配符能够有效地避免上面提到的'取反号陷阱'(negation trap):

rm *[!4]?.*

将扩展成"所有除了点号前倒数第二个字符为'4'的文件",也就是只保留文件'346.bak'。

您可能会问,有没有其他匹配方式?到目前为止,您只看到了在指定位置匹配唯一字符的方法。但其实您也可以这样:

ls [13]*

将列出所有以字符'1'或'3'开头的文件;在我们的例子中,文件'124.bak'、'311.bak~'和'346.bak'匹配。注意到您必须用中括号将匹配的模式括起来,否则模式只匹配以字符串'13'开头的文件。

接下来,您将高兴地看到还可以定义匹配的范围:

ls *[3-8]?.*

将列出所有点号前倒数第二个字符落在'3'到'8'范围的文件。在我们的例子中,匹配的文件是'346.bak'和'583.bak'。

引用 shell 的特殊字符

但是,上面的那些机制存在一个缺点:shell 总在命令执行前,试着进行扩展。有时候,会变得很棘手:

l 文件名包含特殊字符。假设您在那个目录中还有一个名为'!56.bak'的文件。下面试图进行模式匹配:

rm !*

rm

rm: too few arguments

shell 将'!*'解释成历史记录的替换(加入前一个命令的所有参数),而不是匹配方式。

l 命令本身带特殊字符作参数。一些 Linux 下的命令行工具,比如 (e)grep、sed、awk、find 及 locate ,都使用自己的正则表达式(regular expressions)。这些表达式与模式匹配看起来惊人地相似,但在某些地方又有所不同。

但为了使这些特殊命令生效,shell 就不能先将其当作模式匹配来解释:

find . -name [1-9]* -print

find: paths must precede expression

应该是:

find . -name '[1-9]*' -print

./346.bak

./124.bak

./583.bak

./311.bak~

您可以通过反斜线(back slash)来引用特殊字符,比如 ! 、$ 、? 或空格:

ls \!*

!56.bak

或者用(单)引号:

ls '!'*

!56.bak

请注意,要看清楚引号应该放在什么位置。命令 ls '!*' 将查找名为'!*'的文件,这是由于通配符也在引号间,所以只能依照字面来解释。

输出重定向

Unix 的理念是汇集许多小程序,每个东东都有特殊的专长。复杂的任务不是由大型软件完成,而是运用 shell 的机制,组合许多小程序共同完成。重定向就在其中发挥着重要的作用。

在多个命令间重定向

这要通过管道(pipe),由管道符号|来标识。语法是:

command1 | command2 | command3 等等

这种格式您一定已经见到过了。管道经常将一个程序的输出送到'more'或'less'来阅读。

ls -l | less

其中,第一个命令提供目录内容,第二个则将其以翻页的方式显示。更复杂的例子如:

rpm -qa | grep ^x | less

第一个命令给出所有已安装的 RPM 包,第二个则将其过滤(filter:'grep'),只剩下以'^x'开头的包,第三个命令则将结果以翻页的方式显示。

重定向至文件

有时,您希望将命令的输出结果保存到文件中,或以文件内容作为命令的参数。这可以通过'>'和'<'来实现。

command > file

将 command 的输出保存到 file 中,这将覆盖 file 中的内容:

ls > dirlist

将当前目录的内容保存到'dirlist'文件。

command < file

将 file 内容作为 command 的输入:

sort < dirlist > sdirlist

将文件'dirlist'的内容送到命令'sort',然后再将排序后的结果送到文件'sdirlist'。当然,您也可以一步到位:

ls | sort > sdirlist

一种特殊的方式是'command 2> file'。这将 command 执行的出错信息送到 file 中。这个您到时候会需要……

另一种操作符是'>>',这将输出添加到已存在的文件中:

echo "string" >> file

将 string 加到文件 file 中。这是不打开文件而完成编辑的好办法!

但是,'<'和'>'操作符都有一个重要的限制:

command < file1 > file1

将删除 file1 的内容,而

command < file1 >> file1

却可以很好地工作,将加工过的 file1 内容加回到文件中。

是不是有点多?;-) 不必惊慌,您完全可以按照自己的速度,一步步地来学习。别忘了,实践是最好的学习方法……

熟知了许多 shell 的机制后, 您可能急着想知道如何来定制环境。在后面的两篇中,您将得到这方面的启示。在最后一篇中,还有一段如何处理 shell 出错信息的常见问答(FAQ),及一些配置技巧。

第五篇:bash 配置文件/提示符/改变 $PATH

bash 配置文件

在您的 home 目录下,运行

ls .bash*

您将看到这些文件:

l .bash_history :记录了您以前输入的命令,

l .bash_logout :当您退出 shell 时,要执行的命令,

l .bash_profile :当您登入 shell 时,要执行的命令,

l .bashrc :每次打开新的 shell 时,要执行的命令。

请注意后两个的区别:'.bash_profile'只在会话开始时被读取一次,而'.bashrc'则每次打开新的终端(如新的 xterm 窗口)时,都要被读取。按照传统,您得将定义的变量,如 PATH ,放到'.bash_profile'中,而象 aliases(别名)和函数之类,则放在'.bashrc'。但由于'.bash_profile'经常被设置成先读取'.bashrc'的内容,您如果图省事的话,就把所有配置都放进'.bashrc'。

这些文件是每一位用户的设置。系统级的设置存储在'/etc/profile'、'/etc/bashrc'及目录'/etc/profile.d'下的文件中。但您得习惯用各自的配置文件:编辑不需要'root'权限,还可以使您的设置更有个性。当系统级与用户级的设置发生冲突时,将采用用户的设置。

读取'.bashrc'的内容,您如果要省点事的话,就把您所有的配置都放进'.bashrc'。

上面的这些文件是每位用户的设置,系统级的设置存储在'/etc/profile'、'/etc/bashrc'及目录'/etc/profile.d'下的文件中。您最好习惯使用各自的配置文件:编辑不需要'root'权限,还可以使您的设置更具个性。当系统级与用户级的设置发生冲突时,将优先采用用户的设置。

提示符

每次当您打开一个控制台(console)或 xterm 时,最先看到的就是提示符(prompt),类似于:

account@hostname ~ $

在默认设置下,提示符将显示您的用户名、主机名(默认是'localhost')、当前所在目录(在 Unix 中,'~'表示您的 home 目录)。

按照传统,最后一个字符可以标识您是普通用户($),还是'root'(#)。

您可以通过 $PS1 变量来设置提示符。命令

echo $PS1

将显示当前的设定。其中可用字符的含义在 man bash 的'PROMPTING'部分有说明。

如何才能完成理想的设置呢?对于健忘的初学者来讲,默认设定有些不友好,因为提示符只显示当前目录的最后一部分。如果您看到象这样的提示符

tom@localhost bin $

您的当前目录可能是'/bin'、'/usr/bin'、'/usr/local/bin'及'/usr/X11R6/bin'。当然,您可以用

pwd (输出当前目录,print working directory)

能不能叫 shell 自动告诉您当前目录呢?

当然可以。这里我将提到的设定,包括提示符,大都包含在文件'/etc/bashrc'中。您可以通过编辑各自 home 目录下的'.bash_profile'和'.bashrc'来改变设置。

在 man bash 中的'PROMPTING'部分,对这些参数(parameter)有详细说明。您可以加入一些小玩意,如不同格式的当前时间,命令的历史记录号,甚至不同的颜色。

在'~/.bashrc'中,我喜欢的设定是:

PS1="\[\033[1m\][\w]\[\033[0m\] "

'root'在'~/.bashrc'中的设定 是:

PS1="\[\033[0;31m\][\w]\[\033[0m\] "

这样我得到的提示符就是:

[/usr/bin]

当用'root'时,变成:

[/usr/bin]

我已经除掉了主机名和用户名,因为我用不着这些。但我首先想一眼就能看出我的身份是普通用户还是'root'。注意到,普通用户的提示符可以是黑底白字,或白底黑字。

要在终端上获得恰当的颜色调配, 您可以编辑下面这个脚本color ,赋予执行权限(chmod +x color),然后再运行。

#!/bin/bash

#

# This file echoes a bunch of color codes to the

# terminal to demonstrate what's available. Each

# line is the color code of one forground color,

# out of 17 (default + 16 escapes), followed by a

# test use of that color on all nine background

# colors (default + 8 escapes).

#

T='gYw' # The test text

echo -e "\n 40m 41m 42m 43m\

44m 45m 46m 47m";

for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \

'1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \

' 36m' '1;36m' ' 37m' '1;37m';

do FG=${FGs// /}

echo -en " $FGs \033[$FG $T "

for BG in 40m 41m 42m 43m 44m 45m 46m 47m;

do echo -en "$EINS \033[$FG\033[$BG $T \033[0m";

done

echo;

done

echo

一种更适当的设定:

PS1="\u: \w\\$ "

这样,提示符就变成:

user_name: /usr/bin$

您可以通过命令 export 来测试不同的设置(比如,export PS1="\u: \w\\$ ")。如果找到了适合的提示符,就将设置放到您的'.bashrc''中。这样,每次打开控制台或终端窗口时,都会生效。

您甚至可以给提示符设定主题(theme),也就是搭配不同的颜色,使其看起来象很棒的 ol
的 C64 提示符。如果您对此感兴趣,可以看一下
Bashish(http://hem.passagen.se/arnognulf/index2.html)。

改变 $PATH

'$PATH'与'$PS1'一样,也是环境变量。输入

set

将列出所有当前定义的环境变量。

您看到的这些环境变量在 shell 的配置文件中定义,可能是用户自己的配置文件,也可能是由'root'通过'/etc'下面的系统级文件定义的。如果您使用 X ,更多的一些变量将由 X 、您的窗口管理器或桌面环境的启动文件配置。

如果对这些设置不很清楚,您暂时最好不要随便改动。了解如何改变 $PATH 变量很有用,因为这个变量决定了 shell 将到哪些目录中寻找命令或程序。如果要执行的命令的目录在 $PATH 中,您就不必输入这个命令的完整路径,直接输入命令就可以了。一些第三方软件没有将可执行文件放到 Linux 的标准目录中。因此,将这些非标准的安装目录添加到 $PATH 是一种解决的办法。此外,您也将看到如何处理一般的环境变量。

首先,作为惯例,所有环境变量名都是大写。由于 Linux 区分大小写,这点您要留意。当然,您可以自己定义一些变量,如'$path'、'$pAtH',但 shell 不会理睬这些变量。

第二点是变量名有时候以'$'开头,但有时又不是。当设置一个变量时,您直接用名称,而不需要加'$':

PATH=/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin

要获取变量值的话,就要在变量名前加'$':

echo $PATH

/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin

否则的话,变量名就会被当作普通文本了:

echo PATH

PATH

处理 $PATH 变量要注意的第三点是:您不能只替换变量,而是要将新的字符串添加到原来的值中。在大多数情况下,您不能用'PATH=/some/directory',因为这将删除 $PATH 中其他的所有目录,这样您在该终端运行程序时,就不得不给出完整路径。所以,只能作添加:

PATH=$PATH:/some/directory

这样,PATH 被设成当前的值(以 $PATH 来表示)+新添的目录。

到目前为止,您只为当前终端设置了新的 $PATH 变量。如果您打开一个新的终端,运行 echo $PATH ,将返回旧的 $PATH 值,而看不到您刚才添加的新目录。因为您先前定义的是一个局部环境变量(仅限于当前的终端)。

要定义一个全局变量,使在以后打开的终端中生效,您需要将局部变量输出(export),可以用'export'命令:

export PATH=$PATH:/some/directory

现在如果您打开一个新的终端,输入 echo $PATH ,也能看到新设置的 $PATH 了。请注意,命令'export'只能改变当前终端及以后运行的终端里的变量。对于已经运行的终端没有作用。

为了将目录永久添加到您的 $PATH ,只要将'export'的那行添加到您的'.bash_profile'文件中。

请不要在'.bashrc'中设置 PATH ,否则会导致 PATH 中目录的意外增长。您每次打开一个新的 shell ,'.bashrc'都会作用。所以如果在该文件中添加目录,您每次打开一个终端,目录又会被添加。这将导致 PATH 变量由于目录复制,不断地增长。

第六篇:命令的别名、Shell 函数/从这里出发/Shell 常见问题

命令的别名、Shell 函数

记住所有的命令及各自带的可选项,然后每次一一输入,这确实有点枯燥。但幸运的是,您可以为常用命令定义快捷方式。这些快捷方式可以用较简单的命令别名(alias),或复杂一些的 shell 函数的语法来定义。

命令的别名

例如,我用下面的命令来上传 MUO 中的文件:

rsync -e ssh -z -t -r -vv --progress /home/tom/web/muo/rsmuo/docs muo:/www/mandrakeuser/docs

显然,如果每次都要逐一输入,那我早晚会变成木头。因此我在'~/.bashrc'中定义了别名:

alias upmuo='rsync -e ssh -z -t -r -vv --progress /home/tom/web/muo/rsmuo/docs muo:/www/mandrakeuser/docs'

现在,我只要输入 upmuo 就可以完成上传任务了。

定义别名的语法是:

alias shortcut='command'

命令中有空格的话 ,就需要用引号(如在命令与可选项间就有空格)。请注意,您可以用单引号或双引号,但他们是有区别的。

单引号将剥夺其中的所有字符的特殊含义,而双引号中的'$'(参数替换)和'`'(命令替换)是例外。这意味着,如果您想在别名中应用变量或命令的替换,就得用双引号。看一下上面的例子,我在'.bashrc'中定义了一个称为 MUOHOME 的变量:

export MUOHOME=$HOME/web/muo/rsmuo/docs

要在上面的别名中用上这个变量,我就必须用双引号:

alias upmuo="rsync -e ssh -z -t -r -vv --progress $MUOHOME muo:/www/mandrakeuser/docs"

否则,别名将查找一个名为'$MUOHOME'的目录或文件。

您可以用'alias'在命令行快速地创建别名,或将命令放到各自的'~/.bashrc',或放到系统级的'/etc/profile.d/alias.sh'中(而在 Mandrake Linux 8 以前的版本里,用的是'/etc/bashrc')。要删除一个别名,只要输入:unalias alias 。运行 alias 将列出您系统中所有定义的别名。

如果看一下'~/.bashrc'和'/etc/profile.d/alias.sh',您会发现系统已经定义了一些别名。您可以为同一个命令定义多个别名。当然,您得先确认别名与其他程序名不同,比如象 alias rm='ls -l' 这样的就不能工作。您可以在命令行输入这些快捷方式,测试一下。如果 shell 找不到相同名称的命令,那您就可以将其用作别名了。

以下别名可能有用(不要忘了引号!) :

l alias rpmq='rpm -qa | grep' :现在 rpmq string 就将列出所有名称中含有 string 的已安装 RPM 包,

l alias ls='ls -ho --color | more' :ls 将以彩色分页方式列出文件,文件大小以 KB为单位,

l alias use='du --max-depth=1 | sort -n | more' :use 将子目录按大小排好,并以分页方式列出,

目录的别名也可以是可移动的介质:alias dlm='/mnt/cdrom/RedHat/RPMS/' 。

提示:将有相似功能的别名以相同字母开头,比如将所有目录的别名以'd'作开头,这样有助于记忆。

我相信,您将会用到这些功能。

Shell 函数

写 shell 函数涉及到了 shell 脚本,这超出了我们讨论的范围(也不在我的掌握范围之内 ;-))。事实上,shell 函数属于 shell 脚本,但可以在同一 shell 下被预加载(preload)和执行(而一般的 shell 脚本至少要打开一个 sub-shell)。

通过 shell 函数,您可以做很多 aliases 无法完成的事情。下面就是一个例子:

function apros() { apropos $1 | egrep -v '(3|\(n\)'; }

定义了一个新命令,称为'apros'。apros name 将先执行'apropos name'(即在 man page 中搜索命令),然后将得到的输出送到管道(|),接着用'egrep'过滤,排除第'3'和第'n'章节的 man page ,这个命令可能没什么大用处,但可以整理'apropos'命令的输出。

函数允许您在函数内部任何位置,使用运行时的参数。而别名,则只允许在命令行尾放一个参数(比如前面的别名'rpmq')。

'$1'就是位置参数(positional parameter),表示函数第一个参数的位置标识符。依此类推,还有'$2'等。

function apros() { apropos $1 | egrep -v "\($2"; }

如果您这样运行'apros'命令:

apros name man_section_number

这个命令将搜索标题中含 name 的 man pages ,但排除 man_section_number 部分:

apros menu 3

将搜索标题含'menu'的 man page ,但排除第三章节(关于编程的)。注意到您得引用(quote) 两次,而且还用到了双引号:

l 您必须引用'egrep'的搜索模式,这样可以不至于被 shell 误解。

l 您必须用双引号,这样第二个参数才能被正确解释。

l 您必须引用圆括号,这样使'egrep'按字面意思对待对待参数。

是不是有点意思?;-)

shell 函数的处理类似于别名:将其放到您的'.bashrc'文件,这样就能永久生效了。

从这里出发

我们谈到的只是 shell 的一个开头。掌握了shell 脚本,您就可以做很多事情,比如将任务自动化,纠正别人脚本中的错误,按照您的习惯定制 Linux 系统。如果您打算学习某种复杂的编程语言,那 shell 脚本也是一个很好的开端,因为基本概念都是类似的。

BASH Programming - Introduction HOW-TO:

http://www.ibiblio.org/mdw/HOWTO/Bas...tro-HOWTO.html

将更深入这些主题,并且将把您带到 shell 编程的世界。然后可以继续阅读我强烈推荐的 Advanced Bash-Scripting Guide(http://www.ibiblio.org/mdw/LDP/abs/h...??,作者是 Mendel Cooper 。

如果您偏好纸书,那我推荐 S. Veeraraghavan 的《Teach Yourself Shell Programming》,Sams 出版社。我倒觉得 O'Reilly 公司由 Newham/Rosenblatt 写的《Learning the bash Shell》,不过尔尔,但这可能只有我这么看 ;-) 。

除了这些,就是练习,练习,再练习。阅读其他人写的 shell 脚本,看看他们在做什么,怎么做,为什么那样做。

请不要用'root'测试您的脚本。Have fun 。

- 作者: 东方之子 2007年03月3日, 星期六 17:07  回复(0) |  引用(0) 加入博采

Linux初学者Patch使用指南

  简介

   本文的目的是向Linux新手介绍一种无价的资源,Larry Wall的patch程序。patch是用来查找文件之间差异的GNU diff命令的一个接口;diff有很多选项,但是该命令最常用的用途是用来生成一个文件,该文件中列出了内容发生改变的行,显示两个原始文件、修改过的行以及由于内容没有变化而忽略掉的行。patch典型地用于把一个目录下的源代码文件更新到新的版本,从而就避免了下载整个新的源代码档案的必要。下载一个有效的patch仅仅需要下载发生变化的那些代码行就可以了。

   patch最初源自十年前,那时网络带宽的限制促进了patch的发展,然而和当时的很多Unix工具一样,直到现在,patch还在广泛应用。在Dr. Dobb之旅的2月份的程序员杂志中,Larry Wall对早期的patch做了一些很有趣的说明:

   DDJ:顺便问一下,patch和diff哪个出现的早?

   LW:从很长一段时间来说,diff出现地比较早。我想diff大约比patch早10年出现,一回想起来,我就纳闷为什么没有人早些想到使用patch呢?

   但是我想我知道这中间的原因。这很大程度上是心理因素使然。当开发出diff时,程序员增加了一个e选项,我想就是这个选项的原因,该选项后来滋生为一个ed脚本,因此大家都会对自己说,"嗯,如果我想自动使用diff,那么我就使用这个选项。"因此从来都没有人编写一个计算机程序来获取其它格式的输出并使用这些结果。或者是那些设计diff的人员,或者是那些使用diff格式而受益的人员太沉迷其中了,因为你可以对那些已经修改过的内容使用diff操作并让这些内容正常工作都是很容易的。

   现在回想起来,这个问题是显而易见的。但是平心而论,与其说这是一个天才的灵感的闪现,还不如说这是自信心的体现。我开发出rn的第一个版本,然后继续为它编写补丁,这整个事情就是一团乱麻。你不可能强制用户使用补丁,因为他们可以手工完成这些工作。因此,他们就会省略一些自己认为不必要的工作,他们把新的修改加诸于原来的程序之上,因此而使得程序混乱。我编写补丁,这样就没有人找借口说这很难了。

   我不清楚是否事实就是如此,但是多年以来,我一直对别人讲patch对于计算机文化的影响比rn和Perl的影响都要大。现在Internet的速度比原来有大幅度的提高,把整个发行版本分散到世界各地也变得更加简单,似乎只有在开发者之间才需要传送补丁。我已经很多年没有传送Perl的patch工具包了。我认为虽然patch整体上的重要性在逐渐降低,但是仍然是开发者交流思想的一种方法。但是就那一段时间而言,patch真正在相当大的程度上都影响了软件的开发方式。

   Larry Wall针对patch对于计算机业界总体上重要性正在降低的评价可能是正确的,但是在自由软件世界中,patch仍然是一种必不可少的工具。无处不在的patch使得新手和非程序员能够简单地参与软件的alpha测试和beta测试,这对于整个计算机业界是十分有益的。

   在我留意到在Linux内核邮件列表中会周期性的出现这样一件事情时就产生了写这篇文章的念头。大约每三个月就会有人张贴要求把Linux内核源代码的发行版本独立出来的文章,据说这是因为有些人只对i386的代码和IDE的磁盘驱动感兴趣,他们并不想为每个内核发行版本都下载Alpha、Sparc等等的文件和众多的SCSI驱动程序。这篇文章后面紧跟的是一些耐心的回复文章(有些文章则并没有耐心),大部分文章都是在讨论原来的使用有关patch来更新内核源代码。接着Linus Torvalds就会再次声明自己没有兴趣投身于这种把内核源程序切割成小块的繁杂的劳动,但是如果有人愿意,他们可以自由地开展这项独立的工程。到现在为止都没有志愿者出现。我并不想谴责那些内核黑客不能耐心等待,却把生活变得复杂;我猜想直接使用内核工作可能比检查整个内核的发行版本方案要更加有趣、更富有挑战性。下载11M的内核源程序包可是件非常耗费时间的事情(对于那些按照时间上网的人来说,这是很昂贵的),但是内核patch才只有几十K大小,很少会超过1M。我的硬盘上的2.1.99开发内核源程序经过patch的升级,已经升级到了2.1.119版本,我怀疑如果我紧随内核的发展而不断升级,那么也许我就要完整地下载每一个发行版本了。


   使用patch

   patch附带有一个很好的帮助,其中罗列了很多选项,但是99%的时间只要两个选项就能满足我们的需要:

   patch -p1 < [patchfile]

   patch -R < [patchfile] (used to undo a patch)

   -p1选项代表patchfile中文件名左边目录的层数,顶层目录在不同的机器上有所不同。要使用这个选项,就要把你的patch放在要被打补丁的目录下,然后在这个目录中运行path -p1 < [patchfile]。来自Linux内核patch的一个简短的引用可以这样实现:

   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 @@

   int swap_header_version;

   int lock_map_size = PAGE_SIZE;

   int nr_good_pages = 0; - char tmp_lock_map = 0; + unsigned long tmp_lock_map = 0;

   应用来自本段中使用-p1开关拷贝的patch可以有效地减短patch定位的路径;patch会查找当前目录下一个名为/mm的子目录,接着应该会在这儿发现swapfile.c文件,然后等待打补丁。在这个过程中,以破折号(“-”号,译者注)开始的行会被一个以加号(“+”号,译者注)开始的行代替。一个典型的patch会包含对多个文件的更新,每个部分中都由对两个版本的文件运行diff -u命令的输出结果组成。

   patch在操作时把自己的输出结果显示在屏幕上,但是这种输出通常都滚屏太快,来不及观看。原来准备patch的文件名为*.orig,新的patch文件会覆盖这个初始文件名。

   打补丁的问题

   使用不同版本的patch问题来源可能不同,所有的版本在网络上都是可用的。Larry Wall近年来已经不再做很多工作来更新patch了,这可能是由于他最后发行的一个版本在大部分情况下都能正常运行。最近几年以来,一直是GNU项目的FSF程序员发行新版本的patch。他们首先修订有问题的patch,但是我最近一直使用没有问题的2.5版本(这是Debian2.0的发行版本号)。过去,我的2.1版本也一直运行的很好。当前的GNU patch的版本可以从GNU FTP站点上获取,然而大部分人都只使用他们Linux发行版中所提供的版本。

   让我们假定你已经对一个目录下的源程序文件进行了patch修补工作,但是patch并没有清晰地发挥作用。这可能会偶然发生,在打补丁的过程中会显示错误信息,其中带有行号,说明哪一个文件出现了问题。有时错误是很明显的,例如缺少了分号,这种错误可以不费多大力气就能改正。另外一种可能是从patch部分删除了产生问题的部分,但是这样根据所涉及到的文件的不同可能会正常工作,也可能不能正常工作了。

   另外一种常见的错位为:假设你有一个未使用tar打包的内核源程序文件,在/linux/arch/下浏览各个子目录时你会发现各种机器体系结构子目录,例如alpah、sparc等等。如果你和大多数Linux用户一样,使用的是Intel的处理器(或者是Intel系列),你可以决定删除这些目录,这些目录对于编译你特殊的内核并不需要,只是白白占用了磁盘空间。一段时间之后发行了一个新的内核patch,此时试图进行patch操作,当它发现不能找到自己打补丁需要的Alpha或者PPC文件,就会停顿下来。幸运的是patch在这些地方允许用户参与,它会询问"Skip this patch?"回答"y",patch就可以按照正确的路径继续执行。也许你需要回答这个问题很多次,因此允许自己不需要的目录保留在磁盘上是一种很好的方法。

   给内核打补丁的技巧

   很多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文件。

   如果你准备查看命令的输出,或者可能你希望保留*.orig文件直到你确定打过补丁的源程序编译已经通过,按照我的经验,直接运行patch(正如前面介绍的一样,patch位于内核源程序的最高目录)是很可靠的。为了避免对patch进行解压,在使用之前,可以使用这样一个技巧:

   gzip -cd patchXX.gz | patch -p1

   或者

   bzip2 -dc patchXX.bz2 | patch -p1

   在使用patch之后,可以使用find程序来检测被拒绝的文件:

   find . -name *.rej

   第一次使用这个命令,语法可能有些不清楚。点号(“.”)说明find应该查找当前目录并递规查找当前目录之下的所有子目录。记住,点号前后都应该有一个空格。通配符"*"号前面的反斜线把星号转义出来,以免shell会搞混,星号是有其它意义的。如果find找到了任何的*.rej文件,它就会把文件名打印到屏幕上。如果没有任何输出find就退出了,那么就差不多能确定patch正确发挥作用了。

   find的另外一个工作是删除*.orig文件:

   find . -name *.orig -print0 | xargs -0r rm -f

   这个命令敲起来相当麻烦,可以使用一个新的shell别名来代替这个命令。在你的~/.bashrc文件中类似这样的一行:

   alias findorig find . -name *.orig -print0 | xargs -0r rm -f

   可以允许你只输入findorig就可以调用前面的命令。如果别名命令的定义中包含空格,那么就必须使用单引号。为了不用先退出再重新登陆就可以使用一个新的别名,可以在命令行中敲如~/.bashrc。

   附加内容和结束语

   在撰写本文时,我刚好把自己的机器从2.1版本使用patch升级到了2.5版本。这两个版本都是来自现在的FSF/GNU维护人员。马上我就注意到2.5版本默认的输出已经改变了,屏幕上显示的信息变少了。原来在patch检测进行修补的行号时显示的Larry Wall的"...hmm"不见了。2.5版本的输出只剩下诸如"patching file [filename]"之类的信息了,而没有早期版本显示的那么多信息了。无可否认,信息滚屏太快,根本无法阅读,但是输出可以重定向到一个文件中供以后使用。这种变化不会影响程序的功能,但是减少了人为的成分。在我看来,使用诸如原来的"...hmm"信息和源代码中的注释一样,对于提醒用户程序是显示执行的工作的结果是很有价值的,这就像人在呼吸一样,而不应该使用一些毫无结果的位集合。通过对patch命令行增加--verbose开关可以恢复原来的显示内容,但是我相信很多用户既不会注意到这个选项,也不会不辞辛劳地输入这个选项。2.1和2.5版本的另外一个不同是除非patch给出了-b选项,否则不能创建*.orig备份文件。

   对于那些对软件和内核"前沿"bug报告测试和提供测试报告不感兴趣的人来说,patch并不是必须的,但是通常大部分Linux世界里有趣的开发都是属于这个范畴的。获得patch的使用方式并不困难,这种努力可以得到充分的回报。 

- 作者: 东方之子 2007年02月28日, 星期三 21:56  回复(0) |  引用(0) 加入博采

FILE STORAGE HARDWARE AND DISK ORGANIZATION

Hard Disk Drive Basics

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.

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.

 

Making Tracks

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.

The figure below shows a hard disk with two platters.

Figure 3-1 Parts of a Hard Drive

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.

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.

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.

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.

Up

Sectors and Clusters

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.

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.

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.

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.

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.

Figure 3-2 Sectors and Clusters

 

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 fragmented. 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.

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.

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.

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.

Master Boot Record (MBR) 

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.

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.

Note: 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.

The example below shows a hex dump of the sector containing the Master Boot Record. The figure shows the sector in two parts:

  • 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.
  • The second part is the Partition Table.
  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 ...<.t..<.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..<.t.....<.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...>....  
  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.

Hard Drive Partition. Partition Table.

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:

  • Partition 1 0x01BE (446)
  • Partition 2 0x01CE (462)
  • Partition 3 0x01DE (478)
  • Partition 4 0x01EE (494)

The last two bytes in the sector are a signature word for the sector and are always 0x55AA. The next example 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.

                                                     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...>....
 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. 

The following table describes each entry in the Partition Table. The sample values correspond to the information for partition 1.

Partition Table Fields

Byte Offset

Field Length

Sample Value

Meaning

00

BYTE

0x80

Boot Indicator. Indicates whether the partition is the system partition. Legal values are:
00 = Do not use for booting.
80 = System partition.

01

BYTE

0x01

Starting Head.

02

6 bits

0x01

Starting Sector. Only bits 0-5 are used. Bits 6-7 are the upper two bits for the Starting Cylinder field.

03

10 bits

0x00

Starting Cylinder. 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.

04

BYTE

0x06

System ID. This byte defines the volume type. In Windows 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.

05

BYTE

0x0F

Ending Head.

06

6 bits

0x3F

Ending Sector. Only bits 0-5 are used. Bits 6-7 are the upper two bits for the Ending Cylinder field.

07

10 bits

0x196

Ending Cylinder. 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.

08

DWORD

3F 00 00 00

Relative Sector.

12

DWORD

51 42 06 00

Total Sectors.

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.

Boot Indicator Field

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.

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 95, UNIX, OS/2, or Windows 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.

System ID Field

For primary partitions and logical drives, the System ID field describes the file system used to format the volume. Windows 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.

These are the values for the System ID field:

Table 3-1 System ID Field Values

Value

Meaning

0x01

12-bit FAT primary partition or logical drive. The number of sectors in the volume is fewer than 32680.

0x04

16-bit FAT primary partition or logical drive. The number of sectors is between 32680 and 65535.

0x05

Extended partition. See section titled "Logical Drives and Extended Partitions," presented later in this chapter, for more information.

0x06

BIGDOS FAT primary partition or logical drive.

0x07

NTFS primary partition or logical drive.


Figure presented earlier in this section, has examples of a BIGDOS FAT partition, an NTFS partition, an extended partition, and a 12-bit FAT partition.

If you install Windows 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 NT, your only option is to delete the partitions.

OEM versions of Windows 95 support the following four partition types for FAT file systems that Windows NT cannot recognize.

Table 3-2 Partition Types

Value

Meaning

0x0B

Primary Fat32 partition, using interrupt 13 (INT 13) extensions.

0x0C

Extended Fat32 partition, using INT 13 extensions.

0x0E

Extended Fat16 partition, using INT 13 extensions.

0x0F

Primary Fat16 partition, using INT 13 extensions.


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 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 NT.

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.

Note

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.

On Windows 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.

- 作者: 东方之子 2007年02月26日, 星期一 15:22  回复(0) |  引用(0) 加入博采

深入浅出硬盘分区表
流星 发表于 2005-8-15 14:59:06

    人们在使用电脑时,有时由于异常操作,有时由于病毒侵袭,会导致某个分区消失或硬盘无法启动。究其原因,就是硬盘分区表受损。硬盘分区表可以说是支持硬盘正常工作的骨架.操作系统正是通过它把硬盘划分为若干个分区,然后再在每个分区里面创建文件系统,写入数据文件.本文主要讲述的是分区表的位置,结构以及各个分区表是如何链接起来的.当掌握了这些知识后,即使分区表受到破坏,一样也可以根据残存的数据手工修复分区表,从而修复分区。

一.分区表的位置及识别标志
    分区表一般位于硬盘某柱面的0磁头 1扇区.而第1个分区表(也即主分区表)总是位于(0柱面,1磁头,1扇区),剩余的分区表位置可以由主分区表依次推导出来.分区表有64个字节,占据其所在扇区的[441-509]字节.要判定是不是分区表,就看其后紧邻的两个字节(也即[510-511])是不是 "55AA",若是,则为分区表.

二.分区表的结构
分区表由4项组成,每项16个字节.共4×16 = 64个字节.每项描述一个分区的基本信息.每个字节的含义如下:
分区表项含义
字节含义
0Activeflag.活动标志.若为0x80H,则表示该分区为活动分区.若为0x00H,则表示该分区为非活动分区.
1,2,3该分区的起始磁头号,扇区号,柱面号磁头号 -- 1字节, 扇区号 -- 2字节低6位,柱面号 -- 2字节高2位 + 3字节
4分区文件系统标志:
分区未用: 0x00H.
扩展分区: 0x05H, 0x0FH.
FAT16分区: 0x06H.
FAT32分区: 0x0BH, 0x1BH, 0x0CH, 0x1CH.
NTFS分区: 0x07H.
5,6,7该分区的结束磁头号,扇区号,柱面号,含义同上.
8,9,10,11逻辑起始扇区号。表示分区起点之前已用了的扇区数.
12,13,14,15该分区所占用的扇区数.

分区表项有几个字节比较重要,下面分别阐述之:
1、(1,2,3)字节
    磁头号由(1)字节8位表示,其范围为(0 -- 28 - 1),也即(0 磁头-- 254磁头)。   
扇区号由(2)字节低6位表示,其范围为(0 -- 26 - 1),由于扇区号从1开始,所以其范围是
(1扇区-63扇区)。柱面号由(2)字节高2位 + (3)字节,共10位表示,其范围为
(0 --2 10 - 1),也即(0 柱面-- 1023柱面)。当柱面号超过1023时,这10位依然表示成1023,
需要注意。(5,6,7)字节含义同上。
2、(8, 9, 10, 11)字节  
    如果是主分区表,则这4 个字节表示该分区起始逻辑扇区号与逻辑0扇区(0柱面,0磁头,1扇区)
之差。如果非主分区表,则这4 个字节要么表示该分区起始逻辑扇区号与扩展分区起始逻辑扇区号之差,
要么为63。详细情况在后面有所阐述。  
注意: 
1、扇区上的字节是按左边低位,右边高位的顺序排列的。所以在取值时,需要把字节再反一下,
让高位字节在左边,低位字节在右边,这一点在读取逻辑起始扇区号和分区大小时需要注意。举个例子:
第一项的逻辑起始扇区为(3F 00 00 00),转换为十进制前要先反一下字节顺序,为(00 00 00 3F)
然后在转换为十进制,即63 .同理分区大小为(3F 04 7D 00),先反为(00 7D 04 3F)再转换为
十进制,即8193087。
2、逻辑扇区号与(柱面,磁头,扇区)的相互转换:
令L = 逻辑扇区号,C = 柱面号,H = 磁头号,S = 扇区号。
每道扇区数 =  63
每柱面磁头数 = 255
每柱面扇区数 = 每道扇区数* 每柱面磁头数= 63 × 255= 16065
柱面号下标从0开始。磁头号[0 -- 254],扇区号[1 -- 63]。
逻辑扇区号下标也从0开始。
(柱面,磁头,扇区)转换成逻辑扇区号的公式为:
L = C×16065 + H ×63 + S - 1 ;
比如(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扇区)
3、分区表上有四项,每一项表示一个分区,所以一个分区表最多只能表示4个分区。主分
区表上的4项用来表示主分区和扩展分区的信息。因为扩展分区最多只能有一个,所以硬盘 
最多可以有四个主分区或者三个主分区,一个扩展分区。余下的分区表是表示逻辑分区的。 
这里有必要阐述一点:逻辑区都是位于扩展分区里面的,并且逻辑分区的个数没有限制。
 
4、分区表所在扇区通常在(0磁头,1扇区),而该分区的开始扇区通常位于(1磁头,1扇区),中间
隔了63 个隐藏扇区。
  
三.分区表链的查找
  分区表链实际上相当于一个单向链表结构。第一个分区表,也即主分区表,可以有一项描述扩展分区。而这一项就相当于指针,指向扩展分区。然后我们根据该指针来到扩展分区起始柱面的0头1扇区,找到第二个分区表。对于该分区表,通常情况下:第一项描述了扩展分区中第一个分区的信息,第二项描述下一个分区,而这第二项就相当于指向第二个分区的指针,第三项,第四项一般均为0。我们可以根据该指针来到扩展分区中第二个分区起始柱面的0头1扇区,找到第三个分区表。以此类推,只到最后一个分区表。而最后一个分 区表只有第一项有信息,余下三项均为0.相当于其指针为空.所以只要找到了一个分区表就可 以推导找出其后面所有分区表。不过该分区表前面的分区表就不好推导出来了。但令人高兴的是这个链表的头节点,也即主分区表的位置是固定的位于(0柱面, 0磁头, 1扇区)处,我们可以很轻易的找到它,然后把剩下的所有分区表一一找到。
以笔者的硬盘为例:一个主分区(C盘), 一个扩展分区.扩展分区中有两个逻辑分区(D盘,E盘)其分区表链示意图如下:

图一 分区表链示意图

(一).读取(0柱面,0磁头,1扇区)处C盘的主分区表:
[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 ]
第一项:
(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盘前面已
有63个扇区,这63个扇区为系统隐藏扇区。
6. (3F 04 7D 00):
反向,(00 7D 04 3F) 16  =  (8193087) 10。表明C盘有8193087个扇区。即(0柱面,1磁头,1扇区)
(509柱面,254磁头,63扇区)共有8193087个扇区。
第二项:
(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,即
(510 柱面,0磁头,1扇区)。这是真实准确的,我一般都用这一项来定位分区起点。
6. (1F 2C B4 00):
反向, (00 B4 2C 1F) 16  =  (11807775) 10. 表示扩展分区共有11807775个扇区。通过上面得到
的起点和分区的大小,可以推导出扩展分区的结束位置:8193150 + 11807775 = 20000925号扇区,
(1244 柱面,254磁头,63扇区)。

二.查找D盘分区表  根据上面的信息,第二个分区表,也即D盘分区表在(510柱面,0磁头,1扇区)

处。读取该扇区,得到分区表如下:

[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 ]
第一项:
(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扇区)与扩展分区
起始逻辑扇区号(510柱面,0磁头,1扇区)之差。表示D盘前面已有63个扇区,这63个扇区为系统
隐藏扇区。
6. (BF A3 5D 00):
反向,(00 5D A3 BF) 16  =  (6136767) 10。表明D盘有6136767个扇区。
通过上面得到的起点和分区的大小,可以推导出D盘的结束位置:8193150 + 63 + 6136767 =
14329980号扇区。即(891柱面,254磁头,63扇区)。与上面的正好吻合。
第二项:
(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盘分区表所在扇区。
其值为E盘分区表所在扇区号与扩展分区起始扇区号之差。所以,E盘分区表所在扇区号为:
8193150 + 6136830 = 14329980。即(892柱面,0磁头,1扇区)。

6.(21 88 56 00):
反向,(00 56 88 21) 16  =  (5670945) 10.表示E盘共有11807775个扇区。通过上面得到的起点
和分区的大小,可以推导出E盘的结束位置:14329980 + 5670945 = 20000925号扇区,即
(1244 柱面,254磁头,63扇区)。

三.查找E盘分区表 根据上面的信息,第三个分区表,也即E盘分区表在(892柱面,0磁头,1扇区)

处。读取该扇区,得到分区表如下:

[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,说明没有下一个分区表了。该分区表就是分区表链的最后一个节点。
第一项:
(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个扇区, 
这63个扇区为系统隐藏扇区。
操作系统无法对这些扇区进行读写,所以可以把自己的秘密信息写在这里.
6. (E2 87 56 00): 
反向,(00 56 87 E2) 16  =  (5670882) 10。表明E盘有5670882个扇区。而D盘分区表相应项为
5670945.5670945 - 5670882 = 63.正好等于63个隐藏扇区.这是因为D盘分区表描述的是
(892柱面,0磁头,1扇区) 到 (1244 柱面,254磁头,63扇区) 之间的扇区数。而E盘分区表
描述的是(892柱面, 1磁头,1扇区) 到(1244 柱面,254磁头,63扇区) 之间的扇区数。
 

- 作者: 东方之子 2007年02月26日, 星期一 14:53  回复(0) |  引用(0) 加入博采

php中Cookie及其使用

Cookie技术是一个非常有争议的技术,自经诞生它就成了广大网络用户和Web开发人员的
一个争论焦点。有一些网络用户,甚至包括一些资深的Web专家也对它的产生和推广感到不满,这倒不是因为
Cookie技术的功能太弱或别的技术性能上的原因,而仅仅是因为他们觉得Cookie 的使用,对网络用户的隐私
构成了危害。因为Cookie是由Web服务器保存在用户浏览器上的小文本文件,它包含有关用户的信息(如身份
识别号码、密码、用户在Web站点上购物的方式或用户访问该站点的次数)。 

  那么Cookie 技术究竟怎样呢?是否真的给网络用户带来了个人隐私的危害呢?还是让我们看了下面的内
容,再做回答吧。 

  (1)Cookie技术简介 

   在WEB技术发展史上,Cookie技术的出现是一个重大的变革。最先是Netscape在它的Netscape Navigator
浏览器中引入了Cookie技术,从那时起,World Wide Web 协会就开始支持Cookie标准。以后又经过微软的大
力推广(因为微软的IIS Web服务器所采用的ASP技术很大程度的使用了Cookie技术),即在微软的Internet
Explorer浏览器中完全支持Cookie技术。到现在,绝大多数的浏览器都支持Cookie技术,或者至少兼容Cookie
技术的使用。 

  1)什么是Cookie? 

  按照Netscape官方文档中的定义,Cookie是在HTTP协议下,服务器或脚本可以维护客户工作站上信息的
一种方式。Cookie 是由Web服务器保存在用户浏览器上的小文本文件,它可以包含有关用户的信息(如身份
识别号码、密码、用户在Web站点购物的方式或用户访问该站点的次数)。无论何时用户链接到服务器,Web
站点都可以访问Cookie信息。 

  通俗地讲,浏览器用一个或多个限定的文件来支持Cookie。这些文件在使用Windows操作系统的机器上叫
做Cookie 文件,在Macintosh机器上叫做magic Cookie 文件,这些文件被网站用来在上面存储Cookie数据。
网站可以在这些Cookie 文件中插入信息,这样对有些网络用户就有些副作用。有些用户认为这造成了对个人
隐私的侵犯,更糟的是,有些人认为Cookie是对个人空间的侵占,而且会对用户的计算机带来安全性的危害。 

  目前有些Cookie 是临时的,另一些则是持续的。临时的Cookie只在浏览器上保存一段规定的时间,一旦
超过规定的时间该Cookie就会被系统清除。例如在PHP中Cookie被用来跟踪用户进程直到用户离开网站。持续
的Cookie则保存在用户的Cookie文件中,下一次用户返回时,仍然可以对它进行调用。 

  在Cookie文件中保存Cookie,一些用户会过分地认为这将带来很大的问题。主要是有些用户担心Cookie
会跟踪用户网上冲浪的习惯,譬如用户喜爱到那些类型的站点、爱从事些什么活动等。害怕这种个人信息一
旦落入一些别有用心的家伙手中,那么个人也就可能成为一大堆广告垃圾的对象,甚至遭到意外的损害。不
过,这种担心压根儿不会发生,因为网站以外的用户是无法跨过网站来获得Cookie信息的。所以想以这种目
的来应用Cookie是不可能的。不过,由于一些用户错误的理解以及“以讹传讹”,一些浏览器开发商别无选
择,只好作出相识的响应(例如Netscape Navigator4.0和Internet Explorer3.0都提供了屏蔽Cookie 的选
项)。 

  对Cookie技术期待了这么久的结果是,迫使许多浏览器开发商在它们的浏览器中提供了对Cookie的灵活
性控制功能。例如,目前的两大主流浏览器Netscape Navigator 和 Internet Explorer是这样处理Cookie
的:Netscape Navigator4.0不但可以接受Cookie进行警告,而且还可以屏蔽掉Cookie;InternetExplorer3.0
也可以屏蔽Cookie,但在Internet Explorer4.0中就只能进行接受警告而没有提供屏蔽选项,不过在Internet
Explorer4.0之后的更新版本中又加入了屏蔽Cookie的功能选项。 

  此外,很多最新的技术甚至已经可以在不能屏蔽Cookie的浏览器上进行Cookie的屏蔽了。例如,可以通
过将Cookie文件设置成不同的类型来限制Cookie的使用。但是,非常不幸地是,要是你想完全屏蔽Cookie的
话,肯定会因此拒绝许多的站点页面。因为当今已经有许多Web站点开发人员爱上了Cookie技术的强大功能,
例如Session对象的使用就离不开Cookie的支持。 

  尽管今天仍有一些网络用户对于Cookie的争论乐此不倦,但是对于绝大多数的网络用户来说还是倾向于
接受Cookie的。因此,我们尽可以放心地使用Cookie技术来开发我们的WEB页面。 

  2)Cookie是怎样工作的? 

  要了解Cookie,必不可少地要知道它的工作原理。一般来说,Cookie通过HTTP Headers从服务器端返回
到浏览器上。首先,服务器端在响应中利用Set-Cookie header来创建一个Cookie ,然后,浏览器在它的请
求中通过Cookie header包含这个已经创建的Cookie,并且反它返回至服务器,从而完成浏览器的论证。 

  例如,我们创建了一个名字为login的Cookie来包含访问者的信息,创建Cookie时,服务器端的Header 
如下面所示,这里假设访问者的注册名是“Michael Jordan”,同时还对所创建的Cookie的属性如path、
domain、expires等进行了指定。 

  Set-Cookie:login=Michael Jordan;path=/;domain=msn.com; 
  expires=Monday,01-Mar-99 00:00:01 GMT 

  上面这个Header会自动在浏览器端计算机的Cookie文件中添加一条记录。浏览器将变量名为“login”
的Cookie赋值为“Michael Jordon”。注意,在实际传递过程中这个Cookie的值是经过了URLEncode方法的
URL编码操作的。 这个含有Cookie值的HTTP Header被保存到浏览器的Cookie文件后,Header就通知浏览器
将Cookie通过请求以忽略路径的方式返回到服务器,完成浏览器的认证操作。 

  此外,我们使用了Cookie的一些属性来限定该Cookie的使用。例如Domain属性能够在浏览器端对Cookie
发送进行限定,具体到上面的例子,该Cookie只能传达室到指定的服务器上,而决不会跑到其他的如
www.hp.com的Web站点上去。Expires属性则指定了该Cookie保存的时间期限,例如上面的Cookie在浏览器上
只保存到1999年3月1日1秒。当然,如果浏览器上Cookie 太多,超过了系统所允许的范围,浏览器将自动对
它进行删除。至于属性Path,用来指定Cookie将被发送到服务器的哪一个目录路径下。 

  说明:浏览器创建了一个Cookie后,对于每一个针对该网站的请求,都会在Header中带着这个Cookie;
不过,对于其他网站的请求Cookie是绝对不会跟着发送的。而且浏览器会这样一直发送,直到Cookie过期为止。 

  上一部分讲了有关Cookie的技术背景,这部分来说说在PHP里如何设置、使用、删除Cookie,及Cookie
的一些限制。PHP对Cookie支持是透明的,用起来非常方便。 

  1、设置Cookie

  PHP用SetCookie函数来设置Cookie。必须注意的一点是:Cookie是HTTP协议头的一部分,用于浏览器和
服务器之间传递信息,所以必须在任何属于HTML文件本身的内容输出之前调用Cookie函数。SetCookie 函数
定义了一个Cookie,并且把它附加在HTTP头的后面,SetCookie函数的原型如下:

int SetCookie(string name, string value, int expire, string path, 
string domain, int secure); 

  除了name之外所有的参数都是可选的。value,path,domain 三个参数可以用空字符串代换,表示没有设
置;expire和 secure两个参数是数值型的,可以用0表示。expire参数是一个标准的Unix时间标记,可以用
time()或mktime() 函数取得,以秒为单位。secure参数表示这个Cookie是否通过加密的HTTPS协议在网络上
传输。 

  当前设置的Cookie 不是立即生效的,而是要等到下一个页面时才能看到.这是由于在设置的这个页面里
Cookie由服务器传递给客户浏览器,在下一个页面浏览器才能把Cookie从客户的机器里取出传回服务器的原
因。在同一个页面设置Cookie,实际是从后往前,所以如果要在插入一个新的Cookie之前删掉一个,你必须
先写插入的语句,再写删除的语句,否则可能会出现不希望的结果。 

  来看几个例子:

  简单的:

SetCookie("MyCookie", "Value of MyCookie"); 

  带失效时间的: 

SetCookie("WithExpire", "Expire in 1 hour", time()+3600);//3600秒=1小时 

  什么都有的: 

SetCookie("FullCookie", "Full cookie value", time()+3600, "/forum", ".phpuser.com", 1); 

  这里还有一点要说明的,比如你的站点有几个不同的目录,那么如果只用不带路径的Cookie的话,在一
个目录下的页面里设的Cookie在另一个目录的页面里是看不到的,也就是说,Cookie是面向路径的。实际上,
即使没有指定路径,WEB 服务器会自动传递当前的路径给浏览器的,指定路径会强制服务器使用设置的路径。
解决这个问题的办法是在调用SetCookie时加上路径和域名,域名的格式可以是“www.phpuser.com”,也可
是“.phpuser.com”。 

  SetCookie函数里表示value的部分,在传递时会自动被encode,也就是说,如果value的值是“test 
value”在传递时就变成了“test%20value”,跟URL的方法一样。当然,对于程序来说这是透明的,因为在
PHP接收Cookie的值时会自动将其decode。 

  如果要设置同名的多个Cookie,要用数组,方法是: 

SetCookie("CookieArray[]", "Value 1"); 
SetCookie("CookieArray[]", "Value 2"); 

  或 

SetCookie("CookieArray[0]", "Value 1"); 
SetCookie("CookieArray[1]", "Value 2"); 

  2、接收和处理Cookie 

  PHP对Cookie的接收和处理的支持非常好,是完全自动的,跟FORM变量的原则一样,特别简单。比如设
置一个名为MyCookier的Cookie,PHP会自动从WEB服务器接收的HTTP头里把它分析出来,并形成一个与普通
变量一样的变量,名为$myCookie,这个变量的值就是Cookie的值。数组同样适用。另外一个办法是引用PHP
的全局变量$HTTP_COOKIE_VARS数组。 

  分别举例如下:(假设这些都在以前的页面里设置过了,并且仍然有效) 

echo $MyCookie; 
echo $CookieArray[0]; 
echo count($CookieArray); 
echo $HTTP_COOKIE_VARS["MyCookie"]; 

  就这么简单。 

  3、删除Cookie 

  要删除一个已经存在的Cookie,有两个办法: 

  一是调用只带有name参数的SetCookie,那么名为这个name的Cookie 将被从关系户机上删掉;另一个办
法是设置Cookie的失效时间为time()或time()-1,那么这个Cookie在这个页面的浏览完之后就被删除了(其
实是失效了)。 

  要注意的是,当一个Cookie被删除时,它的值在当前页在仍然有效的。 

  4、使用Cookie的限制 

  首先是必须在HTML文件的内容输出之前设置; 
  其次不同的浏览器对Cookie的处理不一致,且有时会出现错误的结果。比如:MS IE+SERVICE PACK 1
不能正确处理带域名和路径的Cookie ,Netscape Communicator 4.05和MS IE 3.0不能正确处理不带路径和
时间的Cookie。至于MS IE 5 好象不能处理带域名、路径和时间的Cookie。这是我在设计本站的页面时发现
的。 
  第三个限制是在客户端的。一个浏览器能创建的Cookie数量最多为30个,并且每个不能超过4KB,每个WEB
站点能设置的Cookie总数不能超过20个。 

  关于Cookie的话题,就说到这儿了。 

  (由于Cookie最初由Netscape定义的,所以附上Netscape公司关于Cookie的官方原始定义的网址:
_spec.html" target=_blank>
http://www.netscape.com/newsref
/std/cookie_spec.html

Cookie技术是一个非常有争议的技术,自经诞生它就成了广大网络用户和Web开发人员的
一个争论焦点。有一些网络用户,甚至包括一些资深的Web专家也对它的产生和推广感到不满,这倒不是因为
Cookie技术的功能太弱或别的技术性能上的原因,而仅仅是因为他们觉得Cookie 的使用,对网络用户的隐私
构成了危害。因为Cookie是由Web服务器保存在用户浏览器上的小文本文件,它包含有关用户的信息(如身份
识别号码、密码、用户在Web站点上购物的方式或用户访问该站点的次数)。

- 作者: 东方之子 2007年02月5日, 星期一 12:54  回复(0) |  引用(0) 加入博采

css定位(position)属性
要点如下:
1、绝对定位的参照位置是上层最近的position不是static的元素,其实就是说具有position:relative/absolute/fixed属性的上层元素。如果没有,就以body为定位标准。
2、如果想把某个上层作成下层绝对定位的参照位置,可以把上层的position设定为relative偏移为0就可以了
3、position:fixed 为固定定位,参照位置不是父层而是浏览器视窗。所以可以用fixed属性来设定类似传统框架布局,或者飘固定广告或者固定导航都可以。
4、相对定位属性中的正值可以理解为从上层元素边缘向中间移动,而负值可以理解为从边缘向外部移动。
5、相对定位的元素只是从正常的位置上移开,但是它占有的页面位置并不消失而变成空白。
5、visibility可以设置成hidden,这时候元素看不见但是仍旧占有页面位置。display:none;则根本就完全消失。

- 作者: 东方之子 2007年01月29日, 星期一 23:23  回复(0) |  引用(0) 加入博采

css对各浏览器的兼容问题
区分三款浏览器简单方法:
#example { color: #333; } /* Moz FF */
* html #example { color: #f0f; } /* IE6 */
*+html #example { color: #0ff; } /* IE7 */

马上试了一下,效果很好,不过有句要补充一下!
在兼容IE7的*+html的hack一定要在顶部加入DTD声明,否则无效
将下面这句声明加入下面可运行的html的顶部,就可以看到效果拉~当然要保证你的浏览器是IE7
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

1.为什么在不同的浏览器显示效果不一样?
因为不同浏览器对于css样式表的解析不一样,所以导致样式乃至层布局发生变化。例如,ff中设置padding属性时,div会相应增加height和width,而ie的解析是不会的,再例如ff对盒模型的解析和ie相差两个象素。

2.设计时要做到所有浏览器都兼容吗?
我的答案是即使能做到也没有必要去做,科技是在进步的,用户总是在推陈出新的使用这新版本的浏览器,根据“设计诉说”的站点统计小样本结果显示,6225个访问者中有72.1%使用IE6.0;12.7%使用IE7.0;7.9%在使用FF2.0,剩余的不同版本的浏览器占的百分比都不到1% 所以我认为只要做到IE6 FF2.0 以及新出的IE7.0兼容即可,顶多向下兼容一下IE5.5,完全没有必要为了那些个小数点费劲脑子。如果有必要可以另外设计css文件,然后通过js判断浏览器版本进行选择相应的文件。

3.css样式的优先级是怎么样的?
这个是个好问题,当你弄明白这个,我想应该可以很自如的运用一些兼容样式表的技巧了。在正常的IE中,如果你在css中重复定义一个属性时,浏览器解析的是后面的属性,举个例子
box {
height:100px;
height:200px;
height:400px;
height:300px;
}
重复定义盒模型的高度属性,越后面优先级越高,所以浏览器解析出的结果就是高度为300px。

4.如何做到让IE6.0与FF兼容?
最常用的一种方法了,也是屡试不爽的——“!important”,这个字段是用来提高优先级的,而IE6.0对于找个字段是无法识别的,于是FF与IE6.0就可以分开解析了。例如,在IE下显示red,FF下显示blue,只需要这么写 
color {
background-color:blue !important;
background-color:red;
}
“!important”FF可以识别,blue那行提高优先级,因此在FF中blue优先级高于red,显示为蓝色

IE6.0将上面的样式识别成
color {
background-color:blue;
background-color:red;
}
red优先级高,所以显示为红色。

切记,上下两句的位置一定不能颠倒。问为什么的再好好看看上两个问题,再不明白就面壁去....

5.如何做到让更低版本IE兼容?
其实我认为做到IE6.0与FF2.0已经足够,5.5的兼容用“ /**/” 5.0的兼容用“>”,具体我就不说了,说实在我也不大懂,大家可以去google一下

6.如何做到IE7.0兼容?
这个问题我也要问大家,大家有答案的告诉我,因为新版的IE7.0对于“!important”具有识别能力,可是对于盒以及padding等的解析却和IE6.0差不多,于是乎,完全兼容了IE6.0和FF2.0的就似乎兼容不了IE7.0,捣腾了好久,还是不知道怎么办。请大家帮帮忙!

7.css对浏览器兼容应做到完全一致吗?
个人认为在满足可读性的原则和不影响整体布局的前提下,界面有些许的位置不同是可以允许的,要在不同浏览器下做到一模一样,那真是太费劲了。

- 作者: 东方之子 2007年01月28日, 星期日 23:42  回复(0) |  引用(0) 加入博采

CSS浏览器兼容问题
E6.0,ie7.0与Firefox的CSS兼容性问题
      1.DOCTYPE 影响 CSS 处理
  2.FF: div 设置 margin-left, margin-right 为 auto 时已经居中, IE 不行
  3.FF: body 设置 text-align 时, div 需要设置 margin: auto(主要是 margin-left,margin-right) 方可居中
  4.FF: 设置 padding 后, div 会增加 height 和 width, 但 IE 不会, 故需要用 !important 多设一个 height 和 width
  5.FF: 支持 !important, IE 则忽略, 可用 !important 为 FF 特别设置样式,值得注意的是,一定要将xxxx !important 这句放置在另一句之上
  6.div 的垂直居中问题: vertical-align:middle; 将行距增加到和整个DIV一样高 line-height:200px; 然后插入文字,就垂直居中了。缺点是要控制内容不要换行
  7.cursor: pointer 可以同时在 IE FF 中显示游标手指状, hand 仅 IE 可以
   8.FF:  链接加边框和背景色,需设置 display: block, 同时设置 float: left 保证不换行。参照 menubar, 给 a 和  menubar 设置高度是为了避免底边显示错位, 若不设 height, 可以在 menubar 中插入一个空格。
  9.在mozilla firefox和IE中的BOX模型解释不一致导致相差2px解决方法:div{margin:30px!important;margin:28px;}
  注意这两个margin的顺序一定不能写反,据阿捷的说法!important这个属性IE不能识别,但别的浏览器可以识别。所以在IE下其实解释成这样:div{maring:30px;margin:28px}
  重复定义的话按照最后一个来执行,所以不可以只写margin:XXpx!important;
  10.IE5 和IE6的BOX解释不一致
  IE5下div{width:300px;margin:0 10px 0 10px;}
   div的宽度会被解释为300px-10px(右填充)-10px(左填充)最终div的宽度为280px,而在IE6和其他浏览器上宽度则是以 300px+10px(右填充)+10px(左填充)=320px来计算的。这时我们可以做如下修改div{width:300px! important;width /**/:340px;margin:0 10px 0 10px}
  关于这个/**/是什么我也不太明白,只知道IE5和firefox都支持但IE6不支持,如果有人理解的话,请告诉我一声,谢了!:)
  11.ul标签在Mozilla中默认是有padding值的,而在IE中只有margin有值所以先定义ul{margin:0;padding:0;}就能解决大部分问题

  
    注意事项:

  1、float的div一定要闭合。

  例如:(其中floatA、floatB的属性已经设置为float:left;)<#div id=\"floatA\" >
<#div id=\"floatB\" >
<#div id=\"NOTfloatC\" >
  这里的NOTfloatC并不希望继续平移,而是希望往下排。
  这段代码在IE中毫无问题,问题出在FF。原因是NOTfloatC并非float标签,必须将float标签闭合。
  在<#div class=\"floatB\">
<#div class=\"NOTfloatC\">
  之间加上<#div class=\"clear\">
  这个div一定要注意声明位置,一定要放在最恰当的地方,而且必须与两个具有float属性的div同级,之间不能存在嵌套关系,否则会产生异常。
  并且将clear这种样式定义为为如下即可:.clear{
clear:both;}
  此外,为了让高度能自动适应,要在wrapper里面加上overflow:hidden;
  当包含float的box的时候,高度自动适应在IE下无效,这时候应该触发IE的layout私有属性(万恶的IE啊!)用zoom:1;可以做到,这样就达到了兼容。
  例如某一个wrapper如下定义:.colwrapper{
overflow:hidden;
zoom:1;
margin:5px auto;}

  2、margin加倍的问题。

  设置为float的div在ie下设置的margin会加倍。这是一个ie6都存在的bug。
  解决方案是在这个div里面加上display:inline;
例如:
<#div id=\"imfloat\">


  相应的css为
#IamFloat{
float:left;
margin:5px;/*IE下理解为10px*/
display:inline;/*IE下再理解为5px*/}

  3、关于容器的包涵关系

  很多时候,尤其是容器内有平行布局,例如两、三个float的div时,宽度很容易出现问题。在IE中,外层的宽度会被内层更宽的div挤破。一定要用Photoshop或者Firework量取像素级的精度。

  4、关于高度的问题

  如果是动态地添加内容,高度最好不要定义。浏览器可以自动伸缩,然而如果是静态的内容,高度最好定好。(似乎有时候不会自动往下撑开,不知道具体怎么回事)

  5、最狠的手段 - !important;

  如果实在没有办法解决一些细节问题,可以用这个方法.FF对于"!important"会自动优先解析,然而IE则会忽略.如下.tabd1{
background:url(/res/images/up/tab1.gif) no-repeat 0px 0px !important; /*Style for FF*/
background:url(/res/images/up/tab1.gif) no-repeat 1px 0px; /* Style for IE */}
  值得注意的是,一定要将xxxx !important 这句放置在另一句之上,上面已经提过 IE7.0出来了,对CSS的支持又有新问题。浏览器多了,网页兼容性更差了,疲于奔命的还是我们 ,为解决IE7.0的兼容问题,找来了下面这篇文章:

现 在我大部分都是用!important来hack,对于ie6和firefox测试可以正常显示,但是ie7对!important可以正确解释,会导致 页面没按要求显示!搜索了一下,找到一个针对IE7不错的hack方式就是使用“*+html”,现在用IE7浏览一下,应该没有问题了。

现在写一个CSS可以这样:
#example { color: #333; } /* Moz */
* html #example { color: #666; } /* IE6 */
*+html #example { color: #999; } /* IE7 */

那么在firefox下字体颜色显示为#333,IE6下字体颜色显示为#666,IE7下字体颜色显示为#999,他们都互不干扰。

- 作者: 东方之子 2007年01月28日, 星期日 22:39  回复(0) |  引用(0) 加入博采

XHTML+CSS兼容性解决方案小集
使用XHTML+CSS构架好处不少,但也确实存在一些问题,不论是因为使用不熟练还是思路不清晰,我就先把一些我遇到的问题写在下面,省的大家四处找。

1.在mozilla firefox和IE中的BOX模型解释不一致导致相差2px解决方法:

div{margin:30px!important;margin:28px;}

注意这两个margin的顺序一定不能写反,据阿捷的说法!important这个属性IE不能识别,但别的浏览器可以识别。所以在IE下其实解释成这样:

 div{maring:30px;margin:28px}

重复定义的话按照最后一个来执行,所以不可以只写margin:XXpx!important;

2.IE5和IE6的BOX解释不一致IE5下div{width:300px;margin:0 10px 0 10px;}div的宽度会被解释为300px-10px(右填充)-10px(左填充)最终div的宽度为280px,而在IE6和其他浏览器上宽度则 是以300px+10px(右填充)+10px(左填充)=320px来计算的。这时我们可以做如下修改:

 div{width:300px!important;width  /**/:340px;margin:0  10px  0  10px}

关于这个/**/是什么我也不太明白,只知道IE5和firefox都支持但IE6不支持,如果有人理解的话,请告诉我一声,谢了!:)

3.ul标签在Mozilla中默认是有padding值的,而在IE中只有margin有值所以先定义:

 ul{margin:0;padding:0;}

就能解决大部分问题。

4.关于脚本,在xhtml1.1中不支持language属性,只需要把代码改为:

<script  type="text/javascript">

就可以了。

5.如果你在BOX容器里使float和text-align的方向设为一致:

{float:left;text-align:left;margin:0 0 0 200px;}

我们可做如下修改:

{float:left;text-align:left;margin:0 0 0 200px;display:inline;}

- 作者: 东方之子 2007年01月28日, 星期日 22:37  回复(0) |  引用(0) 加入博采

XHTML教程
现在都讲究标准建站,而标准建站使用的技术主要是XHTML+CSS,而现在我们普遍使用的是HTML代码,那么我该如何转换呢?以及HTML和XHTML有什么不同呢?在这个教程里,你将学到HTML和XHTML之间的不同,以及如何将HTML转换为XHTML。毕竟XHTML是发展的方向,所以我觉得该教程有必要在本站上发布。我感觉要是你想使用标准还是最好先学HTML,因为比较简单,然后再来看该教程。

  XHTML介绍:

  XHTML是 EXtensible HyperText Markup Language(可扩展超文本标记语言) 的英文缩写,而HTML则是 HyperText Markup Language(超文本标记语言) ,这是名字的不同。其实我们说得标准应该是XML,那为什么要学习XHTML呢?因为现在的HTML代码烦琐,危机四伏,但是XML使用环境还不成熟,所以推出了一个过度的产品就是XHTML,它起着呈上起下的作用。也有人认为XHTML是HTML的一个升级版本,其实也是正确的,我的理解是XHTML把HTML做得更加规范的一个标记语言,使HTML变得功能强大,减少了代码的烦琐尤其是表格。

  XHTML是在2000年1月26日被国际标准组织机构W3C(World Wide web Consortium)定为一个标准的,认为是HTML的一个最新版本,并且将逐渐替换HTML。现在所有的浏览器都支持XHTML,XHTML兼容 HTML 4.0。也有人认为XHTML就是HTML4.01。如果你在学习过程中自己编写了一个符合标准的站,你可以通过W3C的验证,验证通过后你将会得到一个标志,通常是XHTML1.0认证和CSS验证。我也不清楚目前国内有多少个网站同时通过了这两个验证。大家可以去http://www.w3.org/这个站点去验证你的站,如果符合那两个规则则会分别给我们两段代码加到你的网页上向别人展示说明你采用了标准建站啊,牛啊!

    XHTML是The Extensible HyperText Markup Language(可扩展标识语言)的缩写。HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言,看起来与HTML有些相象,只有一些小的但重要的区别,XHTML就是一个扮演着类似HTML的角色的XML,所以,本质上说,XHTML是一个过渡技术,结合了部分XML的强大功能及大多数HTML的简单特性。
  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)。
 

  为什么我们使用XHTML

  XHTML是HTML升级为XML的过度产品,被定为一个标准,XHTML完全兼容HTML4.01,并且具有XML的语法。下面我们来看一个含有错误代码的HTML,如下:
<html>
  <head>
  <title>This is bad HTML</title>
  <body>
  <h1>Bad HTML
  </body>

  虽然含有错误代码,但是当我们在浏览器中浏览时还能正常显示。XML是一个标记语言,但是它要求在网页中出现的任何元素都应该被标记出来,XML是用来描述网页中的数据的,而HTML用来显示网页中的元素的。目前我们上网使用的各种浏览器技术,包括手提电脑、手机上网浏览等等,都要求浏览的一些内容都要被正确标记,如果有错误的标记可能会使显示特别混乱、甚至不能正常显示。

  因此联合 HTML 和XML , 还有其他的一些技术,我们得到了一种现在有用的而且在将来也有用的语言 - XHTML。

  当在将来都规范的时候我们就要用的 XHTML 正确格式的标记了,使所有的浏览器都能正确的执行,所以我们现在有必要开始学习XHTML了。

  XHTML和HTML之间的区别:

  XHTML是一项新技术,在浏览器和一些其他的软件都支持它之前,我们应该有必要熟悉一下这项技术。为了我们更好的学习XHTML之前我们应该熟悉一下HTML4.0,我们可以去下载一个参考手册来熟悉一下。以便于我们学起XHTML来更简单,换句话说我们现在使用HTML编写代码时应该尽力少写错误代码,如:都要使用小写的字符来编写HTML,每个标记之后都要加上标记的结束如:<p>网页教学网欢迎您的光临</p> 结束一定要有,我们要保持这种规则。

  它们之间最大的区别在于:

  1.XHTML 元素一定要被正确的嵌套使用。

  在HTML里一些元素可以不正确嵌套也能正常显示,如:
  <b><i>This text is bold and italic</b></i>
  而在XHTML必须要正确嵌套之后才能正常使用,如:
  <b><i>This text is bold and italic</i></b>
  注意:这个错误通常发生在当嵌套多层之后的标签里面。如:
  <ul>
   <li>Coffee</li>
   <li>Tea
   <ul>
    <li>Black tea</li>
    <li>Green tea</li>
   </ul>
   <li>Milk</li>
  </ul>
  正确的应该是:
  <ul>
   <li>Coffee</li>
   <li>Tea
   <ul>
    <li>Black tea</li>
    <li>Green tea</li>
   </ul>
   </li>
   <li>Milk</li>
  </ul>
  观察上述的两段代码我们可以看到正确的里面我们在 </ul>之后插入 </li> 标签。

  XHTML 文件一定要有正确的组织格式。

  所有的XHTML应该正确的被嵌套在以<html>开始以</html>结束的元素里面,其他的元素可以有子元素,并且子元素也要被正确的嵌套在他们的父元素内。如:
<html>
  <head> ... </head>
  <body> ... </body>
  </html>
  标签名字一定要用小写字母。
  因为 XHTML文档是XML应用程序, XML 对大小写是敏感的。象 <br> 和 <BR> 是两个不同的标记。如错误代码:
  <BODY>
  <P>This is a paragraph</P>
  </BODY>
  正确格式为:
  <body>
  <p>This is a paragraph</p>
  </body>

  所有的 XHTML 元素一定要关闭

  不能有没有关闭的空的元素存在我们的代码中,其实对于这点我们是比较好结束的,有开始就应该有结束吗?例如错误代码:
  <p>This is a paragraph
  <p>This is another paragraph
  正确的为:
  <p>This is a paragraph</p>
  <p>This is another paragraph</p>
  独立的一个标签我们也要结束用 />来结束。
  例如:错误代码
  This is a break<br>
  Here comes a horizontal rule:<hr>
  Here's an image <img src="happy.gif" alt="Happy face">
  正确代码:
  This is a break<br />
  Here comes a horizontal rule:<hr />
  Here's an image <img src="happy.gif" alt="Happy face" />
  通过上面的几个例子我们基本上看出了HTML和XHTML之间的不同,那么我们应该从现在起应该试着改变我们现在的HTML,例如都使用小写的标记、在标记之后加上结束标记的符号 />。
  XHTML 的语法
  简单的说写 XHTML 要用干净的 HTML 语法。
  XHTML的一些其他语法要求:
  属性名字必须小写。如:
  错误代码:
  <table WIDTH="100%">
  正确的代码:
  <table width="100%">
  属性值必须要被引用。如:
  错误的代码:
  <table width=100%>
  正确的代码:
  <table width="100%">
  属性的缩写被禁止。如:
  错误的代码:
  <dl compact>
  <input checked>
  <input readonly>
  <input disabled>
  <option selected>
  <frame noresize>
  正确的代码:
  <dl compact="compact">
  <input checked="checked" />
  <input readonly="readonly" />
  <input disabled="disabled" />
  <option selected="selected" />
  <frame noresize="noresize" />
  列出一个表让大家知道:
  HTML          XHTML
  compact       compact="compact"
  checked       checked="checked"
  declare       declare="declare"
  readonly       readonly="readonly"
  disabled       disabled="disabled"
  selected      selected="selected"
  defer        defer="defer"
  ismap        ismap="ismap"
  nohref       nohref="nohref"
  noshade       noshade="noshade"
  nowrap       nowrap="nowrap"
  multiple      multiple="multiple"
  noresize      noresize="noresize"

  用id属性代替name属性。如:
  HTML 4.01 中为a,applet, frame, iframe, img 和 map定义了一个name属性.在 XHTML 里name属性是不能被使用的,应该用id 来替换它。如:

  错误代码:
  <img src="picture.gif" name="picture1" />
      正确的代码:
  <img src="picture.gif" id="picture1" />
  注意:我们为了使旧浏览器也能正常的执行该内容我们也可以在标签中同时使用id和name属性。如:
  <img src="picture.gif" id="picture1" name="picture1" />
  为了适应新的浏览器浏览我们在上述代码中的最后我加了/来结束标签。

 

 

XHTML DTD定义文档的类型。
  在XHTML中我们必须声明文档的类型,以便于浏览器知道你的文档是什么类型的,而且声明部分要加在文档的head之前。如:
  <!DOCTYPE Doctype goes here>
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>Title goes here</title>
  </head><body>
  Body text goes here
  </body></html>
  注:DOCTYPE声明不是 XHTML 文档的一部分,它也不是文档的一个元素,所以我们没必要加上结束标签。
  注:XHTML属性都是在<html>标签里面。然而当我们在w3.org验证时,并不解释我们的文档有没有声明类型。这是因为"xmlns=http://www.w3.org/1999/xhtml"是一个固定的值,如果你没声明的话,它也会被自动的加到<html>标签前。

  我们使用DOCTYPE时的基本机构:
  <!DOCTYPE ...>
  <html>
  <head>
  <title>... </title>
  </head>
  <body> ... </body>
  </html>

  DOCTYPE是document type(文档类型)的简写,用来说明你用的XHTML或者HTML是什么版本。

  其中的DTD(例如xhtml1-transitional.dtd)叫文档类型定义,里面包含了文档的规则,浏览器就根据你定义的DTD来解释你页面的标识,并展现出来。

  要建立符合标准的网页,DOCTYPE声明是必不可少的关键组成部分;除非你的XHTML确定了一个正确的DOCTYPE,否则你的标识和CSS都不会生效。

  XHTML 1.0 提供了三种DTD声明可供选择:

  过渡的(Transitional):要求非常宽松的DTD,它允许你继续使用HTML4.01的标识(但是要符合xhtml的写法)。完整代码如下:

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  严格的(Strict):要求严格的DTD,你不能使用任何表现层的标识和属性,完整代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

  框架的(Frameset):专门针对框架页面设计使用的DTD,如果你的页面中包含有框架,需要采用这种DTD。完整代码如下:

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

  如何转换现有的结构为XHTML

  我们选择什么样的DOCTYPE?理想情况当然是严格的DTD,但对于我们大多数刚接触web标准的设计师来说,过渡的DTD(XHTML 1.0 Transitional)是目前理想选择(包括本站,使用的也是过渡型DTD)。因为这种DTD还允许我们使用表现层的标识、元素和属性,也比较容易通过W3C的代码校验。

  我们从现在的HTML转换为XHTML注意以下几点:
 

  一、在每个页面的首部都加上文档类型的说明。如:

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  当然可以选择其他类型的。

  二、标记和name 要都用小写。

  我们可以自己编写一个替换程序,将你的HTML文档中的所有的标记都换为小写字母,还有name属性也要变为小写。

  三、所有的属性值都要用引号引起来。

  四、单独的标签,如: <hr> , <br> and <img>,都要在后面加/来结束。在这里不建议使用诸如:<img>和</img>形式的方式,直接在其后面加/就可以了,如<br />。

  五、我们打开W3C DTD 的官方网站:http://validator.w3.org/check/referer,验证时一般错误可能会出现在你的标签嵌套里。也可以用官方网站提供的转换工具tidy来实现转换:http://www.w3.org/People/Raggett/tidy/,我不建议大家直接来使用该工具来验证,因为我们毕竟是新学XHTML我们还是自己转换,这样我们可以熟悉XHTML啊,再者说我们还要学习tidy工具的使用,那样也是比较麻烦的。

  六、我们直接打开下面的页面可以直接输入网址来验证我们的程序了:

  XHTML 的模块化

  为什么要模块化设计XHTML呢?XHTML虽然简单,但是它的内容很多,包括了一个网络设计师需要的绝大多数功能。XHTML一方面内容繁多复杂,但是从另一个角度来看它却是非常简单的。为了将XHTML分割成小的模块,W3C已经建立起了小型的已经定义好了的一系列XHTML元素,他们独立的能被与其他XML标准合并成的大型的更复杂的程序的简单设备所使用。

  通过XHTML模型,程序设计师能够做如下的事情:

  1.选择那些能够被使用XHTML构建块标准的设备所支持的元素。
  2.在遵循XHTML标准的同时使用XML可以对XHTML扩展。
  3.简单化的XHTML可以应用于像掌上电脑、移动电话、电视和家用电器等设备。
  4.通过加入心的XML功能(像声音、多媒体的)将XHTML延续到复杂程序的设计上。
  5.像XHTML基本(XHTML对于移动设备的一个子集)那样来定义XHTML的轮廓。

 

模块名

描述

Applet Module

* applet元素.

Base Module

定义基本元素.

Basic Forms Module

定义基本的表单元素

Basic Tables Module

定义基本的表格元素

Bi-directional Text Module

定义 bdo 元素.

Client Image Map Module

定义浏览器的 image map 元素.

Edit Module

Defines the editing elements del and ins.

Forms Module

Defines all elements used in forms.

Frames Module

定义框架集元素

Hypertext Module

定义 a 元素.

Iframe Module

定义 iframe 元素.

Image Module

定义 img 元素.

Intrinsic Events Module

定义事件改变属性元素

Legacy Module

Defines deprecated* elements and attributes.

Link Module

定义link 元素.

List Module

定义 list 元素 ol, li, ul, dd, dt, dl.

Metainformation Module

定义 meta 元素.

Name Identification Module

Defines the deprecated* name attribute.

Object Module

定义object 和param 元素.

Presentation Module

定义表现元素如 b 和 i.

Scripting Module

定义 script and noscript 元素.

Server Image Map Module

定义 server side image map 元素.

Structure Module

定义结构 html, head, title and body.

Style Attribute Module

定义 style 属性.

Style Sheet Module

定义style 元素.

Tables Module

定义表内应用的元素.

Target Module

定义 target 属性.

Text Module

定义 text container 元素如: p and h1.

XHTML代码规范

 

我们必须先了解一下web标准有关代码的规范。了解这些规范可以帮助你少走弯路,尽快通过代码校验。

1.所有的标记都必须要有一个相应的结束标记

以前在HTML中,你可以打开许多标签,例如<p>和<li>而不一定写对应的</p>和</li>来关闭它们。但在XHTML中这是不合法的。XHTML要求有严谨的结构,所有标签必须关闭。如果是单独不成对的标签,在标签最后加一个"/"来关闭它。例如:

<br /><img height="80" alt="网页设计师" src="../images/logo_w3cn_200x80.gif" width="200" />

2.所有标签的元素和属性的名字都必须使用小写

与HTML不一样,XHTML对大小写是敏感的,<title>和<TITLE>是不同的标签。XHTML要求所有的标签和属性的名字都必须使用小写。例如:<BODY>必须写成<body> 。大小写夹杂也是不被认可的,通常dreamweaver自动生成的属性名字"onMouseOver"也必须修改成"onmouseover"。

3.所有的XML标记都必须合理嵌套

同样因为XHTML要求有严谨的结构,因此所有的嵌套都必须按顺序,以前我们这样写的代码:

<p><b></p>/b>

必须修改为:

<p><b></b>/p>

就是说,一层一层的嵌套必须是严格对称。

4.所有的属性必须用引号""括起来

在HTML中,你可以不需要给属性值加引号,但是在XHTML中,它们必须被加引号。例如:

<height=80>

必须修改为:

<height="80">

特殊情况,你需要在属性值里使用双引号,你可以用",单引号可以使用&apos;,例如:

<alt="say&apos;hello&apos;">

5.把所有<和&特殊符号用编码表示

  • 任何小于号(<),不是标签的一部分,都必须被编码为& l t ;

  • 任何大于号(>),不是标签的一部分,都必须被编码为& g t ;

  • 任何与号(&),不是实体的一部分的,都必须被编码为& a m p;

注:以上字符之间无空格。

6.给所有属性赋一个值

XHTML规定所有属性都必须有一个值,没有值的就重复本身。例如:

<td nowrap> <input type="checkbox" name="shirt" value="medium" checked>

必须修改为:

<td nowrap="nowrap"> <input type="checkbox" name="shirt" value="medium" checked="checked">

7.不要在注释内容中使“--”

“--”只能发生在XHTML注释的开头和结束,也就是说,在内容中它们不再有效。例如下面的代码是无效的:

<!--这里是注释-----------这里是注释-->

用等号或者空格替换内部的虚线。

<!--这里是注释============这里是注释-->

以上这些规范有的看上去比较奇怪,但这一切都是为了使我们的代码有一个统一、唯一的标准,便于以后的数据再利用。

- 作者: 东方之子 2007年01月28日, 星期日 20:34  回复(0) |  引用(0) 加入博采

中文搜索引擎技术揭密:网络蜘蛛
 随着搜索经济的崛起,人们开始越加关注全球各大搜索引擎的性能、技术和日流量。作为企业,会根据搜索引擎的知名度以及日流量来选择是否要投放广告等;作为普通网民,会根据搜索引擎的性能和技术来选择自己喜欢的引擎查找资料;作为学者,会把有代表性的搜索引擎作为研究对象……

    而作为一个网站的经营者,其更关心的或许是如何通过网络载体让更多的网民知道自己的网站,进而获得更高的流量和知名度。这其中,搜索引擎已经成了一个重要的且是免费的宣传途径。一方面,搜索引擎会主动出击,寻找网络上的各种网页数据,并在后台按相关条件进行索引;另一方面,各大网站为了能让自己的内容更多的通过搜索引擎向网民展示,都开始对网站结构进行重大调整,其中包括扁平化结构设计、动态(网页)转静态(网页)、Sitemap等。

    这些看来不经意的举动都让我们切身感受到搜索引擎对我们网络使用方式的改变起到了重要作用。并且,正因为搜索引擎的兴起以及社会各界对其重视程度日渐高涨,还由此创造了一个全新的职位——SEO。实际上,搜索引擎经济的崛起,又一次向人们证明了网络所蕴藏的巨大商机。网络离开了搜索将只剩下空洞杂乱的数据,以及大量等待去费力挖掘的金矿。


    搜索引擎一直专注于提升用户的体验度,其用户体验度则反映在三个方面: 准、全、快 。用专业术语讲是:查准率、查全率和搜索速度(即搜索耗时)。其中最易达到的是搜索速度,因为对于搜索耗时在1秒以下的系统来说,访问者很难辨别其快慢了,更何况还有网络速度的影响。因此,对搜索引擎的评价就集中在了前两者:准、全。中文搜索引擎的“准”,需要保证搜索的前几十条结果都和搜索词十分相关,这需由“ 分词技术 ”和“ 排序技术 ”来决定;中文搜索引擎的“全”则需保证不遗漏某些重要的结果,而且能找到最新的网页,这需要搜索引擎有一个强大的网页收集器,一般称为“网络蜘蛛”,也有叫“网页机器人”。



    研究搜索引擎技术的文章不少,但大部分讨论的是如何评价网页的重要性,对于网络蜘蛛研究的文章不多。网络蜘蛛技术并不是一项十分高深的技术,但要做一个强大的网络蜘蛛,却非易事。在目前磁盘容量已经不是瓶颈的时候,搜索引擎一直在扩大自己的网页数量。最大的搜索引擎Google( http://www.google.com )从2002年的10亿网页增加到现在近40亿网页;最近雅虎搜索引擎( http://search.yahoo.com/ )号称收录了45亿个网页;国内的中文搜索引擎百度( http://www.baidu.com )的中文页面从两年前的七千万页增加到了现在的两亿多。据估计,整个互联网的网页数达到100多亿,而且每年还在快速增长。因此一个优秀的搜索引擎,需要不断的优化网络蜘蛛的算法,提升其性能。


    或许有些人有疑问,为何搜索引擎需要用网络蜘蛛抓取网站所有的网页,为什么不在搜索者输入关键词后只把那些需要的结果抓取过来?这实际上是效率问题,搜索引擎不可能在搜索时实时去检查每个网页,而是需要把网页先抓取下来,按照关键词建立好索引,每次搜索的结果都会直接从搜索引擎建立好索引的数据库中查找,然后把结果返回给访问者。 关于搜索引擎系统架构方面的知识, 本文主要介绍网络蜘蛛的相关技术。


网络蜘蛛基本原理


    网络蜘蛛即Web Spider,是一个很形象的名字。把互联网比喻成一个蜘蛛网,那么Spider就是在网上爬来爬去的蜘蛛。网络蜘蛛是通过网页的链接地址来寻找网页,从网站某一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其它链接地址,然后通过这些链接地址寻找下一个网页,这样一直循环下去,直到把这个网站所有的网页都抓取完为止。如果把整个互联网当成一个网站,那么网络蜘蛛就可以用这个原理把互联网上所有的网页都抓取下来。


    对于搜索引擎来说,要抓取互联网上所有的网页几乎是不可能的,从目前公布的数据来看,容量最大的搜索引擎也不过是抓取了整个网页数量的百分之四十左右。这其中的原因一方面是抓取技术的瓶颈,无法遍历所有的网页,有许多网页无法从其它网页的链接中找到;另一个原因是存储技术和处理技术的问题,如果按照每个页面的平均大小为20K计算(包含图片),100亿网页的容量是100×2000G字节,即使能够存储,下载也存在问题(按照一台机器每秒下载20K计算,需要340台机器不停的下载一年时间,才能把所有网页下载完毕)。同时,由于数据量太大,在提供搜索时也会有效率方面的影响。因此,许多搜索引擎的网络蜘蛛只是抓取那些重要的网页,而在抓取的时候评价重要性主要的依据是某个网页的链接深度。


    在抓取网页的时候,网络蜘蛛一般有两种策略:广度优先和深度优先(如下图所示)。广度优先是指网络蜘蛛会先抓取起始网页中链接的所有网页,然后再选择其中的一个链接网页,继续抓取在此网页中链接的所有网页。这是最常用的方式,因为这个方法可以让网络蜘蛛并行处理,提高其抓取速度。深度优先是指网络蜘蛛会从起始页开始,一个链接一个链接跟踪下去,处理完这条线路之后再转入下一个起始页,继续跟踪链接。这个方法有个优点是网络蜘蛛在设计的时候比较容易。两种策略的区别,下图的说明会更加明确。


中文搜索引擎技术揭密:网络蜘蛛


    由于不可能抓取所有的网页,有些网络蜘蛛对一些不太重要的网站,设置了访问的层数。例如,在上图中,A为起始网页,属于0层,B、C、D、E、F属于第1层,G、H属于第2层,I属于第3层。如果网络蜘蛛设置的访问层数为2的话,网页I是不会被访问到的。这也让有些网站上一部分网页能够在搜索引擎上搜索到,另外一部分不能被搜索到。 对于网站设计者来说,扁平化的网站结构设计有助于搜索引擎抓取其更多的网页。


    网络蜘蛛在访问网站网页的时候,经常会遇到加密数据和网页权限的问题,有些网页是需要会员权限才能访问。当然,网站的所有者可以通过协议让网络蜘蛛不去抓取(下小节会介绍),但对于一些出售报告的网站,他们希望搜索引擎能搜索到他们的报告,但又不能完全免费的让搜索者查看,这样就需要给网络蜘蛛提供相应的用户名和密码。网络蜘蛛可以通过所给的权限对这些网页进行网页抓取,从而提供搜索。而当搜索者点击查看该网页的时候,同样需要搜索者提供相应的权限验证。


网站与网络蜘蛛


    网络蜘蛛需要抓取网页,不同于一般的访问,如果控制不好,则会引起网站服务器负担过重。今年4月,淘宝网( http://www.taobao.com )就因为雅虎搜索引擎的网络蜘蛛抓取其数据引起淘宝网服务器的不稳定。网站是否就无法和网络蜘蛛交流呢?其实不然,有多种方法可以让网站和网络蜘蛛进行交流。一方面让网站管理员了解网络蜘蛛都来自哪儿,做了些什么,另一方面也告诉网络蜘蛛哪些网页不应该抓取,哪些网页应该更新。


    每个网络蜘蛛都有自己的名字,在抓取网页的时候,都会向网站标明自己的身份。网络蜘蛛在抓取网页的时候会发送一个请求,这个请求中就有一个字段为User-agent,用于标识此网络蜘蛛的身份。例如Google网络蜘蛛的标识为GoogleBot,Baidu网络蜘蛛的标识为BaiDuSpider,Yahoo网络蜘蛛的标识为Inktomi Slurp。如果在网站上有访问日志记录,网站管理员就能知道,哪些搜索引擎的网络蜘蛛过来过,什么时候过来的,以及读了多少数据等等。如果网站管理员发现某个蜘蛛有问题,就通过其标识来和其所有者联系。下面是博客中国( http://www.blogchina.com )2004年5月15日的搜索引擎访问日志:


中文搜索引擎技术揭密:网络蜘蛛
    网络蜘蛛进入一个网站,一般会访问一个特殊的文本文件Robots.txt,这个文件一般放在网站服务器的根目录下,如: http://www.blogchina.com/robots.txt 。网站管理员可以通过robots.txt来定义哪些目录网络蜘蛛不能访问,或者哪些目录对于某些特定的网络蜘蛛不能访问。例如有些网站的可执行文件目录和临时文件目录不希望被搜索引擎搜索到,那么网站管理员就可以把这些目录定义为拒绝访问目录。Robots.txt语法很简单,例如如果对目录没有任何限制,可以用以下两行来描述: User-agent: * Disallow:


    当然,Robots.txt只是一个协议,如果网络蜘蛛的设计者不遵循这个协议,网站管理员也无法阻止网络蜘蛛对于某些页面的访问,但一般的网络蜘蛛都会遵循这些协议,而且网站管理员还可以通过其它方式来拒绝网络蜘蛛对某些网页的抓取。


    网络蜘蛛在下载网页的时候,会去识别网页的HTML代码,在其代码的部分,会有META标识。通过这些标识,可以告诉网络蜘蛛本网页是否需要被抓取,还可以告诉网络蜘蛛本网页中的链接是否需要被继续跟踪。例如: 表示本网页不需要被抓取,但是网页内的链接需要被跟踪。


    关于Robots.txt的语法和META Tag语法,有兴趣的读者查看文献[4]


    现在一般的网站都希望搜索引擎能更全面的抓取自己网站的网页,因为这样可以让更多的访问者能通过搜索引擎找到此网站。为了让本网站的网页更全面被抓取到,网站管理员可以建立一个网站地图,即Site Map。许多网络蜘蛛会把sitemap.htm文件作为一个网站网页爬取的入口,网站管理员可以把网站内部所有网页的链接放在这个文件里面,那么网络蜘蛛可以很方便的把整个网站抓取下来,避免遗漏某些网页,也会减小对网站服务器的负担。


内容提取


    搜索引擎建立网页索引,处理的对象是文本文件。对于网络蜘蛛来说,抓取下来网页包括各种格式,包括html、图片、doc、pdf、多媒体、动态网页及其它格式等。这些文件抓取下来后,需要把这些文件中的文本信息提取出来。准确提取这些文档的信息,一方面对搜索引擎的搜索准确性有重要作用,另一方面对于网络蜘蛛正确跟踪其它链接有一定影响。


    对于doc、pdf等文档,这种由专业厂商提供的软件生成的文档,厂商都会提供相应的文本提取接口。网络蜘蛛只需要调用这些插件的接口,就可以轻松的提取文档中的文本信息和文件其它相关的信息。


    HTML等文档不一样,HTML有一套自己的语法,通过不同的命令标识符来表示不同的字体、颜色、位置等版式,如:、、 等,提取文本信息时需要把这些标识符都过滤掉。过滤标识符并非难事,因为这些标识符都有一定的规则,只要按照不同的标识符取得相应的信息即可。但在识别这些信息的时候,需要同步记录许多版式信息,例如文字的字体大小、是否是标题、是否是加粗显示、是否是页面的关键词等,这些信息有助于计算单词在网页中的重要程度。同时,对于HTML网页来说,除了标题和正文以外,会有许多广告链接以及公共的频道链接,这些链接和文本正文一点关系也没有,在提取网页内容的时候,也需要过滤这些无用的链接。例如某个网站有“产品介绍”频道,因为导航条在网站内每个网页都有,若不过滤导航条链接,在搜索“产品介绍”的时候,则网站内每个网页都会搜索到,无疑会带来大量垃圾信息。过滤这些无效链接需要统计大量的网页结构规律,抽取一些共性,统一过滤;对于一些重要而结果特殊的网站,还需要个别处理。这就需要网络蜘蛛的设计有一定的扩展性。


    对于多媒体、图片等文件,一般是通过链接的锚文本(即,链接文本)和相关的文件注释来判断这些文件的内容。例如有一个链接文字为“张曼玉照片”,其链接指向一张bmp格式的图片,那么网络蜘蛛就知道这张图片的内容是“张曼玉的照片”。这样,在搜索“张曼玉”和“照片”的时候都能让搜索引擎找到这张图片。另外,许多多媒体文件中有文件属性,考虑这些属性也可以更好的了解文件的内容。
    动态网页一直是网络蜘蛛面临的难题。所谓动态网页,是相对于静态网页而言,是由程序自动生成的页面,这样的好处是可以快速统一更改网页风格,也可以减少网页所占服务器的空间,但同样给网络蜘蛛的抓取带来一些麻烦。由于开发语言不断的增多,动态网页的类型也越来越多,如:asp、jsp、php等。这些类型的网页对于网络蜘蛛来说,可能还稍微容易一些。网络蜘蛛比较难于处理的是一些脚本语言(如VBScript和JavaScript)生成的网页,如果要完善的处理好这些网页,网络蜘蛛需要有自己的脚本解释程序。对于许多数据是放在数据库的网站,需要通过本网站的数据库搜索才能获得信息,这些给网络蜘蛛的抓取带来很大的困难。对于这类网站,如果网站设计者希望这些数据能被搜索引擎搜索,则需要提供一种可以遍历整个数据库内容的方法。


    对于网页内容的提取,一直是网络蜘蛛中重要的技术。整个系统一般采用插件的形式,通过一个插件管理服务程序,遇到不同格式的网页采用不同的插件处理。这种方式的好处在于扩充性好,以后每发现一种新的类型,就可以把其处理方式做成一个插件补充到插件管理服务程序之中。


更新周期


    由于网站的内容经常在变化,因此网络蜘蛛也需不断的更新其抓取网页的内容,这就需要网络蜘蛛按照一定的周期去扫描网站,查看哪些页面是需要更新的页面,哪些页面是新增页面,哪些页面是已经过期的死链接。
    搜索引擎的更新周期对搜索引擎搜索的查全率有很大影响。如果更新周期太长,则总会有一部分新生成的网页搜索不到;周期过短,技术实现会有一定难度,而且会对带宽、服务器的资源都有浪费。搜索引擎的网络蜘蛛并不是所有的网站都采用同一个周期进行更新,对于一些重要的更新量大的网站,更新的周期短,如有些新闻网站,几个小时就更新一次;相反对于一些不重要的网站,更新的周期就长,可能一两个月才更新一次。
    一般来说,网络蜘蛛在更新网站内容的时候,不用把网站网页重新抓取一遍,对于大部分的网页,只需要判断网页的属性(主要是日期),把得到的属性和上次抓取的属性相比较,如果一样则不用更新。

结论 

    本文主要讨论了网络蜘蛛相关的技术要点,如果要设计好的网络蜘蛛, 需要了解更多的技术细节,可以参考文献


    网络蜘蛛在搜索引擎中占有重要位置,对搜索引擎的查全、查准都有影响,决定了搜索引擎数据容量的大小,而且网络蜘蛛的好坏直接影响搜索结果页中的死链接(即链接所指向的网页已经不存在)的个数。目前如何发现更多的网页、如何正确提取网页内容、如果下载动态网页、如何提供抓取速度、如何识别网站内内容相同的网页等都是网络蜘蛛需要进一步改进的问题。

- 作者: 东方之子 2007年01月22日, 星期一 16:06  回复(0) |  引用(0) 加入博采

揭开神秘面纱,搜索引擎原理浅析

在浩如烟海的Internet上,特别是其上的Web(World Wide Web万维网)上,不会搜索,就不会上网。网虫朋友们,你了解搜索引擎吗?它们是怎么工作的?你都使用哪些搜索引擎?今天我就和大家  
聊聊搜索引擎的话题。

一、搜索引擎的分类

获得网站网页资料,能够建立并提供查询的系统,我们都可以把它叫做搜索引擎。按照工作原理的不同,可以把它们分为两个基本类别:全文搜索引擎(FullText Search Engine)和分类目录Directory)。数据库

全文搜索引擎的数据库是依靠一个叫“网络机器人(Spider)”或叫“网络蜘蛛(crawlers)”的软件,通过网络上的各种链接自动获取大量网页信息内容,并按以定的规则分析整理形成的。Google、百度都是比较典型的全文搜索引擎系统。

分类目录则是通过人工的方式收集整理网站资料形成数据库的,比如雅虎中国以及国内的搜狐、新浪、网易分类目录。另外,在网上的一些导航站点,也可以归属为原始的分类目录,比如“网址之家”(http://www.hao123.com/)。

全文搜索引擎和分类目录在使用上各有长短。全文搜索引擎因为依靠软件进行,所以数据库的容量非常庞大,但是,它的查询结果往往不够准确;分类目录依靠人工收集和整理网站,能够提供更为准确的查询结果,但收集的内容却非常有限。为了取长补短,现在的很多搜索引擎,都同时提供这两类查询,一般对全文搜索引擎的查询称为搜索“所有网站”或“全部网站”,比如Google的全文搜索(http://www.google.com/intl/zh-CN/);把对分类目录的查询称为搜索“分类目录”或搜索“分类网站”,比如新浪搜索(http://dir.sina.com.cn/)和雅虎中国搜索(http://cn.search.yahoo.com/dirsrch/)。

在网上,对这两类搜索引擎进行整合,还产生了其它的搜索服务,在这里,我们权且也把它们称作搜索引擎,主要有这两类:

⒈元搜索引擎(META Search Engine)。这类搜索引擎一般都没有自己网络机器人及数据库,它们的搜索结果是通过调用、控制和优化其它多个独立搜索引擎的搜索结果并以统一的格式在同一界面集中显示。元搜索引擎虽没有“网络机器人”或“网络蜘蛛”,也无独立的索引数据库,但在检索请求提交、检索接口代理和检索结果显示等方面,均有自己研发的特色元搜索技术。比如“metaFisher元搜索引擎”

http://www.hsfz.net/fish/),它就调用和整合了Google、Yahoo、AlltheWeb、百度和OpenFind等多家搜索引擎的数据。

⒉集成搜索引擎(All-in-One Search Page)。集成搜索引擎是通过网络技术,在一个网页上链接很多个独立搜索引擎,查询时,点选或指定搜索引擎,一次输入,多个搜索引擎同时查询,搜索结果由各搜索引擎分别以不同页面显示,比如“网际瑞士军刀”(http://free.okey.net/%7Efree/search1.htm)。

二、搜索引擎的工作原理

全文搜索引擎的“网络机器人”或“网络蜘蛛”是一种网络上的软件,它遍历Web空间,能够扫描一定IP地址范围内的网站,并沿着网络上的链接从一个网页到另一个网页,从一个网站到另一个网站采集网页资料。它为保证采集的资料最新,还会回访已抓取过的网页。网络机器人或网络蜘蛛采集的网页,还要有其它程序进行分析,根据一定的相关度算法进行大量的计算建立网页索引,才能添加到索引数据库中。我们平时看到的全文搜索引擎,实际上只是一个搜索引擎系统的检索界面,当你输入关键词进行查询时,搜索引擎会从庞大的数据库中找到符合该关键词的所有相关网页的索引,并按一定的排名规则呈现给我们。不同的搜索引擎,网页索引数据库不同,排名规则也不尽相同,所以,当我们以同一关键词用不同的搜索引擎查询时,搜索结果也就不尽相同。

和全文搜索引擎一样,分类目录的整个工作过程也同样分为收集信息、分析信息和查询信息三部分,只不过分类目录的收集、分析信息两部分主要依靠人工完成。分类目录一般都有专门的编辑人员,负责收集网站的信息  
。随着收录站点的增多,现在一般都是由站点管理者递交自己的网站信息给分类目录,然后由分类目录的编辑人员审核递交的网站,以决定是否收录该站点。如果该站点审核通过,分类目录的编辑人员还需要分析该站点的内容,并将该站点放在相应的类别和目录中。所有这些收录的站点同样被存放在一个“索引”中。用户在查询信息时,可以选择按照关键词搜索,也可按分类目录逐层查找。如以关键词搜索,返回的结果跟全文搜索引擎一样,也是根据信息关联程度排列网站。需要注意的是,分类目录的关键词查询只能在网站的名称、网址、简介等内容中进行,它的查询结果也只是被收录网站首页的URL地址,而不是具体的页面。分类目录就像一个电话号码薄一样,按照各个网站的性质,把其网址分门别类排在一起,大类下面套着小类,一直到各个网站的详细地址,一般还会提供各个网站的内容简介,用户不使用关键词也可进行查询,只要找到相关目录,就完全可以找到相关的网站(注意:是相关的网站,而不是这个网站上某个网页的内容,某一目录中网站的排名一般是按照标题字母的先后顺序或者收录的时间顺序决定的)。数据库

三、搜索引擎的发展趋势。

一个好的搜索引擎,不仅数据库容量要大,更新频率、检索速度要快,支持对多语言的搜索,而且随着数据库容量的不断膨胀,还要能从庞大的资料库中精确地找到正确的资料。

⒈提高搜索引擎对用户检索提问的理解。

    为了提高搜索引擎对用户检索提问的理解,就必须有一个好的检索提问语言。为了克服关键词检索和目录查询的缺点,现在已经出现了自然语言智能答询。用户可以输入简单的疑问句,比如“如何能杀死计算机中的病毒”,搜索引擎在对提问进行结构和内容的分析之后,或直接给出提问的答案,或引导用户从几个可选择的问题中进行再选择。自然语言的优势在于,一是使网络交流更加人性化,二是使查询变得更加方便、直接、有效。就以上面的例子来讲,如果用关键词查询,多半人会用“病毒”这个词来检索,结果中必然会包括各类病毒的介绍,病毒是怎样产生的等等许多无用信息,而用“如何能杀死计算机中的病毒”检索,搜索引擎会将怎样杀死病毒的信息提供给用户,提高了检索效率。

⒉垂直主题搜索引擎有着极大的发展空间。

    网上的信息浩如烟海,网络资源以惊人的速度增长,一个搜索引擎很难收集全所有主题的网络信息,即使信息主题收集得比较全面,由于主题范围太宽,很难将各主题都做得精确而又专业,使得检索结果垃圾太多。这样以来,垂直主题的搜索引擎以其高度的目标化和专业化在各类搜索引擎中占据了一席之地。目前,一些主要的搜索引擎,都提供了新闻、Mp3、图片、Flash等的搜索,加强了检索的针对性。

⒊元搜索引擎,能够提供全面且较为准确的查询结果。

    现在的许多搜索引擎,其收集信息的范围、索引方法、排名规则等都各不相同,每个搜索引擎平均只能涉及到整个Web资源的30-50%,这样导致同一个搜索请求在不同搜索引擎中获得的查询结果的重复率不足34%,而每一个搜索引擎的查准率不到45%。元搜索引擎(META Search Engine)是将用户提交的检索请求发送到多个独立的搜索引擎上去搜索,并将检索结果集中统一处理,以统一的格式提供给用户,因此有搜索引擎之上的搜索引擎之称。它的主要精力放在提高搜索速度、智能化处理搜索结果、个性化搜索功能的设置和用户检索界面的友好性上,查全率和查准率都比较高。
  

- 作者: 东方之子 2007年01月22日, 星期一 16:04  回复(0) |  引用(0) 加入博采

linux下软件的基本安装和卸载
Linux软件的安装和卸载一直是困扰许多新用户的难题。在Windows中,我们可以使用软件自带的安装卸载程序或在控制面板中的“添加/删除程序”来实现。与其相类似,在Linux下有一个功能强大的软件安装卸载工具,名为RPM。它可以用来建立、安装、查询、更新、卸载软件。该工具是在命令行下使用的。在Shell的提示符后输入rpm,就可获得该命令的帮助信息。


  软件的安装


  Linux下软件的安装主要有两种不同的形式。第一种安装文件名为xxx.tar.gz;另一种安装文件名为xxx.i386.rpm。以第一种方式发行的软件多为以源码形式发送的;第二种方式则是直接以二进制形式发送的。

  对于第一种,安装方法如下:

  1 .首先,将安装文件拷贝至你的目录中。例如,如果你是以root身份登录上的,就将软件拷贝至/root中。

  #cp xxx.tar.gz /root

  2 .由于该文件是被压缩并打包的,应对其解压缩。命令为:

  #tar xvzf filename.tar.gz 如果是filename.tar.bz2格式的,应该是tar jxvf filename.tar.bz2来解压

  3. 执行该命令后,安装文件按路径,解压缩在当前目录下。用ls命令可以看到解压缩后的文件。通常在解压缩后产生的文件中,有“Install”的文件。该文件为纯文本文件,详细讲述了该软件包的安装方法。

  4.执行解压缩后产生的一个名为configure的可执行脚本程序。它是用于检查系统是否有编译时所需的库,以及库的版本是否满足编译的需要等安装所需要的系统信息。为随后的编译工作做准备。命令为: #./configure

如果您想把软件安装到指定目录,应该用#./configure --prefix=/您自己指定的目录,比如我想把一个mlterm安装到/opt/mlterm目录中,应该如下输入
#./configure --prefix=/opt/mlterm

  5.检查通过后,将生成用于编译的MakeFile文件。此时,可以开始进行编译了。编译的过程视软件的规模和计算机性能的不同,所耗费的时间也不同。命令为: #make。

  6.成功编译后,键入如下的命令开始安装:

  #make install

  7.安装完毕,应清除编译过程中产生的临时文件和配置过程中产生的文件。键入如下命令:

  #make clean

  #make distclean

  至此,软件的安装结束。

  对于第二种,其安装方法要简单得多。

  同第一种方式一样,将安装文件拷贝至你的目录中。然后使用rpm来安装该文件。命令如下:

  #rpm -i filename.i386.rpm

  rpm将自动将安装文件解包,并将软件安装到缺省的目录下。并将软件的安装信息注册到rpm的数据库中。参数i的作用是使rpm进入安装模式。


  软件的卸载


  1.软件的卸载主要是使用rpm来进行的。卸载软件首先要知道软件包在系统中注册的名称。键入命令:

  #rpm -q -a

  即可查询到当前系统中安装的所有的软件包。

  2. 确定了要卸载的软件的名称,就可以开始实际卸载该软件了。键入命令:

  #rpm -e [package name]

  即可卸载软件。参数e的作用是使rpm进入卸载模式。对名为[package name]的软件包进行卸载。由于系统中各个软件包之间相互有依赖关系。如果因存在依赖关系而不能卸载,rpm将给予提示并停止卸载。你可以使用如下的命令来忽略依赖关系,直接开始卸载:

  #rpm -e [package name] -nodeps

  忽略依赖关系的卸载可能会导致系统中其它的一些软件无法使用

如果想知道rpm包安装到哪里了呢?
应该用 #rpm -ql [package name]

3.如何卸载用源码包安装的软件?
最好是看README和INSTALL ;一般的情况下都有说,但大多软件没有提供源码包的卸载方法;我们可以找到软件的安装点删除。主要看你把它安装在哪了。
比如:

如果安装软件时,指定个目录。这个问题也不会难;

比如用源码包安装gaim 的

#./configure --prefix=/opt/gaim
#make
#make install

如果安装mlterm
#./configure --prefix=/opt/mlterm
#make
#make install

把源码包安装的软件,都指定安装在 /opt目录中,这样不就知道了??

如果删除,就删除相应的软件目录;

有些软件要在解压安装目录中执行 make uninstall ,这样就卸载掉了;

- 作者: 东方之子 2007年01月11日, 星期四 18:16  回复(0) |  引用(0) 加入博采

Linux下软件安装方法总结
一、rpm包安装方式步骤:
引用:

1、找到相应的软件包,比如soft.version.rpm,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.version.rpm所在的目录;

4、输入rpm -ivh soft.version.rpm



二、deb包安装方式步骤:

引用:
1、找到相应的软件包,比如soft.version.deb,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.version.deb所在的目录;

4、输入dpkg -i soft.version.deb



三、tar.gz源代码包安装方式:

引用:
1、找到相应的软件包,比如soft.tar.gz,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.tar.gz所在的目录;

4、tar -xzvf soft.tar.gz //一般会生成一个soft目录

5、cd soft

6、./configure

7、make

8、make install



四、tar.bz2源代码包安装方式:

引用:
1、找到相应的软件包,比如soft.tar.bz2,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.tar.bz2所在的目录;

4、tar -xjvf soft.tar.bz2 //一般会生成一个soft目录

5、cd soft

6、./configure

7、make

8、make install



五、apt方式安装:

引用:
1、打开一个终端,su -成root用户;

2、apt-cache search soft 注:soft是你要找的软件的名称或相关信息

3、如果2中找到了软件soft.version,则用apt-get install soft.version命令安装软件 注:只要你可以上网,只需要用apt-cache search查找软件,用apt-get install软件



六、bin文件安装:

如果你下载到的软件名是soft.bin,一般情况下是个可执行文件,安装方法如下:

引用:
1、打开一个终端,su -成root用户;

2、chmod +x soft.bin

3、./soft.bin //运行这个命令就可以安装软件了



/************关于本文档********************************************

*filename:Linux下软件安装方法总结

*purpose:总结了Linux下各种软件安装方法

*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)

Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言编程

*date time:2006-07-26 18:10:00

*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途

* 但请遵循GPL。

*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力

*********************************************************************/



七、不需要安装的软件:

有了些软件,比如lumaqq,是不需要安装的,自带jre解压缩后可直接运行。假设下载的是lumaqq.tar.gz,使用方法如下:

引用:
1、打开一个终端,su -成root用户;

2、tar -xzvf lumaqq.tar.gz //这一步会生成一个叫LumaQQ的目录

3、cd LumaQQ

4、chmod +x lumaqq //设置lumaqq这个程序文件为可运行

5、此时就可以运行lumaqq了,用命令./lumaqq即可,但每次运行要输入全路径或切换到刚才生成的LumaQQ目录里

6、为了保证不设置路径就可以用,你可以在/bin目录下建立一个lumaqq的链接,用命令ln -s lumaqq /bin/ 即可,以后任何时候打开一个终端输入lumaqq就可以启动QQ聊天软件了

7、如果你要想lumaqq有个菜单项,使用菜单编辑工具,比如Alacarte Menu Editor,找到上面生成的LumaQQ目录里的lumaqq设置一个菜单项就可以了,当然你也可以直接到/usr/share/applications目录,按照里面其它*.desktop文件的格式生成一个自己的desktop文件即可。



建议开发者们不要用red hat/red flag/suse等第一代Linux操作系统,用这些除了方便(也就是说比较傻瓜型)、界面豪华点外没什么好。用debian/ubuntu等第二代吧,apt命令安装软件是最简单的。apt命令会自动解决软件安装过程中的依赖问题,会把没有的包安装上,会把版本低的包自动升级,当然,都是要经你确认一次的。

如果你使用Red Hat等第1代Linux系统,安装软件是比较麻烦的事,rpm -ivh softA.rpm是用来安装softA软件的,但通常情况下可能遇到的问题是提示说需要安装softB1, softB2, softB3等一堆软件,然后你安装softB1软件包时,可能又会提示你说需要安装softC1, softC2, softC3, softC4等一堆软件……这样一来你就只够时间到处去找这些软件包了。光盘上没有就得去网上下载,网上还得搜索半天,时间都花在搜索软件包了。而且就算找到这些软件包,还可能会遇到的问题是:softC2软件包必须在softC1软件包之前安装才可以,顺序错了也安装不成功。但这谁知道呢?难啊。所以,你没有时间来安装体验软件的功能了,更别说开发软件了。

建议你安装第2代Linux操作系统,典型的是Debian Linux和Ubuntu Linux,我之前在文章“如何在安装了Windows操作系统的电脑上安装Linux操作系统”里提到一个简明安装手册,你下载来照着操作就可以安装Ubuntu了。

第2代操作系统在安装软件方面相当简单:第一步,搜索你要的软件,比如你要找一个游戏软件,它的名称叫myward,这个游戏软件的说明是:my own war game。搜索这个软件包就只需要输入命令apt-cache search myward,或者输入软件名称的一部分apt-cache search war,或者你不知道软件名称,输入软件说明里的一部分文字apt-cache search game,都可以找到这个软件,找到后进行第二步,只需要输入apt-get install myward,即后面跟上软件名称就可以安装了。

我是做程序开发的,不希望自己只会google找东西,希望有更多的时间研究Linux内核。

- 作者: 东方之子 2007年01月11日, 星期四 18:13  回复(0) |  引用(0) 加入博采

Linux 硬件管理的基础知识

Linux 硬件管理的基础知识

作者:北南南北
来自:LinuxSir.Org
摘要:本文主要解说在Linux中,硬件设备的表示方法及查看工具等;最主要的目的是当我们遇到硬件问题时,懂得如何根据硬件信息来解决问题;


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
正文
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++


一、在Linux 系统中,对硬件判别的标识的依据;

在 LinuxSir.Org 讨论区,我们经常看到有些弟兄这样来描述自己的硬件“我的显示卡是XXX牌子的,Linux 不支持怎么办?”。其实这样描述是最差的,大家也根本没有办法提供帮助;因为Linux对硬件的识别是以为芯片组的厂商为依据的,而非硬件的品牌;因为现在硬件厂商大多是OEM的,也就是说硬件的主芯片是他们生产不了的,但他们会从硬件主芯片厂商拿来,焊接在自己的电路板上,这就是OEM 的过程;

无论什么硬件都是以芯片组的厂商为标识的,而不是什么市场看到的这个品牌,那个品牌的;举个例子,我们在市场上看到有各种各样的显卡,其实看一下他们的芯片,大多是ATI和 NVIDIA的,所有的ATI和NVIDIA的驱动都是ATI和NVIDIA开发出来的。所以我们提问的时候,要把硬件的芯片说出来,芯片是驱动的唯一标识,而不是品牌!!!

所以我们要找硬件的驱动时,我们一定要根据硬件主芯片的信息来找相关的驱动;


二、在Linux中查看硬件信息的工具;

在Linux 中,并不是没有工具可以查看硬件的芯片信息,应该说Linux的工具能把硬件信息查看的更清楚;下面介绍几个常用的工具;我们最常用的工具还是lspci ;其它的工具只是了解一下;


1、lspci 列出所有PCI 设备;

lspci - list all PCI devices ,主要是有来列出机器中的PCI 设备,比如声卡、显卡、猫、网卡等,主板集成设备也能列出来;lspci 是读取 hwdata 数据库,hwdata 由软件包 hwdata 提供;大约有如下文件;

[beinan@localhost ~]# rpm -ql hwdata-0.158-1
/etc/hotplug/blacklist
/etc/pcmcia
/etc/pcmcia/config
/usr/X11R6/lib/X11/Cards
/usr/share/doc/hwdata-0.158
/usr/share/doc/hwdata-0.158/COPYING
/usr/share/doc/hwdata-0.158/LICENSE
/usr/share/hwdata
/usr/share/hwdata/CardMonitorCombos
/usr/share/hwdata/Cards
/usr/share/hwdata/MonitorsDB
/usr/share/hwdata/pci.ids
/usr/share/hwdata/pcitable
/usr/share/hwdata/upgradelist
/usr/share/hwdata/usb.ids

lspci 有两个参数是我们常用的,-b 和-v ,lspci 也会把usb接口列出来;

举例:

[root@localhost beinan]# lspci -b
00:00.0 Host bridge: Intel Corporation 82852/82855 GM/GME/PM/GMV Processor to I/O Controller (rev 02)
00:00.1 System peripheral: Intel Corporation 82852/82855 GM/GME/PM/GMV Processor to I/O Controller (rev 02)
00:00.3 System peripheral: Intel Corporation 82852/82855 GM/GME/PM/GMV Processor to I/O Controller (rev 02)
00:02.0 VGA compatible controller: Intel Corporation 82852/855GM Integrated Graphics Device (rev 02)
00:02.1 Display controller: Intel Corporation 82852/855GM Integrated Graphics Device (rev 02)
00:1d.0 USB Controller: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (rev 03)
00:1d.1 USB Controller: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (rev 03)
00:1d.2 USB Controller: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (rev 03)
00:1d.7 USB Controller: Intel Corporation 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (rev 03)
00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev 83)
00:1f.0 ISA bridge: Intel Corporation 82801DBM (ICH4-M) LPC Interface Bridge (rev 03)
00:1f.1 IDE interface: Intel Corporation 82801DBM (ICH4-M) IDE Controller (rev 03)
00:1f.3 SMBus: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (rev 03)
00:1f.5 Multimedia audio controller: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (rev 03)
00:1f.6 Modem: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (rev 03)
02:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (rev 10)
02:09.0 CardBus bridge: Texas Instruments Texas Instruments PCIxx21/x515 Cardbus Controller
02:09.2 FireWire (IEEE 1394): Texas Instruments Texas Instruments OHCI Compliant IEEE 1394 Host Controller
02:09.3 Unknown mass storage controller: Texas Instruments Texas Instruments PCIxx21 Integrated FlashMedia Controller
02:09.4 Class 0805: Texas Instruments Texas Instruments PCI6411, PCI6421, PCI6611, PCI6621, PCI7411, PCI7421, PCI7611, PCI7621 Secure Digital (SD)

分析一下这台机器中有什么设备,看主要的就行,与我们应用相关的;

00:02.0 VGA compatible controller: Intel Corporation 82852/855GM Integrated Graphics Device (rev 02)
00:02.1 Display controller: Intel Corporation 82852/855GM Integrated Graphics Device (rev 02) 注:这是显示卡;
USB Controller 表示的是USB 接口;我们看到有三个这样的设备;我的笔记本上正好有三个USB 接口;
Multimedia audio controller: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (rev 03) 注:这是声卡;
Modem: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (rev 03) 注:这是猫;
Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (rev 10) 注:这是网卡,芯片是8139的;
FireWire (IEEE 1394): Texas Instruments Texas Instruments OHCI Compliant IEEE 1394 Host Controller 注:这是1394接口的信息;事实上我的笔记本也有这样的接口;



那得到这些信息有什么用处呢?如果机器中有些设备支持的不好,我们就可以根据这些信息在Google 上搜索,比如我感觉我的声卡有问题,就可以根据声卡信息相关的来搜索找解决问题的办法;根据这些信息,我们也可以到硬件芯片组的官方去找答案或者驱动;

如果想知道硬件更为详细的内容,我们可以用 lspci -v 来查看;

[root@localhost beinan]# lspci -v

比如我们可以通过 lspci -v 来查看硬件的irq中断什么的;比如网卡不好用,是不是irq 存在冲突了?如果您不知道怎么解决硬件驱动不了的情况,就要把 lspci -v 相应硬件的信息整段贴出来,这才是解决问题的唯一办法;所以学会提问也是极为重要的;

有的系统发行版本,还有lsusb 的工具,自己尝试一下吧;


2、存储设备查看和操作工具;

我们查看存储设备的工具主要有 fdisk ;parted ;cfdisk 等;最常用也是最方便的就是fdisk ;parted 就当一个补充吧,这个工具目前看来并不是太成熟;

请参考:

《Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍》
《实例解说 fdisk 使用方法》


3、通过查看/proc 目录的相应文件获取一些硬件信息;

我们在查看 /etc/fstab 时,会注意到这样一行;

/dev/proc /proc proc defaults 0 0

proc 看起来象是一个文件系统,其实他并不是一个真正的文件系统 , 它是“proc - process information pseudo-filesystem”,译成中文大概的意思是“进程信息伪装文件系统”呵呵,这是我翻译的,有可能不对,请多多指正;
“The proc filesystem is a pseudo-filesystem which is used as an interface to kernel data
structures. It is commonly mounted at /proc. Most of it is read-only, but some files allow
kernel variables to be changed.”

我再来乱译一下然后再根据/proc 的内容自己理解理解。proc 文件系统做为内核kernel 数据结构的接口,把kernel 的一些信息(比如硬件信息,包括CPU 、网卡、显示卡、内存、文件系统、SCSI 设备 ....)写到 proc 文件系统中,proc被mont 到 /proc 目录;/proc 目录中有大数据大多文件是只读的,但一些数据是根据内核的变化而变化的;/proc 目录中的数据是经常变动的,对于系统中的每个进程都有一个PID;都可以在/proc 中找到;我们也可以通过 ps -aux |more 来查看进程;

我们可以通过 cat 命令来读取/proc 目录下的文件,比如cpu的信息;

[root@localhost beinan]# cat /proc/cpuinfo

详细的内容还得需要您来慢慢查看;对于 /proc 的了解也是有必要的;


4、dmesg

dmesg 是一个显示内核缓冲区系统控制信息的工具;比如系统在启动时的信息会写到/var/log/

注:dmesg 工具并不是专门用来查看硬件芯片组标识的工具,但通过这个工具能让我们知道机器中的硬件的一些参数;因为系统在启动的时候,会写一些硬件相关的日志到 /var/log/message* 或 /var/log/boot* 文件中;

如果我们用这个工具来查看一些硬件的信息;这个工具信息量太大,的确需要耐心;

[root@localhost beinan]# dmesg

[root@localhost beinan]# dmesg -c 注:清理掉缓冲区,下次开机的时候还会自动生成;


5、 hwbrowser

hwbrowser 是 您当前硬件配置的图形化浏览器 ,这个工具是图形的。可能系统在默认的情况下没有安装。需要您安装才行。在Fedora 4.0 中,如果能用yum 或apt 应该是通过如下的命令来安装;

[root@localhost beinan]# yum install hwbrowser

[root@localhost beinan]# apt install hwbrowser
[root@localhost beinan]# hwbrowser

当然您也可以通过rpmfind.net 或者freshrpms.net 上寻找rpm 包来安装

[root@localhost beinan]# rpm -ivh hwbrowser*.rpm

我建议您最好是通过软件包更新工具yum 和apt来安装,这样能自动解决依赖关系;


6、lshal 和 hal-device-manager

通过 lshal 和hal-device-manager 也能知道硬件相关信息,不过这个工具对新手操作起来是有点麻烦,但我还是得介绍一下;

[root@localhost beinan]# lshal

hwbrowser 是 lshal 的图形化界;可能系统在默认的情况下没有安装,这个工具包是Fedora 扩展包,需要您安装才行。在Fedora 4.0 中,如果能用yum 或apt 应该是通过如下的命令来安装;

[root@localhost beinan]# yum install hal-device-manager

[root@localhost beinan]# apt install hal-device-manager
[root@localhost beinan]# hal-device-manager

当然您也可以通过rpmfind.net 或者freshrpms.net 上寻找rpm 包来安装

[root@localhost beinan]# rpm -ivh hal-device-manager*.rpm

我建议您最好是通过软件包更新工具yum 和apt来安装,这样能自动解决依赖关系;


三、不同的硬件有不同的配置工具和与之相应的配置文件;

不同的硬件有不同的配置工具,也有与之相应的配置文件;比如关于显示器和显示卡的配置文件是/etc/X11/xorg.conf ,对于老的Linux版本应该是/etc/X11/X86Config 或 X86Config-4 ,xorg 或 X86的配置文件还包括鼠标、键盘等在X桌面环境下的配置和控制等;

声卡的配置文件是/etc/modprobe.conf 或 /etc/modules.conf ;

文件系统的配置文件是 /etc/fstab ;

声卡的配置工具,一般情况下是alsaconf

当然不同的发行版也有相应的硬件配置或管理 工具,比如Fedora Core 4.0 有如下的硬件配置或管理工具;

[root@localhost beinan]# system-config-mouse
[root@localhost beinan]# system-config-network-tui
[root@localhost beinan]# gnome-system-monitor
[root@localhost beinan]# system-config-network
[root@localhost beinan]# system-config-printer-gui
[root@localhost beinan]# system-config-soundcard
[root@localhost beinan]# setup

当然这些图形化的工具并不是万能的,他们的功能还是有极大的局限性;所以在硬件配置上,大多还是通过文本模式来操作的;


四、硬件驱动是由内核支持的,但驱动都存放在哪里?

硬件驱动是必须由内核支持的,无论是我们自己安装驱动,还是内核自带的驱动都是如此。硬件驱动如果是以内核模块支持的,驱动目录位于: /lib/modules/内核版本/kernel/目录 或 /lib/modules/内核版本/kernel/drivers 目录中;

[root@localhost beinan]# uname -r
2.6.11-1.1369_FC4
[root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/kernel
arch crypto drivers fs lib net sound

注:只有驱动在内核中以模块的方法支持的,或者我们自己安装的驱动,驱动才位于 /lib/modules/相应的目录;如果是直接置入内核的,不会出现在/lib/modules驱动相关的目录;


五、硬件不被系统支持怎么办?

如果一个Linux 系统不支持您的硬件,解决的办法无非是有两种,一种是下载驱动自己安装,Linux的驱动大多是开源社区开发的,厂商提供的比较少;有时也可能要重编内核,主要看驱动内部的说明文件怎么说了。因为驱动本来是要内核支持的,编译内核也极为正常;

值得注意的是:如果我们要重新编译内核,最好把硬件情况摸清楚了,比如鼠标、光驱、软驱、USB 设备;硬盘、文件系统... ... 都要仔细的查看;

请参考:


后记:

Linux 对硬件的支持目前的情况来看是要比前几年好多了,比如声卡、网卡、显示卡(非3D加速,如果是3D加速的,要下载厂商驱动,如果厂商不提供,那大多是没有办法了,因为厂商不公开硬件的相关参数,开源社区也没有办法开发,对不对?);对于有些硬件还是需要我们来自己安装驱动或编译内核来解决;

Linux对硬件的驱动的开发,开源社区是相当积极的,但厂商很少提供非Windows的驱动,大多数的Linux的驱动都是开源社区奉献的;有人可能会说Windows的硬件驱动最容易,但我不是这么认为,我有一声ISA接口的声卡,在windows 98 和winme 中发出怪声,在windows 2000更是没有驱动。但在Linux中却支持的非常好。 呵。。。

Linux 对硬件并不是大家原来所说的,越老越旧的硬件跑起来最好,Linux对新设备的支持,可能厂家刚放出来产品,开源社区就有人研究了。解决办法也会在开源社区可以找到;但有些硬件厂商不会提供驱动的开发参数、信息之类的,所以开源社区有时对这样的硬件也是无奈,但这样的设备目前看来是比较少;大多硬件都支持Linux ;

如果您遇到硬件相关的问题,不妨通过我上面所说的来找线索解决,就目前来看也没有太多的问题。只要仔细一点,细点心,学会用Google 搜索,大多问题还是能解决的。

相关文档:

1、《编译内核操作流程 ──为新手指南》
2、《内核管理概述》
3、《用ALSA驱动声卡流程详解》
4、《Fedora Core 4.0 HAL配置即插即用移动存储(USB及1394)的实践》
5、
《存储设备分区操作及文件系统管理概述》
6、《Fedora / Redhat 软件包管理指南》
7、《硬件相关网站收集》

- 作者: 东方之子 2007年01月9日, 星期二 13:10  回复(0) |  引用(0) 加入博采

php给上传图片加水印
<?php
/******************************************************************************

参数说明:
$max_file_size : 上传文件大小限制, 单位BYTE
$destination_folder : 上传文件路径
$watermark   : 是否附加水印(1为加水印,其他为不加水印);

使用说明:
1. 将PHP.INI文件里面的"extension=php_gd2.dll"一行前面的;号去掉,因为我们要用到GD库;
2. 将extension_dir =改为你的php_gd2.dll所在目录;
******************************************************************************/

//上传文件类型列表
$uptypes=array(
'image/jpg',
'image/jpeg',
'image/png',
'image/pjpeg',
'image/gif',
'image/bmp',
'image/x-png'
);

$max_file_size=2000000;   //上传文件大小限制, 单位BYTE
$destination_folder="uploadimg/"; //上传文件路径
$watermark=1;   //是否附加水印(1为加水印,其他为不加水印);
$watertype=1;   //水印类型(1为文字,2为图片)
$waterposition=1;   //水印位置(1为左下角,2为右下角,3为左上角,4为右上角,5为居中);
$waterstring="
http://www.xplore.cn/"; //水印字符串
$waterimg="xplore.gif";   //水印图片
$imgpreview=1;   //是否生成预览图(1为生成,其他为不生成);
$imgpreviewsize=1;   //缩略图比例
?>
<html>
<head>
<title>ZwelL图片上传程序</title>
<style type="text/css">
<!--
body
{
font-size: 9pt;
}
input
{
background-color: #66CCFF;
border: 1px inset #CCCCCC;
}
-->
</style>
</head>

<body>
<form enctype="multipart/form-data" method="post" name="upform">
上传文件:
<input name="upfile" type="file">
<input type="submit" value="上传"><br>
允许上传的文件类型为:<?=implode(', ',$uptypes)?>
</form>

<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
if (!is_uploaded_file($_FILES["upfile"][tmp_name]))
//是否存在文件
{
    echo "图片不存在!";
    exit;
}

$file = $_FILES["upfile"];
if($max_file_size < $file["size"])
//检查文件大小
{
  echo "文件太大!";
  exit;
}

if(!in_array($file["type"], $uptypes))
//检查文件类型
{
  echo "文件类型不符!".$file["type"];
  exit;
}

if(!file_exists($destination_folder))
{
  mkdir($destination_folder);
}

$filename=$file["tmp_name"];
$image_size = getimagesize($filename);
$pinfo=pathinfo($file["name"]);
$ftype=$pinfo['extension'];
$destination = $destination_folder.time().".".$ftype;
if (file_exists($destination) && $overwrite != true)
{
  echo "同名文件已经存在了";
  exit;
}

if(!move_uploaded_file ($filename, $destination))
{
  echo "移动文件出错";
  exit;
}

$pinfo=pathinfo($destination);
$fname=$pinfo[basename];
echo " <font color=red>已经成功上传</font><br>文件名: <font color=blue>".$destination_folder.$fname."</font><br>";
echo " 宽度:".$image_size[0];
echo " 长度:".$image_size[1];
echo "<br> 大小:".$file["size"]." bytes";

if($watermark==1)
{
  $iinfo=getimagesize($destination,$iinfo);
  $nimage=imagecreatetruecolor($image_size[0],$image_size[1]);
  $white=imagecolorallocate($nimage,255,255,255);
  $black=imagecolorallocate($nimage,0,0,0);
  $red=imagecolorallocate($nimage,255,0,0);
  imagefill($nimage,0,0,$white);
  switch ($iinfo[2])
  {
    case 1:
    $simage =imagecreatefromgif($destination);
    break;
    case 2:
    $simage =imagecreatefromjpeg($destination);
    break;
    case 3:
    $simage =imagecreatefrompng($destination);
    break;
    case 6:
    $simage =imagecreatefromwbmp($destination);
    break;
    default:
    die("不支持的文件类型");
    exit;
  }

  imagecopy($nimage,$simage,0,0,0,0,$image_size[0],$image_size[1]);
  imagefilledrectangle($nimage,1,$image_size[1]-15,80,$image_size[1],$white);

  switch($watertype)
  {
    case 1:   //加水印字符串
    imagestring($nimage,2,3,$image_size[1]-15,$waterstring,$black);
    break;
    case 2:   //加水印图片
    $simage1 =imagecreatefromgif("xplore.gif");
    imagecopy($nimage,$simage1,0,0,0,0,85,15);
    imagedestroy($simage1);
    break;
  }

  switch ($iinfo[2])
  {
    case 1:
    //imagegif($nimage, $destination);
    imagejpeg($nimage, $destination);
    break;
    case 2:
    imagejpeg($nimage, $destination);
    break;
    case 3:
    imagepng($nimage, $destination);
    break;
    case 6:
    imagewbmp($nimage, $destination);
    //imagejpeg($nimage, $destination);
    break;
  }

  //覆盖原上传文件
  imagedestroy($nimage);
  imagedestroy($simage);
}

if($imgpreview==1)
{
echo "<br>图片预览:<br>";
echo "<img src=\"".$destination."\" width=".($image_size[0]*$imgpreviewsize)." height=".($image_size[1]*$imgpreviewsize);
echo " alt=\"图片预览:\r文件名:".$destination."\r上传时间:\">";
}
}
?>
</body>
</html>

- 作者: 东方之子 2007年01月6日, 星期六 23:26  回复(0) |  引用(0) 加入博采

embed标签

embed
  (一)、基本语法:
  embed src=url
  说明:embed可以用来插入各种多媒体,格式可以是 Midi、Wav、AIFF、AU、MP3等等,
      Netscape及新版的IE 都支持。url为音频或视频文件及其路径,可以是相对路径或绝对路径。
  示例:<embed src="your.mid">

  (二)、属性设置:
  1、自动播放:
  语法:autostart=true、false
  说明:该属性规定音频或视频文件是否在下载完之后就自动播放。
  true:音乐文件在下载完之后自动播放;
  false:音乐文件在下载完之后不自动播放。
  示例:<embed src="your.mid" autostart=true>
  <embed src="your.mid" autostart=false>

  2、循环播放:
  语法:loop=正整数、true、false
  说明:该属性规定音频或视频文件是否循环及循环次数。
  属性值为正整数值时,音频或视频文件的循环次数与正整数值相同;
  属性值为true时,音频或视频文件循环;
  属性值为false时,音频或视频文件不循环。
  示例:<embed src="your.mid" autostart=true loop=2>
     <embed src="your.mid" autostart=true loop=true>
     <embed src="your.mid" autostart=true loop=false>

  3、面板显示:
  语法:hidden=ture、no
  说明:该属性规定控制面板是否显示,默认值为no。
  ture:隐藏面板;
  no:显示面板。
  示例:<embed src="your.mid" hidden=ture>
  <embed src="your.mid" hidden=no>

  4、开始时间:
  语法:starttime=mm:ss(分:秒)
  说明:该属性规定音频或视频文件开始播放的时间。未定义则从文件开头播放。
  示例:<embed src="your.mid" starttime="00:10">

  5、音量大小:
  语法:volume=0-100之间的整数
  说明:该属性规定音频或视频文件的音量大小。未定义则使用系统本身的设定。
  示例:<embed src="your.mid" volume="10">

  6、容器属性:
  语法:height=# width=#
  说明:取值为正整数或百分数,单位为像素。该属性规定控制面板的高度和宽度。
  height:控制面板的高度;
  width:控制面板的宽度。
  示例:<embed src="your.mid" height=200 width=200>

  7、容器单位:
  语法:units=pixels、en
  说明:该属性指定高和宽的单位为pixels或en。
  示例:<embed src="your.mid" units="pixels" height=200 width=200>
     <embed src="your.mid" units="en" height=200 width=200>

  8、外观设置:
  语法:controls=console、smallconsole、playbutton、pausebutton、stopbutton、
      volumelever 说明:该属性规定控制面板的外观。默认值是console。
  console:一般正常面板;
  smallconsole:较小的面板;
  playbutton:只显示播放按钮;
  pausebutton:只显示暂停按钮;
  stopbutton:只显示停止按钮;
  volumelever:只显示音量调节按钮。
  示例:<embed src="your.mid" controls=smallconsole>
     <embed src="your.mid" controls=volumelever>

  9、对象名称:
  语法:name=#
  说明:#为对象的名称。该属性给对象取名,以便其他对象利用。
  示例:<embed src="your.mid" name="sound1">

  10、说明文字:
  语法:title=#
  说明:#为说明的文字。该属性规定音频或视频文件的说明文字。
  示例:<embed src="your.mid" title="第一首歌">

  11、前景色和背景色:
  语法:palette=color|color
  说明:该属性表示嵌入的音频或视频文件的前景色和背景色,第一个值为前景色,第二个值为背景
      色,中间用 | 隔开。color可以是RGB色(RRGGBB)也可以是颜色名,还可以是transparent
     (透明)。 示例:<embed src="your.mid" palette="red|black">

  12、对齐方式:
  语法:align=top、bottom、center、baseline、 left、right、texttop、middle、
      absmiddle、absbottom
  说明:该属性规定控制面板和当前行中的对象的对齐方式。
  center:控制面板居中;
  left:控制面板居左;
  right:控制面板居右;
  top:控制面板的顶部与当前行中的最高对象的顶部对齐;
  bottom:控制面板的底部与当前行中的对象的基线对齐;
  baseline:控制面板的底部与文本的基线对齐;
  texttop:控制面板的顶部与当前行中的最高的文字顶部对齐;
  middle:控制面板的中间与当前行的基线对齐;
  absmiddle:控制面板的中间与当前文本或对象的中间对齐;
  absbottom:控制面板的底部与文字的底部对齐。
  示例:<embed src="your.mid" align=top>
     <embed src="your.mid" align=center>

- 作者: 东方之子 2007年01月5日, 星期五 22:46  回复(0) |  引用(0) 加入博采

中文字符集与字符编码

字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB 18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。

中文文字数目大,而且还分为简体中文和繁体中文两种不同书写规则的文字,而计算机最初是按英语单字节字符设计的,因此,对中文字符进行编码,是中文信息交流的技术基础。本文将按照字符集的时间顺序讨论几种典型的字符集,选取几种代表性的中文字符集,研究历史由来、特点、技术特征。


ASCII 字符集

1.名称的由来

ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是基于罗马字母表的一套电脑编码系统。

2.特点

它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO 646。

3.包含内容

控制字符:回车键、退格、换行键等。

可显示字符:英文大小写字符、阿拉伯数字和西文符号

4.技术特征

7位(bits)表示一个字符,共128字符

5.ASCII扩展字符集

7位编码的字符集只能支持128个字符,为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符。

ASCII扩展字符集比ASCII字符集扩充出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。

GB2312 字符集

 1.名称的由来

GB2312又称为GB2312-80字符集,全称为《信息交换用汉字编码字符集·基本集》,由原中国国家标准总局发布,1981年5月1日实施。

2.特点

GB2312是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。

3.包含内容

GB2312收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。其中包括6763个汉字,其中一级汉字3755个,二级汉字3008个;包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

4.技术特征

(1)分区表示:

GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。

各区包含的字符如下:01-09区为特殊符号;16-55区为一级汉字,按拼音排序;56-87区为二级汉字,按部首/笔画排序;10-15区及88-94区则未有编码。

(2)双字节表示

两个字节中前面的字节为第一字节,后面的字节为第二字节。习惯上称第一字节为“高字节” ,而称第二字节为“低字节”。

“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)。

5.编码举例

以GB2312字符集的第一个汉字“啊”字为例,它的区号16,位号01,则区位码是1601,在大多数计算机程序中,高字节和低字节分别加0xA0得到程序的汉字处理编码0xB0A1。计算公式是:0xB0=0xA0+16, 0xA1=0xA0+1。

BIG5 字符集

1.名称的由来

又称大五码或五大码,1984年由台湾财团法人信息工业策进会和五间软件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大众 (FIC)创立,故称大五码。

Big5码的产生,是因为当时台湾不同厂商各自推出不同的编码,如倚天码、IBM PS55、王安码等,彼此不能兼容;另一方面,台湾政府当时尚未推出官方的汉字编码,而中国大陆的GB2312编码亦未有收录繁体中文字。

2.特点

Big5字符集共收录13,053个中文字,该字符集在中国台湾使用。耐人寻味的是该字符集重复地收录了两个相同的字:“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。

3.字符编码方法

Big5码使用了双字节储存方法,以两个字节来编码一个字。第一个字节称为“高位字节”,第二个字节称为“低位字节”。高位字节的编码范围0xA1-0xF9,低位字节的编码范围0x40-0x7E及0xA1-0xFE。

各编码范围对应的字符类型如下:0xA140-0xA3BF为标点符号、希腊字母及特殊符号,另外于0xA259-0xA261,存放了双音节度量衡单位用字:兙兛兞兝兡兣嗧瓩糎;0xA440-0xC67E为常用汉字,先按笔划再按部首排序;0xC940-0xF9D5为次常用汉字,亦是先按笔划再按部首排序。

4.Big5 的局限性

尽管Big5码内包含一万多个字符,但是没有考虑社会上流通的人名、地名用字、方言用字、化学及生物科等用字,没有包含日文平假名及片假名字母。

例如台湾视“着”为“著”的异体字,故没有收录“着”字。康熙字典中的一些部首用字(如“亠”、“疒”、“辵”、“癶”等)、常见的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也没有收录到Big5之中。

GB18030 字符集

1.名称的由来

GB 18030的全称是GB18030-2000《信息交换用汉字编码字符集基本集的扩充》,是我国政府于2000年3月17日发布的新的汉字编码国家标准,2001年8月31日后在中国市场上发布的软件必须符合本标准

2.特点

GB 18030字符集标准的出台经过广泛参与和论证,来自国内外知名信息技术行业的公司,信息产业部和原国家质量技术监督局联合实施。

GB 18030字符集标准解决汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位,收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode 3.0版本兼容,填补Unicode扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编码标准(GB2312,GB13000.1)兼容。

3.编码方法

GB 18030标准采用单字节、双字节和四字节三种方式对字符编码。单字节部分使用0×00至0×7F码(对应于ASCII码的相应码)。双字节部分,首字节码从0×81至0×FE,尾字节码位分别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0×81308130到0×FE39FE39。其中第一、三个字节编码码位均为0×81至0×FE,第二、四个字节编码码位均为0×30至0×39。

4.包含的内容

双字节部分收录内容主要包括GB13000.1全部CJK汉字20902个、有关标点符号、表意文字描述符13个、增补的汉字和部首/构件80个、双字节编码的欧元符号等。  四字节部分收录了上述双字节字符之外的,包括CJK统一汉字扩充A在内的GB 13000.1中的全部字符。

Unicode字符集

1.名称的由来

Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字符集的简称,是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发,1994年正式公布,最新版本是2005年3月31日的Unicode 4.1.0。

2.特征

Unicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

3.编码方法

Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,例如字母“A”的编码为 004116 和字符“?”的编码为 20AC16。所以“A”的编码书写为“U+0041”。

4.UTF-8 编码
UTF-8是Unicode的其中一个使用方式。 UTF是 Unicode Translation Format,即把Unicode转做某种格式的意思。

UTF-8便于不同的计算机之间使用网络传输不同语言和编码的文字,使得双字节的Unicode能够在现存的处理单字节的系统上正确传输。

UTF-8使用可变长度字节来储存 Unicode字符,例如ASCII字母继续使用1字节储存,重音文字、希腊字母或西里尔字母等使用2字节来储存,而常用的汉字就要使用3字节。辅助平面字符则使用4字节。

5.UTF-16 和 UTF-32 编码
UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案,UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码;UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。

- 作者: 东方之子 2006年12月29日, 星期五 20:15  回复(0) |  引用(0) 加入博采

OGG格式详细全攻略

OGG格式详细全攻略

号称MP3杀手的Ogg Vorbis音乐格式,不但音质出众,而且完全免费、开源。现在,它离我们越来越近了。;解码芯片制造商美国Sigmatel公司也宣布在新一代的3600系列MP3解码芯片中增加对OGG格式的支持,加上先前韩国高端MP3对OGG格式的广泛支持,OGG这种先进的音乐格式已经呈现出燎原的趋势。
  相对于90年代发布的MP3格式, OGG格式的支持对于MP3数码音乐播放器来说有重要的意义:首先,数码音乐播放器的内存空间有限,而Q0(64Kbps码率)品质的OGG音乐格式的音质就能达到128Kbps码率MP3音乐格式的音质,能完全满足人们日常欣赏的要求,至少能节省1/2的存储空间。其次,Q10(500Kbps)品质的OGG格式的音质与无损的CD级WAV格式基本完全一致,而体积只有WAV的1/3左右,可以完全取代笨重传统的CD随身听。究竟什么是OGG格式?有什么特点?如何获得OGG格式的音乐文件?下面让我们仔细了解一下:
1.认识OGG

  Ogg是一种先进的有损的音频压缩技术,正式名称是Ogg Vorbis,是一种免费的开源音频格式。OGG编码格式远比90年代开发成功的MP3先进,它可以在相对较低的数据速率下实现比MP3更好的音质。此外,Ogg Vorbis支持VBR(可变比特率)和ABR(平均比特率)两种编码方式, Ogg还具有比特率缩放功能,可以不用重新编码便可调节文件的比特率。 OGG格式可以对所有声道进行编码,支持多声道模式,而不像MP3只能编码双声道。多声道音乐会带来更多临场感,欣赏电影和交响乐时更有优势,这场革命性的变化是MP3无法支持的。在而且未来人们对音质要求不断提高, Ogg的优势将更加明显。
2.如何制作OGG音乐格式文件
  OGG格式的音乐文件现在没有大规模普及,一般我们需要用CD唱片或网上下载的其它格式转换。先介绍一下Ogg编码的一些知识,Ogg的编码中的比特率选项主要有ABR、VBR和Quality三种,其实Ogg的比特率都是可变的,推荐使用设置简单Quality模式,能满足大多数人要求。
下面的列表是Quality的等级划分和对应的比特率:

    在千千静听中转换OGG格式的方法:把想转的歌曲加入到千千静听,在歌曲上右键点转换格式 - 输出格式中选命令行编码器1.0,点击“配置”-编码方案- Vorbis -q6 即Q为6- 确认后点击“立即转换”。

3.选择合适的OGG编码品质
  目前新一代的MP3播放器都增加了对OGG格式支持,比如说魅族的MINIPLAYER(支持OGG/Q-1~Q10)。如果你选购的是小容量版本,建议使用Q2和Q4品质的OGG。 Q2品质的歌曲文件的音质水平全面超过了128KBPS码率的MP3,而文件体积却还要下1/4以上,无疑是音质和体积的很好结合,适合绝大多树普通用户。事实上即使Q0品质的音质就超过了同样采用64Kbps码率的WMA格式,非常接近128KBPS码率的MP3,而64k的wma的音质根本无法达到128kmp3的水平。如果不是很挑剔音质的用户用Q0品质也完全没有任何问题。

  对于音质要求较高的朋友可以选择使用Q4品质的OGG,Q4品质的OGG文件体积与128K MP3相当,而音质超过了Lame压缩的192Kbps/VBR MP3,这一点对支持OGG的数码播放器用户很具有吸引力——同样的容量下你存储更多高音质歌曲。对于容量较高切对希望用数码播放器达到CD随身听音质的发烧友来说,Q10品质的OGG无疑是一个福音,Q10的OGG从频谱上看基本和WAV文件完全一致,而体积只有后者的1/3,一首4分钟的歌曲大约有10MB左右。
在支持OGG/Q10格式的数码音乐播放器诞生之前,很多注重音质的朋友对MP3格式并不感冒——即使普通人也能听出来无损的CD音轨和最高品质的320Kbps码率MP3的音质区别。想魅族的MINIPLAYER之类的新一代高音质MP3播放器配合OGG/Q10格式有完全取代CD随身听的实力。Q5、Q6音质也非常优秀,可以达到256Kbps MP3以上的音质水平,也是对音质和体积很好的折衷,可以根据个人需要自己选择。

总结:
  新一代OGG格式的流行,能以更低的码率和文件体积欣赏到音质更高的音乐歌曲,同时也使得数码随身听设备有了真正取代CD随身听的资本,非常值得我们期待。心动的朋友不妨赶紧体验一下,将自己喜好的CD转换成小巧方便的OGG格式,为自己打造HI-FI级的随身音乐世界。

- 作者: 东方之子 2006年12月17日, 星期日 00:29  回复(0) |  引用(0) 加入博采