LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: xwos

启动挂起:No init found

[复制链接]
发表于 2004-2-7 13:12:27 | 显示全部楼层
真是搞不明白。不知道是不是文件系统的错误。
发表于 2004-2-7 13:14:14 | 显示全部楼层
最初由 gwssi 发表
1.的确有/boot
2.按你说的修改后,错误改了
kmod:failed to exec /sbin/modprobe -s -k block-major-8, errno = 2
VFS: Cannot open root device "sdb1" or 08:11


刚才说错了,出这个错误时因为我试着用过别的内核启动,忘了修改过来了
正确的修改后,错误信息与原来是一样的: No init found
发表于 2004-2-7 13:22:11 | 显示全部楼层
最初由 黄叶 发表
真是搞不明白。不知道是不是文件系统的错误。


黄叶兄,我的意思不是说init脚本的风格造成kernel panic问题,而是顺便指出一下发行版本间的异同。

fedora的init脚本的确是混合风格,阁下对比两者便可知道。我指出其中一点,传统的sysv只有rc.x目录以及rc.sysinit(<--这个名字我可能记错,总之是run at once)目录,目录里都是些到init.d的软链接;而bsd同样传承于sysvinit,不过它使用rc.sysinit脚本(不是目录)来统率各个运行级别(同样也是脚本)。

另外,我在lfs以及fedora上编译过很多次2.6.x内核,考虑到我总结出来的现象后就从没有遇到kernel panic问题,所以在下不好回答,还请兄弟们指教。
发表于 2004-2-7 15:24:02 | 显示全部楼层
哦。是这样啊。我没有仔细的比较过这个问题。
不过,原来看到有一篇文章说bsd是比较老的启动试,而较新的都是采用sysv的启动方式,它给了一个关于红帽子的例了。

我对sysv和bsd的启动方式了解不多。谢谢指教。
发表于 2004-2-8 12:49:49 | 显示全部楼层
不知道兄弟们有没有升级某些兼容内核2.6的工具,尤其是procps,fedora自带的procps很旧。
  1. o  Gnu C                  2.95.3                  # gcc --version
  2. o  Gnu make               3.78                    # make --version
  3. o  binutils               2.12                    # ld -v
  4. o  util-linux             2.10o                   # fdformat --version
  5. o  module-init-tools      0.9.10                  # depmod -V
  6. o  e2fsprogs              1.29                    # tune2fs
  7. o  jfsutils               1.1.3                   # fsck.jfs -V
  8. o  reiserfsprogs          3.6.3                   # reiserfsck -V 2>&1|grep reiserfsprogs
  9. o  xfsprogs               2.6.0                   # xfs_db -V
  10. o  pcmcia-cs              3.1.21                  # cardmgr -V
  11. o  quota-tools            3.09                    # quota -V
  12. o  PPP                    2.4.0                   # pppd --version
  13. o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
  14. o  nfs-utils              1.0.5                   # showmount --version
  15. o  procps                 3.1.13                  # ps --version
  16. o  oprofile               0.5.3                   # oprofiled --version
复制代码
 楼主| 发表于 2004-2-9 17:07:54 | 显示全部楼层
好感动!竟然有那么多大哥来帮忙分析!谢谢!

对于“启动挂起:NO init found”我查看了一些资料,
我这边造成上面问题的原因有两个:
1.在/ 目录下没建立initrd目录,
2.没有相应的动态函式库ld-linux.so.2或者函式库错误,
对于第一点我也不是很清楚具体的原因,因为我在引导器中已指定了init的
相应路径,但还是不行,在/下创建一个initrd空目录就好了。
对于第二点我也是试验的时候才发现的,如果在lib目录中没有lb-linux.so.2
或者发生错误(特别是在编译kernel的时候),肯定会出现上面的问题.(至于
动态函式库的信息可参考下面的文章,转载)
后来我做了一些试验,发现
1.上面的问题跟fstab文件关系不大,即使fstab文件为空,INIT也可以找到运
行,只是在后面mount filesystem的时候才会有问题,
2.如果inittab文件出错,也不会出现上面的信息,至少会出现
INIT: version2.78 boot
INIT: no found inittab file or inittab file error.
type run level:
而不会出现"NO init found"
3.跟lilo或grub引导器设置关系不大,如果是设置有误,要么系统不会运行
到这一步,要么会在下面mount fs时才会出现error。
所以在我看来上面第二个原因几率比较大,至于第一点还请各位大哥帮忙分
析一下。
另外我从一本书上找到了系统启动时内核初始化过程的资料,我会尽快把它
传上来供大家参考一下!
谢谢!




