cgweb 回复于:2003-09-03 10:39:34 |
[size=18:f99ca3b6da][color=red:f99ca3b6da][b:f99ca3b6da]Linux开机启动程序详解[/b:f99ca3b6da][/color:f99ca3b6da][/size:f99ca3b6da] 由于操作系统正在变得越来越复杂,所以开机引导和关机下电的过程也越来越智能化。从简单的DOS系统转移到Windows NT系统,人们已经亲身感受到了这些变化——这已不仅仅是核心操作系统的启动引导和关闭了,还包括必须要同时启动或者关闭相当数量的服务项目。类似于Windows NT,Linux系统启动过程需要打开的服务项目也是数量极大的。 这里,我们假设大家已经熟悉其它操作系统的引导过程,了解硬件的自检引导步骤,就只从Linux操作系统的引导加载程序(对个人电脑而言通常是LILO)开始,介绍Linux开机引导的步骤。 加载内核 LILO启动之后,如果你选择了Linux作为准备引导的操作系统,第一个被加载的东西就是内核。请记住此时的计算机内存中还不存在任何操作系统,PC(因为它们天然的设计缺陷)也还没有办法存取机器上全部的内存。因此,内核就必须完整地加载到可用RAM的第一个兆字节之内。为了实现这个目的,内核是被压缩了的。这个文件的头部包含着必要的代码,先设置CPU进入安全模式(以此解除内存限制),再对内核的剩余部分进行解压缩。 执行内核 内核在内存中解压缩之后,就可以开始运行了。此时的内核只知道它本身内建的各种功能,也就是说被编译为模块的内核部分还不能使用。最基本的是,内核必须有足够的代码设置自己的虚拟内存子系统和根文件系统(通常就是ext2文件系统)。一旦内核启动运行,对硬件的检测就会决定需要对哪些设备驱动程序进行初始化。从这里开始,内核就能够挂装根文件系统(这个过程类似于Windows识别并存取C盘的过程)。内核挂装了根文件系统之后,将启动并运行一个叫做init的程序。 注意:在这里我们故意略去了Linux内核启动的许多细节,这些细节只有内核开发人员才感兴趣。如果你好奇的话,可以访问http://www.redhat.com:8080地址处的 “Kernel Hackers Guide”。 init进程 init进程是非内核进程中第一个被启动运行的,因此它的进程编号PID的值总是1。init读它的配置文件/etc/inittab,决定需要启动的运行级别(Runlevel)。从根本上说,运行级别规定了整个系统的行为,每个级别(分别由0到6的整数表示)满足特定的目的。如果定义了initdefault级别,这个值就直接被选中,否则需要由用户输入一个代表运行级别的数值。 输入代表运行级别的数字之后,init根据/etc/inittab文件中的定义执行一个命令脚本程序。缺省的运行级别取决于安装阶段对登录程序的选择:是使用基于文本的,还是使用基于X-Window的登录程序。 rc命令脚本程序 我们已经知道,当运行级别发生改变时,将由/etc/inittab文件定义需要运行哪一个命令脚本程序。这些命令脚本程序负责启动或者停止该运行级别特定的各种服务。由于需要管理的服务数量很多,因此需要使用rc命令脚本程序。其中,最主要的一个是/etc/rc.d/rc,它负责为每一个运行级别按照正确的顺序调用相应的命令脚本程序。我们可以想象,这样一个命令脚本程序很容易变得难以控制!为了防止这类事件的发生,需要使用精心设计的方案。 对每一个运行级别来说,在/etc/rc.d子目录中都有一个对应的下级目录。这些运行级别的下级子目录的命名方法是rcX.d,其中的X就是代表运行级别的数字。比如说,运行级别3的全部命令脚本程序都保存在/etc/rc.d/rc3.d子目录中。 在各个运行级别的子目录中,都建立有到/etc/rc.d/init.d子目录中命令脚本程序的符号链接,但是,这些符号链接并不使用命令脚本程序在/etc/rc.d/init.d子目录中原来的名字。如果命令脚本程序是用来启动一个服务的,其符号链接的名字就以字母S打头;如果命令脚本程序是用来关闭一个服务的,其符号链接的名字就以字母K打头。 许多情况下,这些命令脚本程序的执行顺序都很重要。如果没有先配置网络接口,就没有办法使用DNS服务解析主机名!为了安排它们的执行顺序,在字母S或者K的后面紧跟着一个两位数字,数值小的在数值大的前面执行。比如:/etc/rc.d/rc3.d/S50inet就会在/etc/rc.d/rc3.d/S55named之前执行(S50inet配置网络设置,S55named启动DNS服务器)。 存放在/etc/rc.d/init.d子目录中的、被符号链接上的命令脚本程序是真正的实干家,是它们完成了启动或者停止各种服务的操作过程。当/etc/rc.d/rc运行通过每个特定的运行级别子目录的时候,它会根据数字的顺序依次调用各个命令脚本程序执行。它先运行以字母K打头的命令脚本程序,然后再运行以字母S打头的命令脚本程序。对以字母K打头的命令脚本程序来说,会传递Stop参数;类似地对以字母S打头的命令脚本程序来说,会传递Start参数。 编写自己的rc命令脚本 在维护Linux系统运转的日子里,肯定会遇到需要系统管理员对开机或者关机命令脚本进行修改的情况。有两种方法可以用来实现修改的目的: ● 如果所做的修改只在引导开机的时候起作用,并且改动不大的话,可以考虑简单地编辑一下/etc/rc.d/rc.local脚本。这个命令脚本程序是在引导过程的最后一步被执行的。 ● 如果所做的修改比较细致,或者还要求关闭进程使之明确地停止运行,则需要在/etc/rc.d/init.d子目录中添加一个命令脚本程序。这个命令脚本程序必须可以接受Start和Stop参数并完成相应的操作。 第一种方法,编辑/etc/rc.d/rc.local脚本,当然是两种方法中比较简单的。如果想在这个命令脚本程序中添加内容,只需要使用喜欢的编辑器程序打开它,再把打算执行的命令附加到文件的末尾就可以了。这对一两行的修改来说的确很便利。 如果确实需要使用一个命令脚本程序,这时必须选择第二个方法。编写一个rc命令脚本程序的过程并不像想象中那么困难。我们下面就给出一个例子,看看它是怎样实现的(顺便说一句,你可以把我们的例子当作范本,按照自己的需要进行修改和添加)。 假设你打算每隔60分钟调用一个特殊的程序来弹出一条消息,提醒自己需要从键盘前面离开休息一会儿,命令脚本程序将包括下面几个部分: ● 关于这个命令脚本程序功能的说明(这样就不会在一年之后忘记它); ● 在试图运行它之前验证这个命令脚本程序确实存在; ● 接受start和stop参数并执行要求的动作。 参数给定后,我们就可以编写命令的脚本程序。这个程序很简单,大家可以自己编写一下,我在这里就不给出了。 编写好新的命令脚本程序之后,再从相关的运行级别子目录中加上必要的符号链接,来控制这个命令脚本程序的启动或者停止。在我的印象中,只想让它在运行级别3或者运行级别5中启动,原因是我认为只有这两个运行级别才是日常工作的地方。最后,希望这个命令脚本程序在进入运行级别6(重启动)的时候被关闭。 激活或者禁止服务项目 有的时候会发现,在引导的时候并不需要某个特定的服务被启动。如果你正在考虑使用Linux替换Windows NT的文件和打印服务器,就更是如此。 我们已经知道,在特定的运行级别子目录中给符号链接改个名称,就可以让该服务不被启动,如把其名称的第一个字母由S改为K。一旦熟练掌握了命令行和符号链接,就会发现这是激活或者禁止服务的最快办法。 在学习这个改名方法的时候,可能会觉得图形化的操作界面ksysv比较容易掌握。虽然它原来是设计使用在KDE环境里的,但在Red Hat Linux 7.2下缺省安装的GNOME环境里也运行得很好。如果想启动它,只需简单地打开一个xterm窗口,并输入ksysv命令就可以了。屏幕上会出现一个窗口,其中列出了能够修改的全部参数,需要时还包括在线帮助。 警告:如果是在一个现实中的系统上学习本文的知识,要多多运用常识。当试着对启动脚本程序进行修改的时候,要记住所做的修改可能会造成你的系统不能正常工作,而且无法采用重启动的方法恢复。不要在正常运转的系统上实验新的设置,对你准备修改的文件要全部进行备份。最重要的是,在手边要准备一张引导盘以防不测。 |
colourp 回复于:2003-09-03 10:49:28 |
多谢了.....这个文章真好~~!!! |
cgweb 回复于:2003-09-03 10:54:02 |
别客气, 以前,前辈也是这样帮我的. |
itjane 回复于:2003-12-26 16:42:35 |
這是優先級別吧,比哪說如果local和init中同時都有的 |
magyma 回复于:2005-04-01 21:39:52 |
very good! I like!! |
JohnBull 回复于:2005-04-01 21:56:47 |
init会先调用rc.sysinit(初始化主机名、时区、键盘、console字体、....) 然后切换运行级,运行级切换的最后运行rc.local。 然后fork出getty(显示出“Login:”) ... |
寂寞烈火 回复于:2005-04-01 22:17:43 |
[img:e2fe25c754]http://blog.chinaunix.net/resserver.php?blogId=126&resource=1365-boot.jpg[/img:e2fe25c754] |
JohnBull 回复于:2005-04-01 22:59:07 |
[quote:a427dff0ac="寂寞烈火"][/quote:a427dff0ac] 此图有误。 应该是 [code:1:a427dff0ac] mingetty ----(exec)-----> login ------(exec)------> shell [/code:1:a427dff0ac] 并没有login回到mingetty这个过程。 |
wangyih 回复于:2005-04-01 23:07:46 |
应该有login回到mingetty这个过程 |
JohnBull 回复于:2005-04-01 23:25:44 |
[quote:7aa01ed375="wangyih"]应该有login回到mingetty这个过程[/quote:7aa01ed375] 看我的图! mingetty已经exec成login了,login又exec成shell了。 没有返回的过程。 不信ps axf看看 |
wangyih 回复于:2005-04-01 23:32:08 |
[quote:6422c30274="JohnBull"] 看我的图! mingetty已经exec成login了,login又exec成shell了。 没有返回的过程。 不信ps axf看看[/quote:6422c30274] LOGIN不成功会回到tty |
JohnBull 回复于:2005-04-01 23:36:03 |
[quote:468ce5d543="wangyih"] LOGIN不成功会回到tty[/quote:468ce5d543] 谬误! 1. 不成功会出来shell吗? 2. 不成功的话login会exit,然后init会根据inittab的respawn属性重新再生出另一个getty来。 不信自己ps ax看看前后两个getty的pid是不是不一样。 |
wangyih 回复于:2005-04-01 23:57:53 |
[quote:7ee1b58848="JohnBull"] 谬误! 1. 不成功会出来shell吗? 2. 不成功的话login会exit,然后init会根据inittab的respawn属性重新再生出另一个getty来。 不信自己ps ax看看前后两个getty的pid是不是不一样。[/quote:7ee1b58848] 我倒是真那不准了。 不过如果login都已经exit了,象您说的mingetty ----(exec)-----> login ------(exec)------> shell ,整个进程(这些连续的exec下来的)都结束了。 整个客户端与服务器都断了,就算init再搞出tty来客户端那还看的到 |
JohnBull 回复于:2005-04-02 00:19:26 |
[quote:2b276c64b5="wangyih"] 不过如果login都已经exit了,象您说的mingetty ----(exec)-----> login ------(exec)------> shell ,整个进程(这些连续的exec下来的)都结束了。 整个客户端与服务器都断了,就算init再搞出tty来客户端那还看的到[/quote:2b276c64b5] 首先,在终端这里不存在客户机/服务器的概念。终端不过是一个设备而已,open()一下就能用了。 看看inittab [code:1:2b276c64b5] ... 1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2 ... [/code:1:2b276c64b5] 意思是:“在第2,3,4,5运行级下,再生式保持mingetty进程” 后面的参数tty?就是要打开的虚终端设备。 respawn就是说如果发现退出了就再fork+exec一个新的出来。 |
wangyih 回复于:2005-04-02 00:35:53 |
[quote:cfb20c33ba="JohnBull"]意思是:“在第2,3,4,5运行级下,再生式保持mingetty进程” 后面的参数tty?就是要打开的虚终端设备。 respawn就是说如果发现退出了就再fork+exec一个新的出来。[/quote:cfb20c33ba] 本机登陆只是一种。还有 运行级别为5的图形方式登陆 单用户模式,不用inittab文件。 以及远程登陆 |
JohnBull 回复于:2005-04-02 00:56:44 |
[quote:4c1fc7f243="wangyih"] 本机登陆只是一种。还有 运行级别为5的图形方式登陆 单用户模式,不用inittab文件。 以及远程登陆[/quote:4c1fc7f243] 这是谁教你的?把他拖出去毙了! 想继续学UNIX/Linux操作系统就听我的,不想学随便。 |
wangyih 回复于:2005-04-02 00:59:06 |
[quote:a66345d34e="JohnBull"] 这是谁教你的?把他拖出去毙了! 想继续学UNIX/Linux操作系统就听我的,不想学随便。[/quote:a66345d34e] 无论怎么学都没必要听你的 |
JohnBull 回复于:2005-04-02 01:02:32 |
[quote:dd7cacdd53="wangyih"] 无论怎么学都没必要听你的[/quote:dd7cacdd53] 你看看这个同学,赌气就不好了嘛! 不管谁说的,正确的意见还是要听的! |
wangyih 回复于:2005-04-02 01:04:50 |
[quote:b4c8c193d8="JohnBull"] 你看看这个同学,赌气就不好了嘛! 不管谁说的,正确的意见还是要听的![/quote:b4c8c193d8] 那你说客户机远程登陆失败之后那个 login: 怎么出来的 |
JohnBull 回复于:2005-04-02 01:06:57 |
[quote:17445d58c1="wangyih"] 那你说客户机远程登陆失败之后那个 login: 怎么出来的[/quote:17445d58c1] init派生出来的另一个getty进程 |
wangyih 回复于:2005-04-02 01:28:17 |
[quote:3103c844f8="JohnBull"] init派生出来的另一个getty进程[/quote:3103c844f8] 和你没学出好。 login都exit,init派生出来的另一个getty进程还和客户端有什么关系 |
JohnBull 回复于:2005-04-02 01:34:36 |
[quote:527115a694="wangyih"] 和你没学出好。 login都exit,init派生出来的另一个getty进程还和客户端有什么关系[/quote:527115a694] 跟客户机扯什么关系? 买一本《UNIX环境高级编程》,看第9章 钱不够就找你娘要啊! |
wangyih 回复于:2005-04-02 01:36:55 |
[quote:87efd3ed3b="JohnBull"] 跟客户机扯什么关系? 买一本《UNIX环境高级编程》,看第9章 钱不够就找你娘要啊![/quote:87efd3ed3b] 你娘说过,不给你零花钱的,我知道 |
JohnBull 回复于:2005-04-02 01:41:15 |
[quote:c495aec5c0="wangyih"] 你娘说过,不给你零花钱的,我知道[/quote:c495aec5c0] 又学我!我想不教你都不行了 没看过不懂就别放炮 :em07: |
wangyih 回复于:2005-04-02 02:17:12 |
你还是没有说出 login都调用exit,连接都断了。init派生出来的另一个getty进程还和客户端有什么关系 客户端显示的login:是怎么出来的? 还是睡觉好。这么水平真是浪费我时间 |
wangyih 回复于:2005-04-02 02:49:05 |
看看你奉若神明的unix环境编程是怎么说的 9.2.1 4.3+BSD终端登录 login 能处理多项工作。因为它得到了用户名,所以能调用getpwnam 取得相应用户的口令文件登录项。然后调用g e t p a ss(3)以显示提示“ P a s s w o r d:”接着读用户键入的口令(自然,禁止回送用户键入的口令)。它调用c r y pt(3)将用户键入的口令加密,并与该用户 口令文件中登录项的p w _ p a s s w d字段相比较。 如果用户几次键入的口令都无效,则login 以 参数1调用exit 表示登录过程失败。父进程( i n i t)了解到子进程的终止情况后,将再次调 用f o r k,其后又跟随着执行g e t t y,对此终端重复上述过程 [quote:c774480fb1]就是说几次失败以后才login才exit ,然后i n i t再搞一个getty。之前失败是继续让用户输入[/quote:c774480fb1] |
ctqucl 回复于:2005-04-02 03:03:45 |
图形方式出现了登录框后登录失败会返回到命令行方式的 “login:”而不是图形的登录框。 可见这个login是重新生成的而不是返回的。 至于网络链接,在前面 rc 时就已经链接,我想这才能体现出linux的稳定性及微内核优势,此时已建立了稳定的连接,终端不过是一个设备而已了,它的崩溃与否不会影响到直接的连接了。 我是这么理解的,请高手多讲点吧。 本人水平不行,不要毙了我啊。 |
Vogel 回复于:2005-04-02 04:02:09 |
[quote:fcfc5f3f3e="wangyih"]你还是没有说出 login都调用exit,连接都断了。init派生出来的另一个getty进程还和客户端有什么关系 客户端显示的login:是怎么出来的? 还是睡觉好。这么水平真是浪费我时间[/quote:fcfc5f3f3e] 简直就是猪! :shock: :shock: |
ctqucl 回复于:2005-04-02 08:58:25 |
[quote:9d33d64b99="wangyih"][/quote:9d33d64b99]login 能处理多项工作。因为它得到了用户名,所以能调用getpwnam 取得相应用户的口令文件登录项。然后调用g e t p a ss(3)以显示提示“ P a s s w o r d:”接着读用户键入的口令(自然,禁止回送用户键入的口令)。它调用c r y pt(3)将用户键入的口令加密,并与该用户 口令文件中登录项的p w _ p a s s w d字段相比较。 如果用户几次键入的口令都无效,则login 以 参数1调用exit 表示登录过程失败。父进程( i n i t)了解到子进程的终止情况后,将再次调 用f o r k,其后又跟随着执行g e t t y,对此终端重复上述过程 跟我预想的差不多 :shock: |
惠繪洋 回复于:2005-04-02 09:46:20 |
各位好, 很高興在討論這一個問題, 小弟也有這個問題想討論一下. 小弟做了一個很菜的linux小系統, 能啟動到 login 畫面, 我已經在 /etc/passwd 及 /etc/shadow 下把root的password關掉, Shadow-HOWTO都是這樣教的. 這樣root就可以不使用密碼登入系統, 但現在當我輸入"root"後, 系統仍是顯示password,需要我輸入password, 但按Shadow HOWTO方法, 這是不會再顯示password提示而登入系統中,想請教各位在輸入"root"後, 系統會調用那個參數來做user的驗証呢. 以我估計應該我是少了驗証的那部份, 請問這個問題應該如何解決呢, 請指教. [code:1:512f681b9c] /etc/passwd root::0:0:root:/root:/bin/bash /etc/shadow root::11715:0::::: [/code:1:512f681b9c] |
wangyih 回复于:2005-04-02 11:44:35 |
[quote:577877d663="Vogel"] 简直就是猪! :shock: :shock:[/quote:577877d663] 说你自己嘛? |