灌溉梦想,记录脚步

青春

  所有的结局都已写好
  所有的泪水也都已起程
  却忽然忘了是怎么样的一个开始
  在那个古老的不在回来的夏日
  无论我如何地去追索
  年轻的你只如云影掠过
  而你微笑的面容极浅极浅
  逐渐隐没在日落后的群岚
  遂翻开那发黄的扉页
  命运将它装订地极为拙劣
  含着泪 我一读再读
  却不得不承认
  青春是一本太仓促的书
   —-1979.6.

  时光匆匆的脚步声
   –<青春>悟读
  一个人就是一本书,
  每个人都在用终生的墨汁著作自己.
  在太阳稍稍西向的时候,你放下了心爱的水仔笔,走出小小的写字间,面对渐而悠远的天空,垂下那颗既是情感又是智慧的头,以感伤的左耳和思辩的右耳倾听时光的优骏在你心的草原上敲响的阵阵蹄声。
  太阳是什么时候转过头顶的,这个最大的疏忽使你充满了不安,最耐心的你终于守不住耐心了,在水边,一粒寂寞的石子打向自己的少女时代,你的湖面荡起了层层的涟漪.
  不知从哪个时候起,作为远景的烟云从群山后面朴素地升起来,在原野上客观地弥散着.
  青春是什么时候黄的,自在的花朵是什么时候落的,树是怎么长高的,落叶是怎么发出叹息的.
  类似的念头你还有好多,这样的时刻你最孤寂;
  类似的情景你最软弱,这样的时刻你最无力;
  这样的时刻你完全失去了主张.
  成熟哪里去了,世故哪里去了,练达哪里去了,理智弯下腰后,情感自然站了上风.
  你感到抬眼就望到生命的尽头,就再也不感想下去了.
  你哭了,你向世界发出了哀求:
  让我再年轻一次吧,我会把青春的那一页装订地很好.你落下了泪,因为这不可能.
  此刻,你是幼稚的,幼稚地很可爱,象今天给我写来情书的那个女孩.