讨论动态函式库格式:
我们都知道在 Linux中有 a.out 与 ELF 两种档案的格式,其中目前我们最常见的便是 ELF 档案格式。在 Linux 的函式库目录中,我们常常可以见到 “*.so” 的档案,例如:“/lib/libc.so.6” 或是 “/lib/ld-linux.so.2”。这些便是在 Linux中所常见到的动态函式库档案。由下图我们可以看到动态函式库 libc.so.6 的 ELF Header:
[code:1:55f6a4dc24]libc.so.6 的 ELF Header  
e_ident ->EI_MAG0:7fh  
->EI_MAG1:E  
->EI_MAG2  
->EI_MAG3:F  
->EI_CLASS:32-bit objects  
->EI_DATA:ELFDATA2LSB  
->EI_VERSION:1h  
->EI_PAD:0h  
->EI_NIDENT:3h  
e_type: ET_DYN (Shared Obj File)  
e_machine:Intel 80386  
e_version:Current version  
e_entry:182a8h  
e_phoff:34h  
e_shoff:3bbf8ch  
e_flags:0h  
e_ehsize:34h  
e_phentsize:20h  
e_phnum:5h  
e_shentsize:28h  
e_shnum:40h  
e_shstrndx:3dh [/code:1:55f6a4dc24]
由图中,我们可以注意到 e_type: ET_DYN,e_type 是在ELF 档案的格式中,用来描述目前该档的档案型态,我们所举的例子为 libc.so.6 这个动态函式库的档案,所以 e_type 的属性为 Shared Obj File。  
我们若再拿一个ELF执行档来比较也是不错的,所以如下图  
[code:1:55f6a4dc24]ls 的 ELF Header  
e_ident ->EI_MAG0:7fh  
->EI_MAG1:E  
->EI_MAG2  
->EI_MAG3:F  
->EI_CLASS:32-bit objects  
->EI_DATA:ELFDATA2LSB  
->EI_VERSION:1h  
->EI_PAD:0h  
->EI_NIDENT:2h  

e_type: ET_EXEC (Executable file)  

e_machine:Intel 80386  
e_version:Current version  
e_entry:8049130h  
e_phoff:34h  
e_shoff:bea4h  
e_flags:0h  
e_ehsize:34h  
e_phentsize:20h  
e_phnum:6h  
e_shentsize:28h  
e_shnum:1ah  
e_shstrndx:19h [/code:1:55f6a4dc24]

我们可以注意到 e_type: ET_EXEC,这就是 ELF 档中对於执行档所定义的档案属性。  
[b:55f6a4dc24]动态连结 VS 静态联结 [/b:55f6a4dc24]
在 Linux 中,执行档我们可以编程成静态联结以及动态连结,以下我们举一个简短的程序作为例子:  

[code:1:55f6a4dc24]#include  
int main()  
{  
printf("\ntest");  
} [/code:1:55f6a4dc24]

我们执行 :  

[root@hlchou /root]# gcc test.c -o test  

所产生出来的执行档 test,预设为使用动态函式库,所以我们可以用以下的指令 :  
[code:1:55f6a4dc24][root@hlchou /root]# ldd test  
libc.so.6 => /lib/libc.so.6 (0x40016000)  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) [/code:1:55f6a4dc24]

