LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3840|回复: 21

不新建分区在现有分区上做LFS的另外两种解决方法(原创)

[复制链接]
发表于 2006-8-23 12:47:04 | 显示全部楼层 |阅读模式
做LFS如果按步就班的来,一般都不会有问题,可偏有好事的人喜欢按自己的意思来(比方我),人家要求新建分区,不管是parted还是PQ,就是懒的动,那好,麻烦自然就跑到最后了.
其实直接把LFS安装在原文件系统上的一个目录下,还是与放在一个新分区下,前面的步骤都是一样的.只是到启动的时候,我们不得不离开我们可爱的chroot环境了.于是安装的各种程序只要是需要动态库的或对路径有硬编码的自然就玩不转了.做好的系统无法启动该多郁闷...然后痛哭说当初真不应该......好了,打住,解铃还需系铃人,就让我们自己动手,为我们的LFS谋生存吧.

先假设我们把LFS安装到了/lfsroot(不在那里也没关系,移过来就OK了,本来我们的LFS就是和宿主系统无关的嘛).
原理很简单,把/lfsroot变成我们真正的根目录就OK了.可变又有两种方法,假变还是真变!
假变,道理同chroot,其实这个简单,懂些Linux编程的人就能做到,自己编个程序比方叫myinit,放在/lfsroot/bin目录下.在grub里传递内核参数init=/lfsroot/bin/myinit.程序作用就是先chroot到/lfsroot,再exec到真正的/sbin/init.可以选择在宿主环境下动态或静态编译,或者选择在chroot到的LFS环境下静态编译(推荐,这样做到与宿主系统无关).这种方法是官方办法,也是常规方法,不新鲜.具体可以参照http://www.linuxfromscratch.org/ ... xisting_systems.txt这篇文章.程序可以到http://www.linuxfromscratch.org/ ... _helpers.tar.bz2下.
这种方法是给真正init做了一个假的家,而且要用自己的程序作init,不知这样会不会有什么微妙的差别.反正/proc/cmdline里肯定是记载下了我们私自篡改的"罪证".
下面我来说说我研究的另两种方法.
先说真变的方法吧.这种方法相对繁琐一些,后面介绍的第二种方法基本上只需改2 处即可.
我们知道,在同一个文件系统下,移动只需要改目录表类似的东西.就相当换个名子.于是,我们命令:/lfsroot,不要作/lfsroot了,改名叫 /;/,不要再叫/了,改名叫/osroot.其实就这么简单.可在什么时候改呢?当然是在init执行前了,在我们的系统中,/boot下一般还会有.img的文件,我们内核配置的时候也有相关的这一项:
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
其实有人说什么内核不支持root=LABEL=/之类的了就是扯淡,全是这个initrd=XXX.img的功劳,有了它,甚至把ext3等系统支持编译成模块都没问题.它会在init之前加载需要的模块.生成它需要mkinitrd软件包,这个系统上应该都有,不过有的可能版本底了,需要升级.我们先不谈这个mkinitrd不管你有也好,没有也好,直接把以前系统的那个拿过来让我们改改用就可以.
比方我们的内核是2.6.16.11,那相应的一般就是initrd-2.6.16.11.img,拷过来为我所用就可以.
下面真正开始了.
cp  /boot/initrd-2.6.16.11.img  /tmp/img.gz  (因为它是gzip压缩过的文件)
cd /tmp
gzip -d img.gz
mount -o loop img /mnt  (随变找个地挂上就行了)
这时你可以到/mnt目录下看看它的真面目了,看看它到底一直为我们默默无闻的做了些什么.
好了,该准备我们需要的工具了,mv必不可少,那么为了方便和更有保障,我们把bash也请来.系统里的这两个文件是不能直接用的.还好我们刚作的LFS,需要的源码包都有,bash包,Coreutils包,编译轻车熟路,只是我们现在需要的是静态版本的,最笨但也很有效的方法就是把
-static假如到LDFLAGS里:./configrue LDFLAGS=-static;make;然后在目录中找到生成的mv,bash拷到/mnt/bin下(我们假设把img文件挂在了/mnt下)
cd /mnt然后动手修改文件就好了,linuxrc文件会被运行,我们在里面调用我们自己写的脚本的比方名子叫mvit
文件清单如下:
原来的linuxrc一般是这样的.注释处是改变处:
################################################################
#!/bin/nash
                                                                                
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 -t ext3 /dev/root /sysroot                    #这行我们做了修改,挂载为rw模式
mvit                                                                 #做我们要做的事情
mount -o remount,ro -t ext3 /dev/root/ /sysroot     #挂回ro模式
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
##################################################################