杨中科老师对于计算机专业相关迷惑的解答

  1、”it专业的学生太多了,而且就业压力很大”是吗?
  现在各个大学为了赚钱拼命扩招,所以不仅IT专业的学生人比较多,而且其他专业的学生人数也比较多,”僧多粥少”就通常意味着就业压力大。但是反过来看,现在很多IT企业都存在”人才荒”的问题,也就是很多企业都招不到合适的人才,我认识一些做IT人力资源方面工作的朋友,他们都普遍反映现在企业里很难招到合适的人才。初看起来很奇怪”每年有很多IT专业大学生毕业,很多都找不到工作”,而”企业每年都缺人,招不到合适的人才”,造成这种奇怪的”人才断层”现象的根本原因就是现在毕业生的素质明显下降了,大学招的人多造成以前没有能力上大学的人也能上大学了,大学招的人多也意味着教学资源平均下来降低了,所以教育质量也降低了,这些就造成了”学生需要工作,企业需要人”的这种状况。
  我接触过很多IT专业的毕业生,给我的第一感觉是很多人的专业水平太差了,毕业了竟然连计算机的一些基础概念都不了解,更不用说专业课、实践技能了,大学四年就是在浑浑噩噩中度过的。我也和一些大学的老师和一些企业的校园招聘人员接触过,他们讲了一个很有意思的现象:每年IT专业就业生里有20%的人根本找不到任何工作,有60%的人找到很一般的工作,而有20%的学生则找到非常好的工作。那20%找不到任何工作的人是在大学里浑浑噩噩的人,根本不学习,整天打游戏;另外20%找到好工作的人在大学期间把自己的学习安排的非常好,不仅把专业课学的比较好,而且不读死书,能把课本上的东西在实践中得到应用,还主动动手参与实际开发;另外60%的人则在大学期间很迷茫,被各种问题迷惑着,想学但是又不知道怎么学、学什么、该不该学,很快大学四年就在迷惑中度过。
  大部分学生都会落在这60%里,也就是找的工作很一般。像你这样有上进心的人肯定不会落在那20%的根本找不到工作的人这个区间里,但是却很容易因为迷茫落在那60%的区间里。其实要进入那20%找到好工作区间里也非常容易,这个问题我已经在如鹏论坛的其他帖子里论述了,我这里简单描述一下:首先要把专业课学好,因为有正规一点的企业(这里的”正规一点的企业”与大中型企业不划等号)在校园招聘的时候不是很在乎你会什么开发工具、做过什么项目,而是考察你的专业课的掌握水平和动手能力,你可以去如鹏论坛的”就业”板块去看一下那些企业校园招聘(注意是校园招聘)的笔试题。其次,要锻炼自己实际的开发技能,因为IT专业课都要求实际动手能力,比如学完了C语言就要自己学着用C语言写一些有用的东西。只要在大学期间好好学习、多动手,到毕业的时候不愁好工作,因为那些找到好工作的学生只是比那些找到非常一般工作的人多努力了一点而已。
  不要被那些”it专业的学生太多了,而且就业压力很大”的说法迷惑了,发出这样感叹的人都是那60%的人,那找到好工作的20%正努力工作并且偷着乐了,哪有时间来抱怨呢,呵呵。IT行业是一个朝阳产业,就业机会多多,而且高端职位也非常多,不愁找不到好工作。加油!
  2、”我还听说这个专业越年轻越吃香。工作到35已经是头了。”
  这个论调你也许刚刚听说,但是你听说的已经是老版本了,目前最新的版本是”IT专业是吃青春饭的,只能干到40岁”。在我十年前进入IT行业的时候就已经有这种说法了,当时的版本是”IT专业只能干到30岁”,五年前听到了”IT专业只能干到35岁”的论调,今年听到了最新的版本”IT专业只能干到40岁”,估计再过5年就该有”IT专业只能干到45岁”这种说法了,年年在升级呀。
  出现这种论调的根本原因是什么呢?大家想想,虽然四十年代末期已经出现了计算机了,但是IT行业真正的飞速发展是在八十年代末发展起来的,国内则还要相对晚几年。假设第一批IT行业从业人员是在1990年大学毕业的,那时候的他们22岁,到了2008年他们正好40岁。一个人在一个行业已经做了十几年了,有的做了主管,有的自己创业做老板,有的则做了架构师,有的则做了技术主管,而也有一些人还在低端岗位挣扎,由于在低端岗位需要比较强的精力,这些40岁的”老人”显然没有刚毕业20来岁的年轻人更有精力,因此很多企业就把这些”老人”给辞退了。由此就诞生了著名的”IT专业是吃青春饭”的理论。
  大家思考一下,不仅是IT行业,任何行业都存在高端职位和低端职位的区别,而任何人如果一辈子在低端职位的话绝不会有什么出息。机械行业比IT行业发展时间长多了,把这两个行业对比一下就能看出异同点。几十年前机械毕业的人有人做了机械行业公司的高管,有人在这个行业创业做了老板,有一些有经验的机械工程师被企业高薪返聘,当然也有一些人在机械行业的低端岗位混了一辈子碌碌无为,企业一改制就被光荣的”下岗”了。由此证明在任何行业,如果你想在一个行业长期发展一定不能一辈子做低端岗位,而应该向高端岗位发展。
  IT行业的高端岗位有如下几种:老板、企业高管、高级工程师等。无论是像哪个方向发展,都需要在IT行业有很深的造诣:做老板要有对这个行业有高屋建瓴的认识和前瞻性才能找到商机;做高管则要有一定的技术水平,能够统领一个比一个聪明工程师,否则没人愿意被你管理;做高级工程师则更需要有非常高深的技术水平,这样才有可能被企业”高薪返聘”,比如微软等公司都有很多架构师、技术总监级别的岗位被很多五六十岁的”老家伙”霸占着。
  所以不要被”IT专业是吃青春饭的”这种观念误导了,这个行业前景非常好,只要不碌碌无为,那么一定前途不可限量。
  3、电子信息工程专业的学生可不可以找到和传统行业贴近的工作
  计算机是一个工具,它的价值就体现在帮助其他行业提高工作效率上。比如会计行业引入计算机就能把财会数据用计算机管理起来;机械行业引入计算机才能实现设备的自动控制。因此IT专业一定是和某个传统行业贴近的。比如我有的朋友在一家医院做信息部主管,主管医院的信息化;有的朋友在服装企业做进销存管理的信息化等;我还碰到过一个人在快运公司做信息化,因为在信息化管理过程中对公司的整体运营非常了解,后来做了业务主管。