来得知目前该执行档共用了哪些动态函式库,以我们所举的 test 执行档来说,共用了两个动态函式库,分别为 libc.so.6 与 ld-linux.so.2。我们还可以透过下面的 file 指令,来得知该执行档的相关属性,如下  

[code:1:55f6a4dc24][root@hlchou /root]# file test  
test: ELF 32-bit LSB executable, Intel 80386, version 1, dynamically linked (use  
s shared libs), not stripped [/code:1:55f6a4dc24]

not stripped 表示这个执行档还没有透过 strip 指令来把执行时用不到的符号、以及相关除错的资讯删除,举个例子来说,目前这个test 执行档大小约为 11694 bytes  

[code:1:55f6a4dc24][root@hlchou /root]# ls -l test  
-rwxr-xr-x 1 root root 11694 Oct 24 02:31 test [/code:1:55f6a4dc24]

经过strip後,则变为 3004 bytes  
[code:1:55f6a4dc24][root@hlchou /root]# strip test  
[root@hlchou /root]# ls -l test  
-rwxr-xr-x 1 root root 3004 Oct 24 02:48 test [/code:1:55f6a4dc24]

不过读者必须注意到一点,经过 strip 过的执行档,就无法透过其它的除错软件从里面取得函式在编程时所附的相关资讯,这些资讯对我们在除错软件时,可以提供不少的帮助,各位在应用上请自行注意。  

相对於编程出来使用动态函式库的执行档 test,我们也可以做出静态联结的执行档 test  

[code:1:55f6a4dc24][root@hlchou /root]# gcc -static test.c -o test [/code:1:55f6a4dc24]

透过指令 ldd,我们可以确定执行档 test 并没有使用到动态函式库  
[code:1:55f6a4dc24][root@hlchou /root]# ldd test  
not a dynamic executable [/code:1:55f6a4dc24]

再透过指令 file,可以注意到 test 目前为 statically linked,且亦尚未经过 strip  
[code:1:55f6a4dc24][root@hlchou /root]# file test  
test: ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, not stripped [/code:1:55f6a4dc24]

使用静态联结,且又没有经过 strip 删去不必要的符号的执行档的大小会是多少,透过 ls -l来看,我们发现大小变成 932358 bytes 比起静态联结的执行档大了相当多  
[code:1:55f6a4dc24][root@hlchou /root]# ls -l test  
-rwxr-xr-x 1 root root 932258 Oct 24 02:51 test [/code:1:55f6a4dc24]
若再经过 strip,则档案大小变为 215364 bytes  

[code:1:55f6a4dc24][root@hlchou /root]# strip test  
[root@hlchou /root]# ls -l test  
-rwxr-xr-x 1 root root 215364 Oct 24 02:55 test [/code:1:55f6a4dc24]

与使用动态函式库的执行档 test 比较起来,大了约 70倍 (215364/3004)。因此,整体来说,在使用的环境中使用动态函式库并且经过 strip 处理的话,可以让整体的空间较为精简。许多执行档都会用到同一组的函式库,像 libc 中的函式是每个执行档都会使用到的,若是使用动态函式库,则可以尽量减少同样的函式库内容重复存在系统中,进而达到节省空间的目的。  

笔者一年前曾写过一个可以用来删去动态函式库中不必要函式的工具,针对这个只用到了 printf 的程序来产生新的 libc.so 的话,我们可以得到一个精简过的 libc.so 大小约为 219068 bytes  

[code:1:55f6a4dc24][root@hlchoua lib]# ls -l libc.so*  
-rwxr-xr-x 1 root root 219068 Nov 2 04:47 libc.so  
lrwxrwxrwx 1 root root 7 Nov 1 03:40 libc.so.6 -> libc.so [/code:1:55f6a4dc24]