mvit:如果你接受不足或错误提示你完全可以这样写
#####################################################################
#!/bin/bash
mv /sysroot/{,.}* /sysroot/osroot
mv /osroot/lfsroot/{,.}* /sysroot/

################################################################

这其中会有自己移动到自己的现象发生,出现错误提示,没关系,我们可以安全的忽略它;然后可能还有其他的副作用.总之不是很安全.

上面的mvit虽然简捷有效,可毕竟有不足,偏偏我们是完美主意者,于是让我们修改一下吧!
mvit:
############################################################
#! /bin/bash
function move()      #实现移动
{
for i in $1/{,.}*
do
   [ "$i " = "$1/* " -o "$i " = "$1/. " -o "$i " = "$1/.. " -o "$i " = "$2 " ] && continue #检查是否是空文件夹,防止发生把自己放到自己里面的白痴问题
   mv $i $2||/bin/bash             #一旦出错,甩出个shell环境,移动删除更改文件等价功能样样都有
done
}
function rmit()            #实现删除空文件夹   
{
src=`echo $1/{,.}*`
if [ -r $1 ] && [ "$src " != "$1/* $1/. $1/.. " ];then
   echo $1 is not empty!you may clean it youself
#   echo $1 is not empty!you may clean it youself>/sysroot/etc/issue #更改此行把警告输出到你要求的地方
   return 1
else
  echo "mount -t tmpfs tmpfs /tmp"|/bin/nash --force 1>/dev/null     #即然没有rm,那么我们变通一下,我们把它们扔到tmpfs中去,umount后就----再见啦^^,其实这里不挂载为tmpfs也可以,因为现在的根文件系统只是内存中虚拟的罢了.
  [ -e $1 ] && mv $1 /tmp
  echo "umount /tmp"|/bin/nash --force 1>/dev/null
fi
}
rmit /sysroot/osroot 1>/dev/null    #如果存在osroot空文件夹,删除.
if echo "mkdir /sysroot/osroot"|/bin/nash --force 1>/dev/null;then   #如果存在非空osroot文件夹,不用在作移动
move /sysroot /sysroot/osroot
rmit /sysroot/osroot/lfsroot/osroot||/bin/bash   #出错甩出个shell
move /sysroot/osroot/lfsroot /sysroot
rmit /sysroot/osroot/lfsroot||/bin/bash          #出错甩出个shell
fi
##################################################################################

然后
umount /mnt
gzip /tmp/img
cp /tmp/img.gz /lfsroot/boot/initrd.img
修改/boot/grub/grub.conf,在加载LFS的内核后面加一句initrd=/lfsroot/boot/initrd.img
至此,可以安全正常的进入我们的LFS系统了.但是差一点没有做.
那就是如何再进入宿主系统,很简单,反过来做就可以了.
mvit:
#####################################################################################
#! /bin/bash
function move()
{
for i in $1/{,.}*
do
   [ "$i " = "$1/* " -o "$i " = "$1/. " -o "$i " = "$1/.. " -o "$i " = "$2 " ] && continue
   mv $i $2||/bin/bash
done
}
function rmit()
{
src=`echo $1/{,.}*`
if [ -r $1 ] && [ "$src " != "$1/* $1/. $1/.. " ];then
   echo $1 is not empty!you may clean it youself
#   echo $1 is not empty!you may clean it youself>/sysroot/etc/issue
   return 1
else
  echo "mount -t tmpfs tmpfs /tmp"|/bin/nash --force 1>/dev/null
  [ -e $1 ] && mv $1 /tmp
  echo "umount /tmp"|/bin/nash --force 1>/dev/null
fi
}
rmit /sysroot/lfsroot 1>/dev/null
if echo "mkdir /sysroot/lfsroot"|/bin/nash --force 1>/dev/null;then
move /sysroot /sysroot/lfsroot
rmit /sysroot/lfsroot/osroot/lfsroot||/bin/bash
move /sysroot/lfsroot/osroot /sysroot
rmit /sysroot/lfsroot/osroot||/bin/bash
fi
#############################################################################################
将这个做好的img,拷到/lfsroot/boot中
cp img.gz /lfsroot/boot/hf.img
把/boot/grub/grub.conf 拷到/lfsroot/boot/grub.conf.修正/lfsroot/boot/grub.conf中的路径.
把宿主系统的initrd行改为initrd=/boot/hf.img   
把宿主系统的kernel行改为initrd=/osroot/boot/XXXXXXXX
把LFS系统的initrd行改为initrd=/boot/initrd.img
把LFS系统的kernel行改为kernel=/boot/XXXXXXXXX
至此大功告成,享受自己的作品去吧.^^