使用mysqldump备份与恢复数据库实例

  备份MySQL数据库的命令
  mysqldump -hhostname -uusername -ppassword databasename > backupfile.sql
  备份MySQL数据库为带删除表的格式,能够让该备份覆盖已有数据库而不需要手动删除原有数据库。
  mysqldump –add-drop-table -uusername -ppassword databasename > backupfile.sql
  直接将MySQL数据库压缩备份
  mysqldump -hhostname -uusername -ppassword databasename | gzip > backupfile.sql.gz
  备份MySQL数据库某个(些)表
  mysqldump -hhostname -uusername -ppassword databasename specific_table1 specific_table2 > backupfile.sql
  同时备份多个MySQL数据库
  mysqldump -hhostname -uusername -ppassword -databases databasename1 databasename2 databasename3 > multibackupfile.sql
  仅仅备份数据库结构
  mysqldump -no-data -databases databasename1 databasename2 databasename3 > structurebackupfile.sql
  备份服务器上所有数据库
  mysqldump -all-databases > allbackupfile.sql
  还原MySQL数据库的命令
  mysql -hhostname -uusername -ppassword databasename < backupfile.sql
  还原压缩的MySQL数据库
  gunzip < backupfile.sql.gz | mysql -uusername -ppassword databasename
  将数据库转移到新服务器
  mysqldump -uusername -ppassword databasename | mysql -host=*.*.*.* -C databasename