与静态联结的执行档大小 215364 bytes 比较起来,若是在这个环境中使用了动态函式库的话成本约为 3004 + 219068 =222072 bytes,不过这是只有一个执行档的情况下,使用动态函式库的环境会小输给使用静态联结的环境,在一个基本的 Linux 环境中,如果大量的使用动态函式库的话,像是有 2 个以上的执行档的话,那用动态函式库的成本就大大的降低了,像如果两个执行档都只用到了 printf,那静态联结的成本为 215364 *2 =430728 bytes,而使用动态函式库的成本为3004 *2 + 219068=225076 bytes,两者相差约一倍。  

很明显的,我们可以看到动态函式库在 Linux 环境中所发挥的妙用,它大幅的降低了整体环境的持有成本,提高了环境空间的利用率。  

ld-linux.so.2  
在 RedHat 6.1 中,我们可以在 /lib 或是 /usr/lib 目录底下找到许多系统上所安装的动态函式库,在文章的这个部分,笔者将把整个函式库大略的架构作一个说明。  

其实 Linux 跟 Windows 一样,提供了一组很基本的动态函式库,在 Windows 上面我们知道 kernel32.dll 提供了其它动态函式库基本的函式呼叫,而在 Linux 上面则透过 ld-linux.so.2 提供了其它动态函式库基本的函式,在笔者电脑的 RedHat6.1 上,ld-linux.so.2 是透过 link 到 ld-2.1.2.so(这部分需视各人所使用的 glibc 版本不同而定)  

[code:1:55f6a4dc24]-rwxr-xr-x 1 root root 368878 Jan 20 14:28 ld-2.1.2.so  
lrwxrwxrwx 1 root root 11 Jan 20 14:28 ld-linux.so.2 -> ld-2.1.2.so [/code:1:55f6a4dc24]

ld-linux.so 是属於 Glibc (GNU C Library) 套件的一部分,只要是使用 Glibc 动态函式库的环境,就可以见到 ld-linux.so 的踪影。  

接下来,我们透过指令 ldd 来验证出各个函式库间的阶层关系,首先如下图我们执行了 ”ldd ls”、”ldd pwd” 与 “ldd vi”,可以看出各个执行档呼叫了哪些动态函式库,像执行档 ls 呼叫了 /lib/libc.so.6 (0x40016000) 与 /lib/ld-linux.so.2 (0x40000000),而括号内的数字为该函式库载入记忆体的位置,在本文的稍後,会介绍到函式库载入时的细节,到时读者会有更深入的了解。  

其实我们不难发现,在 Linux 上使用动态函式库的执行档,几乎都会去呼叫 libc.so.6 与 ld-linux.so.2 这两个动态函式库,笔者过去修改 Glibc 的套件时,也了解到在 Linux 中函式库的关系,ld-linux.so.2 算是最底层的动态函式库,它本身为静态联结,主要的工作是提供基本的函式给其他的函式库,而我们最常会呼叫的 libc.so.6 则是以 ld-linux.so.2 为基础的一个架构完成的动态函式库,它几乎负责了所有我们常用的标准 C 函式库,像是我们在 Linux 下写的 Socket 程序,其中的connect()、bind()、send() .....之类的函式,都是由 libc.so.6 所提供的。  

也因此,libc.so.6 的大小也是相当可观的,在 RedHat 6.1 中经过 strip 後,大小约为 1052428 bytes。  

[code:1:55f6a4dc24][root@hlchoua /root]# ldd /bin/ls  
libc.so.6 => /lib/libc.so.6 (0x40016000)  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)  
[root@hlchoua /root]# ldd /bin/pwd  
libc.so.6 => /lib/libc.so.6 (0x40016000)  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)  
[root@hlchoua /root]# ldd /bin/vi  
libtermcap.so.2 => /lib/libtermcap.so.2 (0x40016000)  
libc.so.6 => /lib/libc.so.6 (0x4001b000)  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) [/code:1:55f6a4dc24]