再来说说第二种方法.
也是假变,大概思路与官方方法相似,但我们不从init下手,还是在img上下手,我觉得这样做比官方方法的优点是下手更提前,整个过程无声无息,隐藏的更好,不会在/proc/cmdline下留下罪证.
也需要静态编译个程序mount,nash提供的mount功能满足不了我们的要求了.
还是编辑img文件,修改linuxrc如下:
###############################################################################
#!/bin/nash
                                                                                
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   
mount --bind /sysroot/lfsroot /sysroot                  #我们只添加了这一行
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
##################################################################################

好吧,处理这个img
gzip /tmp/img
cp /tmp/img.gz /lfsroot/boot/initrd2.img
修改/boot/grub/grub.conf文件,只需在加载LFS内核项下面加上一句
initrd=/lfsroot/boot/initrd2.img
ok了,其他的什么都不需要改了,简单吧.^^


再说一点就是其实我们可以不必把这些静态编译的程序全放进img文件中的,只要过程中能调用到就可以,比方我们把这些程序放到/lfsroot/root/bin中,只要把路经写对就可以了,这种情况下就是到/sysroot/osroot/root/bin中调用程序。


两种方法各有优缺点,第一种更彻底一些,第二种更简单快捷一些.但重要的是明白了其中的方法原理就可以自己的Linux自己想怎么变就怎么变了^^

                        -----------Skymoon作品,转贴注明出处来源,作者.
发表于 2006-8-23 18:56:11 | 显示全部楼层
好,我就觉得学lfs就是学的一种思想,一种方法。不能完全照搬。不然没意思了。支持楼主。
回复 支持 反对

使用道具 举报

发表于 2006-8-23 19:06:25 | 显示全部楼层
mkdevices /dev
echo Creating root device
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev

mkrootdev  是哪里来的?。

其实只要会用 initrd/initramfs 启动的话,换一个目录也没什么难度的噢。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-8-23 21:37:26 | 显示全部楼层
Post by 松心心
好,我就觉得学lfs就是学的一种思想,一种方法。不能完全照搬。不然没意思了。支持楼主。

呵呵,谢谢^^
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-8-23 21:51:36 | 显示全部楼层
Post by 终极幻想
mkdevices /dev
echo Creating root device
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev

mkrootdev  是哪里来的?。


mkrootdev是内核参数识别root=LABEL=/之类的参数的本质原因,是mkinitrd包内的,是静态程序,原来的img文件中就有,拿来就能使^^
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-8-24 21:56:06 | 显示全部楼层
真郁闷,写了这么多没人看么。。。。。。
回复 支持 反对

使用道具 举报

发表于 2006-8-24 23:21:16 | 显示全部楼层
mkinitrd 这个包哪里来的?。。某个发行版自己的?还是类似 yaird 之类的通用的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-8-25 00:21:33 | 显示全部楼层
Post by 终极幻想
mkinitrd 这个包哪里来的?。。某个发行版自己的?还是类似 yaird 之类的通用的。


是通用的。我没有用这个工具包生成,而是直接修改的现有的img文件。每个人的系统可能情况都不太一样,但我想img文件要改的地方也还是那么个思路,不会有太大变化。其实不用这个也可以,dd,mkfs,一个,mount上后,编辑linuxrc文件,调用自己需要的程序就行。没有用cpio形式的,因为不想自己干扰内核太多。


谢谢版主的支持和鼓励^^,曾经发过一篇glibc的帖子,被版主加精还鼓励来了LFS区,呵呵,这次又是版主一直关注照顾,小弟感激不尽啊,在此谢过了^^
回复 支持 反对

使用道具 举报

发表于 2006-8-25 06:33:47 | 显示全部楼层
Post by Skymoon
真郁闷,写了这么多没人看么。。。。。。
正在对比两者的区别。。。

http://www.linuxsir.cn/bbs/showthread.php?t=263280
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-8-25 12:19:10 | 显示全部楼层
Post by d00m3d
正在对比两者的区别。。。

http://www.linuxsir.cn/bbs/showthread.php?t=263280


我看过了,他的方法是我说的在文章最开始提到的官方方法。pre-init的源代码下载我在文中也提到了。方法的英文链接我也给出了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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