Crontab实现定时任务

  Crontab是一个很方便的在unix/linux系统上定时(循环)执行某个任务的程序
  使用cron服务,用 service crond status 查看 cron服务状态,如果没有启动则 service crond start启动它,
  cron服务是一个定时执行的服务,可以通过crontab 命令添加或者编辑需要定时执行的任务:
  crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数
  crontab -l //列出某个用户cron服务的详细内容
  crontab -r //删除没个用户的cron服务
  crontab -e //编辑某个用户的cron服务
  比如说root查看自己的cron设置:crontab -u root -l 再例如,root想删除fred的cron设置:crontab -u fred -r 在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e 进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt 编辑/etc/crontab文件,在末尾加上一行: 30 5 * * * root init 6 这样就将系统配置为了每天早上5点30自动重新启动。
  需要将crond设置为系统启动后自动启动的服务,可以在/etc/rc.d/rc.local 中,在末尾加上
  service crond start 如果还需要在系统启动十加载其他服务,可以继续加上其他服务的启动命令。
  比如: service mysqld start 基本用法: 1. crontab -l 列出当前的crontab任务
  2. crontab -d 删除当前的crontab任务
  3. crontab -e (solaris5.8上面是 crontab -r) 编辑一个crontab任务,ctrl_D结束
  4. crontab filename 以filename做为crontab的任务列表文件并载入
  crontab file的格式: crontab 文件中的行由 6 个字段组成,不同字段间用空格或 tab 键分隔。前 5 个字段指定命令要运行的时间
  分钟 (0-59) 小时 (0-23) 日期 (1-31) 月份 (1-12) 星期几(0-6,其中 0 代表星期日)
  第 6 个字段是一个要在适当时间执行的字符串
  例子: #MIN HOUR DAY MONTH DAYOFWEEK COMMAND #每天早上6点10分
  10 6 * * * date #每两个小时
  0 */2 * * * date (solaris 5.8似乎不支持此种写法) #晚上11点到早上8点之间每两个小时,早上8点
  0 23-7/2,8 * * * date #每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
  0 11 4 * mon-wed date #1月份日早上4点
  0 4 1 jan * date 补充:在使用crontab的时候,要特别注意的是运行脚本中能够访问到的环境变量和当前测试环境中的环境变量未必一致,一个比较保险的做法是在运行的脚本程序中自行设置环境变量(export) (1)先建一个文件crond.txt如下, 每天早上5点36分重新启动
  36 5 * * * reboot (2)上传到/opt目录
  (3)运行命令
  crontab /opt/crond.txt crontab -l 让配置文件生效:如果让配置文件生效,还得重新启动cron,切记,既然每个用户下的cron配置文件修改后。也要重新启动cron服务器。
  在Fedora 和Redhat中,我们应该用;
  [root@localhost ~]# /etc/init.d/crond restart 如果让crond 在开机时运行,应该改变其运行级别;
  [root@localhost ~]# chkconfig –levels 35 crond on service crond status 查看 cron服务状态,如果没有启动则 service crond start启动它, cron服务是一个定时执行的服务,可以通过crontab 命令添加或者编辑需要定时执行的任务
  Crontab文件的每一行由六个域(minutes、hours、day of month、month、day of week、 command)组 成,域之间用空格或Tab分开,其中:
  minutes: 分钟域,值的范围是0到59 hours: 小时域,值的范围是0到23 day of month: 日期,值的范围是1到31 month: 月份,值的范围是1到12 day of week: 星期,值的范围是0到6,星期日值为0 command: 所要运行的命令
  如果一个域是*,表明命令可以在该域所有可能的取值范围内执行。
  如果一个域是由连字符隔开的两个数字,表明命令可以在两个数字之间的范围内执行(包括两个数字 本身)。
  如果一个域是由逗号隔开的一系列值组成的,表明命令可以在这些值组成的范围内执行。
  如果日期域和星期域都有值,则这两个域都有效。
  编写一个文件,用以启动自动备份进程。
  cd /opt touch reboot.txt 在reboot.txt中添加一下内容: 0 4 * * * reboot crontab /opt/reboot.txt 用crontab -e编辑定时操作,例如加入下行命令:
  用crontab -l命令来查看
  注意:需要启动服务(添加在rc.local中) 重启crond任务
  /etc/init.d/cron restart (ubuntu下) 第一种 在Fedora或Redhat 等以RPM包管理的系统中;
  [root@localhost ~]# /etc/init.d/crond start [root@localhost ~]# /etc/init.d/crond stop [root@localhost ~]# /etc/init.d/crond restart /etc/rc.d/init.d/crond restart 命令简介
  crontab-操作每个用户的守护程序和该执行的时间表。
  部分参数说明
  crontab file [-u user]-用指定的文件替代目前的crontab。
  crontab-[-u user]-用标准输入替代目前的crontab. crontab-1[user]-列出用户目前的crontab. crontab-e[user]-编辑用户目前的crontab. crontab-d[user]-删除用户目前的crontab. crontab-c dir- 指定crontab的目录。
  crontab文件的格式:M H D m d cmd. M: 分钟(0-59)。
  H:小时(0-23)。
  D:天(1-31)。
  m: 月(1-12)。
  d: 一星期内的天(0~6,0为星期天)。
  cmd要运行的程序,程序被送入sh执行,这个shell只有USER,HOME,SHELL这三个环境变量。
  下面是一个例子文件:
  #MIN HOUR DAY MONTH DAYOFWEEK COMMAND
  #每天早上6点
  106* * * date
  #每两个小时
  0*/2* * * date
  #晚上11点到早上8点之间每两个小时,早上部点
  0 23-7/2,8* * * date
  #每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
  0 11 4* mon-wed date
  #1月份日早上4点
  0 4 1 jan* date
  范例
  lark:~>crontab-1 列出用户目前的crontab.
  #MIN HOUR DAY MONTH DAYOFWEEK COMMAND
  10 6* * * date
  0*/2* * * date
  0 23-7/2,8 * * * date

 