如下,我们透过 ldd 验证 vi 所用到的动态函式库 /lib/libtermcap.so.2,它本身是呼叫了 libc.so.6 的函式所组成的。  

[code:1:55f6a4dc24][root@hlchoua /root]# ldd /lib/libtermcap.so.2  
libc.so.6 => /lib/libc.so.6 (0x40007000)  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000) [/code:1:55f6a4dc24]

接下来,我们依序测试了 /lib/libc.so.6 与 /lib/ld-linux.so.2  
[code:1:55f6a4dc24][root@hlchoua /root]# ldd /lib/libc.so.6  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)  
[root@hlchoua /root]# ldd /lib/ld-linux.so.2  
statically linked [/code:1:55f6a4dc24]

我们可以整理以上的结论,画成如下的一个架构图  

在这个图中,我们可以清楚的明白 ld-linux.so.2 负责了最基础的函式,而 libc.so.6 再根据这些基本的函式架构了完整的 C 函式库,供其它的动态函式库或是应用程序来呼叫。  

透过笔者所写的一个 ELF 工具程序(注二),我们也可以清楚的看到 libc.so.6呼叫了 ld-linux.so.2 哪些函式  

[code:1:55f6a4dc24][root@hlchoua /root]# /I-elf /lib/libc.so.6|more  
========================================================  
open_target_file:/lib/libc.so.6  
==>ld-linux.so.2  
__register_frame_table  
cfsetispeed  
xdr_int32_t  
utmpname  
_dl_global_scope_alloc  
__strcasestr  
hdestroy_r  
rename  
__iswctype_l  
__sigaddset  
xdr_callmsg  
pthread_setcancelstate  
xdr_union  
__wcstoul_internal  
setttyent  
strrchr  
__sysv_signal ...┅(more) [/code:1:55f6a4dc24]

其实,ldd 指令为一个 shell script 的档案,它主要是透过呼叫 ”run-time dynamic linker” 的命令,并以 LD_TRACE_LOADED_OBJECTS 为参数来秀出这些结果的。  

如下,就是我们不透过 ldd 指令直接以 eval 搭配 LD_TRACE_LOADED_OBJECTS参数来检视 libcrypt.So.1 与 libm.so.6这两个动态函式库的结果。  
[code:1:55f6a4dc24][root@hlchoua /root]# eval LD_TRACE_LOADED_OBJECTS=1 '/lib/libcrypt-2.1.2.so'  
libc.so.6 => /lib/libc.so.6 (0x40016000)  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)  
[root@hlchoua /root]# eval LD_TRACE_LOADED_OBJECTS=1 '/lib/libm.so.6'  
libc.so.6 => /lib/libc.so.6 (0x40016000)  
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) [/code:1:55f6a4dc24]讨论动态函式库的档案格式:
发表于 2004-2-9 17:19:53 | 显示全部楼层
对于“启动挂起:NO init found”我查看了一些资料,
我这边造成上面问题的原因有两个:
1.在/ 目录下没建立initrd目录,
2.没有相应的动态函式库ld-linux.so.2或者函式库错误,
对于第一点我也不是很清楚具体的原因,因为我在引导器中已指定了init的
相应路径,但还是不行,在/下创建一个initrd空目录就好了。
对于第二点我也是试验的时候才发现的,如果在lib目录中没有lb-linux.so.2
或者发生错误(特别是在编译kernel的时候),肯定会出现上面的问题.(至于
动态函式库的信息可参考下面的文章,转载)
后来我做了一些试验,发现
1.上面的问题跟fstab文件关系不大,即使fstab文件为空,INIT也可以找到运
行,只是在后面mount filesystem的时候才会有问题,
2.如果inittab文件出错,也不会出现上面的信息,至少会出现
INIT: version2.78 boot
INIT: no found inittab file or inittab file error.
type run level:
而不会出现"NO init found"
3.跟lilo或grub引导器设置关系不大,如果是设置有误,要么系统不会运行
到这一步,要么会在下面mount fs时才会出现error。
所以在我看来上面第二个原因几率比较大,至于第一点还请各位大哥帮忙分
析一下。