Robots.txt 文件示例

  robots.txt 文件对抓取网络的搜索引擎漫游器(称为漫游器)进行限制。这些漫游器是自动的,在它们访问网页前会查看是否存在限制其访问特定网页的 robots.txt 文件。如果你想保护网站上的某些内容不被搜索引擎收入的话,robots.txt 是一个简单有效的工具。这里简单介绍一下怎么使用它。
  如何放置 Robots.txt 文件
  robots.txt自身是一个文本文件。它必须位于域名的根目录中并 被命名为”robots.txt”。位于子目录中的 robots.txt 文件无效,因为漫游器只在域名的根目录中查找此文件。例如,http://www.example.com/robots.txt 是有效位置,http://www.example.com/mysite/robots.txt 则不是。
  这里举一个robots.txt的例子:
  User-agent: *
  Disallow: /cgi-bin/
  Disallow: /tmp/
  Disallow: /~name/

  使用 robots.txt 文件拦截或删除整个网站
  要从搜索引擎中删除您的网站,并防止所有漫游器在以后抓取您的网站,请将以下 robots.txt 文件放入您服务器的根目录:
  User-agent: *
  Disallow: /
  要只从 Google 中删除您的网站,并只是防止 Googlebot 将来抓取您的网站,请将以下 robots.txt 文件放入您服务器的根目录:
  User-agent: Googlebot
  Disallow: /

  每个端口都应有自己的 robots.txt 文件。尤其是您通过 http 和 https 托管内容的时候,这些协议都需要有各自的 robots.txt 文件。例如,要让 Googlebot 只为所有的 http 网页而不为 https 网页编制索引,应使用下面的 robots.txt 文件。
  对于 http 协议 (http://yourserver.com/robots.txt):
  User-agent: *
  Allow: /

  对于 https 协议 (https://yourserver.com/robots.txt):
  User-agent: *
  Disallow: /

  允许所有的漫游器访问您的网页
  User-agent: *
  Disallow:

  (另一种方法: 建立一个空的 “/robots.txt” 文件, 或者不使用robot.txt。)
  使用 robots.txt 文件拦截或删除网页
  您可以使用 robots.txt 文件来阻止 Googlebot 抓取您网站上的网页。 例如,如果您正在手动创建 robots.txt 文件以阻止 Googlebot 抓取某一特定目录下(例如,private)的所有网页,可使用以下 robots.txt 条目:
  User-agent: Googlebot
  Disallow: /private

  要阻止 Googlebot 抓取特定文件类型(例如,.gif)的所有文件,可使用以下 robots.txt 条目:
  User-agent: Googlebot
  Disallow: /*.gif$

  要阻止 Googlebot 抓取所有包含 ? 的网址(具体地说,这种网址以您的域名开头,后接任意字符串,然后是问号,而后又是任意字符串),可使用以下条目:
  User-agent: Googlebot
  Disallow: /*?

  尽管我们不抓取被 robots.txt 拦截的网页内容或为其编制索引,但如果我们在网络上的其他网页中发现这些内容,我们仍然会抓取其网址并编制索引。因此,网页网址及其他公开的信息,例如指 向该网站的链接中的定位文字,有可能会出现在 Google 搜索结果中。不过,您网页上的内容不会被抓取、编制索引和显示。
  作为网站管理员工具的一部分,Google提供了robots.txt分析工具 。它可以按照 Googlebot 读取 robots.txt 文件的相同方式读取该文件,并且可为 Google user-agents(如 Googlebot)提供结果。我们强烈建议您使用它。 在创建一个 robots.txt 文件之前,有必要考虑一下哪些内容可以被用户搜得到,而哪些则不应该被搜得到。 这样的话,通过合理地使用 robots.txt , 搜索引擎在把用户带到您网站的同时,又能保证隐私信息不被收录。

RAID 5单个硬盘损坏解决办法

设备环境为:HP-DL380-G5,用四个500G的sata盘做的raid5,在一次突然断电之后不久,有一块硬盘亮红灯,基本判断为已经掉线。咨询HP-800要求先备份数据,而后重启检查,但是服务器跑的是虚拟化,单个文件最大在128G以上,没有vcent授权无法迁移,所以800建议等于废话。
采取的办法是:关机,把坏掉的盘撤掉,换上同型号同容量的硬盘,开机,会有个提示:F1(重建raid覆盖现有信息),F2(重建raid保留现有信息),选择F1,启动,没有出现异常。

nash和initrd.img分析

  nash仅仅是作为initrd.img当中加载驱动所使用的命令解释器而已,并没有对initrd.img当中的linuxrc脚本作一个深入的了解。Redhat ES3当中的initrd.img内容如下:
  #!/bin/nash
  echo “Loading scsi_mod.o module”
  insmod /lib/scsi_mod.o
  echo “Loading sd_mod.o module”
  insmod /lib/sd_mod.o
  echo “Loading libata.o module”
  insmod /lib/libata.o
  echo “Loading ata_piix.o module”
  insmod /lib/ata_piix.o
  echo “Loading jbd.o module”
  insmod /lib/jbd.o
  echo “Loading ext3.o module”
  insmod /lib/ext3.o
  echo Mounting /proc filesystem
  mount -t proc /proc /proc
  echo Creating block devices
  mkdevices /dev
  echo Creating root device
  mkrootdev /dev/root
  echo 0x0100 > /proc/sys/kernel/real-root-dev
  echo Mounting root filesystem
  mount -o defaults –ro -t ext3 /dev/root /sysroot
  pivot_root /sysroot /sysroot/initrd
  umount /initrd/proc

  前面是加载驱动部分,而后面是什么用处,就没有深究了。而我自己用的虚拟机里通常会把驱动和文件系统支持编译到内核,也压根用不着initrd.img,所以把这个宝矿放了过去。今天几个学生在Redhat 9的基础上升级内核到2.6.19,并且是驱动、文件系统用模块方式支持,终于出了问题。该来的还是要来的,应了那句话”出来混,迟早都是要还的”。学生们把前面的硬盘驱动、文件系统驱动都替换成2.6的模块,后半部分在我的误导下删除(当然没有删除的也多半没有成功),结果死活不能进入系统,报无法挂载根文件系统的kernel panic错误。查了半天,发现所有的驱动都加载正常,即便是在linuxrc当中加入bash获得一个shell,检查设备和文件系统的状况也都是正常,可就是提示找不到根文件系统。
  开始引起我注意的是,通常在硬盘驱动和文件系统支持都完备的情况下它并没有提示说VFS的root=xxxx错误,而直接提示的”VFS: Unable to mount root fs on (0, 0)”。这意味着它并未识别在grub.conf当中传递给kernel的root=/dev/xxx参数,因为Linux的设备主设备号是不会为0的。我曾怀疑root=参数没有被接受,但却注意到”Please append a correct “root=” boot option”的提示。
  为了找出问题,我在linuxrc中用bash取得了一个shell,然后挂载proc文件系统后检查/proc/sys/kernel/real_root_dev,发现其值为0。这说明kernel得到的真实root文件系统的设备号不正确(当然有例外,注意后面的解释)。我试着把正确的设备值(例如/dev/sda2用0x802)写入,退出bash之后启动果然正常了。这说明kernel解析参数root=/dev/xxx出现了错误。
  经过核对内核代码,发现kernel确实从root=这个参数传递中获得真实的根文件系统的位置,但是这些/dev/xxx会被转换成内核可识别的设备表示形式。转换的过程中内核会试图检查传递进来的/dev/xxx设备是否存在,而这一步是kernel初始化过程中完成的。当我们把硬盘驱动编译为模块时,kernel初始化过程中硬盘尚不能被识别(要等到kernel初始化完,使用initrd.img才能加载硬盘驱动),于是真实根文件系统的设备号就不能被正确转换,使得其保留为初始值0。
  那对于使用硬盘驱动的情况下如何解决这个问题呢?那就是initrd.img后半部分的工作。在加载完硬盘驱动后,脚本会用mkrootdev生成设备/dev/root,通过man nash你会发现这个命令的作用是根据内核传递参数当中的root=来创建对应该设备的节点,节点名就是/dev/root。之后它会把这个设备挂载到/sysroot这个位置,然后用pivot_root这个根交换的命令把真正运行的根文件系统切换到/sysroot之下,而运行linuxrc的initrd的文件系统将被挂载到真正的根系统下的initrd目录。至于”echo 0x0100 > /proc/sys/kernel/real-root-dev”这个命令,看起来是告诉内核真正的文件系统是/dev/ram0,其实是利用内核判断使用/dev/ram0为根文件系统时不再mount其他设备作为根文件系统的分支,作了一个小小的技巧骗过内核。
  整个脚本的关键在于mkrootdev这个命令。它不仅能够根据root=/dev/xxx来生成对应的设备节点,还能够在碰到root=LABEL=/的情况下探测所有的硬盘分区,以便找到对应着卷标为/的分区。这也解开了我一直没弄清楚的为什么root=LABEL=xxx的参数有些环境可以用而有些却不行的谜团。这个LABEL=/的解析根本不是内核完成的,而是initrd.img当中linuxrc脚本的mkrootdev命令来完成的。脚本的第二个关键在于它负责完成了本是由内核做的挂载真实根文件系统的动作,并对当前根(即initrd使用的内存文件系统)和真实根文件系统进行根切换,又利用欺骗让内核误认为当前使用/dev/ram0作为根文件系统可以不再挂载真实的根文件系统,可谓用心良苦啊 ^_^
  当然,如果完全不用initrd.img的机制,你会发现/proc/sys/kernel/real_root_dev的值也是0。这并不是内核也弄错了,而是只有在使用initrd.img机制时,real_root_dev才反映了内核中记录的真实根文件系统的值,虽然它不一定准确。
  最后,总结一下:
  1、当硬盘驱动以模块形式提供时root=xxx传递给内核的参数可能不会直接起作用,内核在检查这个参数时可能会发现这个设备(因为没有加载驱动而)不存在,因此导致内核没有接受root=xxx的参数。
  2、在这种情况下,initrd.img机制的作用不单单是加载驱动这么简单,还肩负着把正确的真实根的设备位置告知内核的艰巨任务。不过实现的方法有两种:
  2.1 把正确的根设备号写入/proc/sys/kernel/real_root_dev,或者
  2.2 自己挂载真正的根设备,并进行根交换把根系统切换到真实的根系统上,还要阻止内核去挂载它认为的真实根系统
  对于2.2,挂载真正的根系统用nash解释器的内置命令mkrootdev完成,它可以根据传递给kernel的参数(估计读了/proc/cmdline)获得/dev/xxx的字符串,或者得到LABEL=xxx的字符串后查询各个分区的卷标来得到对应的真实根设备号。
  3、如果没有使用initrd.img的机制,/proc/sys/kernel/real_root_dev的值没有任何处理,因为它只有在调用initrd.img的时候才会被同步于内核中的操作对象。
  另外,redhat 9所带的nash解释器(版本3.4.42)在处理mkrootdev的流程上是有bug的。如果传给kernel的参数使用root=/dev/xxx的形式,那么nash会从/proc/sys/kernel/real_root_dev里获取用户想使用的真实根文件系统位置,显然这在我们上面的分析当中是0,也就是错误的;而如果参数传递是root=LABEL=/的形式,那么nash的处理走的另外一个分支,它会通过解析所有分区的卷标来查找所要的真实根文件系统,并不再查询/proc/sys/kernel/real_root_dev,这倒让我们可以得到正确的结果。bug呀bug。
  不过FC6所带的nash 5.1.19已经完全不是这个流程了,应当不存在这样的bug。