1.一般的发行版本一般都采用initrd来启动,所以都存在/initrd目录,典型的如fedora
2.可以检测一下你的init程序的相关动态链接库
  ## ldd /bin/init
如果结果中有glibc的动态链接器以及binutils的标准链接器,则说明你的系统工具链完整,不存在什么链接库问题
发表于 2004-2-9 17:28:47 | 显示全部楼层
对于“启动挂起:NO init found”我查看了一些资料,
我这边造成上面问题的原因有两个:
1.在/ 目录下没建立initrd目录,
2.没有相应的动态函式库ld-linux.so.2或者函式库错误,
对于第一点我也不是很清楚具体的原因,因为我在引导器中已指定了init的
相应路径,但还是不行,在/下创建一个initrd空目录就好了。
对于第二点我也是试验的时候才发现的,如果在lib目录中没有lb-linux.so.2
或者发生错误(特别是在编译kernel的时候),肯定会出现上面的问题.(至于
动态函式库的信息可参考下面的文章,转载)
后来我做了一些试验,发现
1.上面的问题跟fstab文件关系不大,即使fstab文件为空,INIT也可以找到运
行,只是在后面mount filesystem的时候才会有问题,
2.如果inittab文件出错,也不会出现上面的信息,至少会出现
INIT: version2.78 boot
INIT: no found inittab file or inittab file error.
type run level:
而不会出现"NO init found"
3.跟lilo或grub引导器设置关系不大,如果是设置有误,要么系统不会运行
到这一步,要么会在下面mount fs时才会出现error。
所以在我看来上面第二个原因几率比较大,至于第一点还请各位大哥帮忙分
析一下。

1.一般的发行版本一般都采用initrd来启动,所以都存在/initrd目录,典型的如fedora
2.可以检测一下你的init程序的相关动态链接库
ldd /bin/init
如果结果中有glibc的动态链接器以及binutils的标准链接器,则说明你的系统工具链完整,并不存在什么链接库问题。同时,如果换成内核2.4就能正确启动系统的话(旧内核尚且行,新内核反而丢失了链接库信息?),这种怀疑就不攻自破啦。
如果还怀疑,还可像lfs一样来检测工具链。

  1. echo 'main(){}' > dummy.c
  2. cc dummy.c
  3. readelf -l a.out |grep interpreter
复制代码

3.lilo以及grub是os loader,从其命令可知它们的工作流程就是载入内核,然后把控制权交给内核,内核初始化完硬件设备后,就营造保护模式,载入并初始化initrd映像,孵生init进程,再把控制权交给init进程。可见运行到initrd那一步和提供启动信息的os loader的设置有莫大的关系。

聊表看法而已。不明白为什么大家会经常遇到这种情况,想必都是旧系统运行了一段日子才升级内核吧。我很少遇到kernel panic问题。
发表于 2004-2-9 21:56:58 | 显示全部楼层
终于大家又拾起这个话题了,对照以下 xwos 的说法

1.没有/initrd,这种情况我几天前在另一个系统中碰见过,没搞明白原因
  这次装的系统中好像没有initrd啊,当然我也建了/initrd

2.我的机器上有/lib/libc.so.6和/lib/ld-linux.so.2
ldd /sbin/init
结果为 libc.so.6 => /lib/libc.so.6 (0x40018000)
       /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
按照lfs的方式检测也正常

另外:我是按照lfs5.0的说明,刚刚做完就启动不了的,并不是用了很久
发表于 2004-2-10 05:01:23 | 显示全部楼层
在我的系统上已经解决了这个问题,虽然还有其他问题

主要问题一直出在grub.conf中,root=的参数应该给出实际系统中root分区的路径如:/dev/sda2

大家的讨论给了我很多提示,非常感谢!希望我的经验对大家有所帮助。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表