最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【workaround】buildroot下面make编译,最后生成的rootfs中的特殊的设备文件,实际是普通文件

Buildroot crifan 4511浏览 0评论

【workaround】buildroot下面make编译,最后生成的rootfs中的特殊的设备文件,实际是普通文件
关键词:buildroot, rootfs, makedevs, mknod, fakeroot, device file, normal file

[问题]
buildroot下面,在make之后,最后会生成我们所要的rootfs,其中包括对应的设备文件。
但是实际结果是,在make之后,我们所得到的设备文件,都只是普通文件而已。
比如,对于buildroot-2009.11来说,在make之后,输入的rootfs位置是output/target/下面,对应的设备文件在output/target/dev/下面,期望是对应的具有主次设备号的设备文件,但是实际只是普通的文件:
crifan@crifan-laptop:buildroot-2009.11$ ls output/target/dev/* -lh
-rw-rw-rw- 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/console
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/fb0
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/fb1
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/fb2
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/fb3
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/hda
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/hda1
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/hda2
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/hda3
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/hda4
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/hdb
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/hdb1
。。。
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/kmem
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/loop0
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/loop1
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mem
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtd0
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtd1
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtd2
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtd3
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtdblock0
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtdblock1
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtdblock2
-rw-r—– 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/mtdblock3
-rw-rw-rw- 1 crifan crifan     0 2010-04-16 22:39 output/target/dev/null
。。。。。。。

[解决过程]
1.去研究了下buildroot的make编译过程,其执行过程如下,其中可以看到是调用makedevs,去根据target/generic/device_table.txt中的设置,生成对应的设备文件的。而此处实际却生成出了普通的文件,而不是我们要的设备文件,所以,先是怀疑,是不是这个makedevs工具本身有啥问题,结果单独去调用此工具去生成设备文件,发现是可以的:
crifan@crifan-laptop:buildroot-2009.11$ rm output/target/dev/* -rf
crifan@crifan-laptop:buildroot-2009.11$ sudo /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/makedevs -d target/generic/device_table.txt /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target
[sudo] password for crifan:
rootdir=/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target
table='target/generic/device_table.txt'

注意要先删除之前的那些设备文件,否则会提示设备已存在,无法创建。
而且对于makedevs,对于创建设备文件的时候,本质上也是调用mknod,所以要用sudo即root权限,才可以执行的。
此时,再去看生成的对应的设备文件,都是正常的:
crifan@crifan-laptop:buildroot-2009.11$ ls output/target/dev -lh
总用量 16K
crw-rw-rw- 1 root root    5,    1 2010-04-16 23:29 console
crw-r—– 1 root tty    29,    0 2010-04-16 23:29 fb0
crw-r—– 1 root tty    29,    1 2010-04-16 23:29 fb1
。。。。
crw-r—– 1 root root    1,    1 2010-04-16 23:29 mem
crw-r—– 1 root root  90,    0 2010-04-16 23:29 mtd0
crw-r—– 1 root root  90,    2 2010-04-16 23:29 mtd1
crw-r—– 1 root root  90,    4 2010-04-16 23:29 mtd2
crw-r—– 1 root root  90,    6 2010-04-16 23:29 mtd3
brw-r—– 1 root root  31,    0 2010-04-16 23:29 mtdblock0
brw-r—– 1 root root  31,    1 2010-04-16 23:29 mtdblock1
brw-r—– 1 root root  31,    2 2010-04-16 23:29 mtdblock2
brw-r—– 1 root root  31,    3 2010-04-16 23:29 mtdblock3
drwxr-xr-x 2 root root      4.0K 2010-04-16 23:29 net
crw-rw-rw- 1 root root    1,    3 2010-04-16 23:29 null
crw-rw-rw- 1 root root  10,    1 2010-04-16 23:29 psaux
crw-rw-rw- 1 root root    5,    2 2010-04-16 23:29 ptmx
。。。

证明此makedevs工具是可以正常工作的。

2.后来,实在找不到具体原因了,只能回头来好好分析一下buildroot的make之后具体执行过程了,后来基本搞懂了,下面根据其输出具体分析其含义:
。。。
echo "2009.11" >
/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target/etc/br-version
mkdir -p /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target/etc
echo "as353x" > /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target/etc/hostname
mkdir -p /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target/etc
echo "Welcome to AS353X" > /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target/etc/issue
/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/toolchain/bin/sed -i -e '/# GENERIC_SERIAL$/s~^.*#~ttySAC0::respawn:/sbin/getty -L ttySAC0 115200 vt100 #~'
/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target/etc/inittab

//此处之前的步骤,就是将之前的一系列设置,都echo输出到对应的位置,比如hostname,etc下面相关的//inittab等,即将rootfs中相关配置内容都输入到将要用到的rootfs中
//下面先删除之前生成的,旧的那个脚本:_fakeroot."rootfs".arm.cramfs,因为下面会生成新的
# Use fakeroot to pretend all target binaries are owned by root
rm -f /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot."rootfs".arm.cramfs

//touch文件.fakeroot.00000,如果没有就新建一个空的, 用于后面输入内容到此脚本中;如果已经存在了,那么说明是别的类型的rootfs,比如对于此处的cramfs来说,之前如果有ext等rootfs,那么此.fakeroot.00000就已经包含了对应之前ext2的输出的内容了
touch /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/.fakeroot.00000
//将所有相关的前面的那些配置,都输出到_fakeroot."rootfs".arm.cramfs中
cat /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/.fakeroot* > /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot."rootfs".arm.cramfs
//同上,输出此命令到该脚本中,注意此时并没有执行呢,对于echo来说,只是输出这些命令对应这些字符串而已,具体的命令执行,要到最后才执行
echo "chown -R 0:0 /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target" >> /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot."rootfs".arm.cramfs
//同上,输出生成设备文件所对应的命令
# Use fakeroot to pretend to create all needed device nodes
echo "/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/makedevs -d target/generic/device_table.txt /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target"
>> /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot."rootfs".arm.cramfs
# Use fakeroot so mkcramfs believes the previous fakery

//同上,输出调用具体工具制作rootfs镜像所用的命令
echo "/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/cramfs-1.1/mkcramfs -q -l -D target/generic/device_table.txt "
"/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/images/"rootfs".arm.cramfs" >> /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot."rootfs".arm.cramfs
chmod a+x /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot."rootfs".arm.cramfs

/*
注意,此时,上面那个文件中,就有了这些内容:
。。。。
chown -R 0:0 /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target
/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/makedevs -d target/generic/device_table.txt /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target
/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/cramfs-1.1/mkcramfs -q -l -D target/generic/device_table.txt  /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/images/rootfs.arm.cramfs
即先将target权限变为0:0,然后去调用makedevs,根据device_table.txt中的定义,生成所要的设备文件,然后调用具体的rootfs镜像制作工具cramfs,制作出对应的rootfs镜像文件rootfs.arm.cramfs
*/
//下面调用fakeroot,加上参数– 后面跟上具体要执行的命令,此处就是之前被那些命令填充了的脚本:
//_fakeroot."rootfs".arm.cramfs
//根据那些命令,生成出对应的rootfs镜像文件,而下面的那些输出,对应着那些命令的执行
/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/fakeroot — /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot."rootfs".arm.cramfs
rootdir=/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target
table='target/generic/device_table.txt'

//此时已经执行完所有的命令了,生成了我们所要的rootfs镜像文件:rootfs.arm.cramfs
//因此,就过河拆桥型的,把不再需要的的fakeroot脚本删掉
# Use fakeroot to pretend all target binaries are owned by root
rm -f /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/build/_fakeroot.rootfs.arm.ext2

此时,就大功告成了,即buildroot用fakeroot工具,伪装成root权限用户,依次去chown,切换target的权限,调用makedevs生成需要的各种系统文件和很多设备文件,再调用mkcramfs去制作出对应的rootfs镜像文件。 一切似乎都很完美,但是,正是这假象,迷惑了单纯的偶们,导致从没有怀疑过buildroot,竟然会如此愚蠢,将那些特殊的设备文件,生成为普通的文件,因此,制作出来的rootfs,肯定是不能用的,因为各种设备节点都不对。。。
然后才有了上面的,对此buildroot的编译过程的深度调查,最后,终于算是搞明白了具体的原因:
下面先列出来我的研究过程:
crifan@crifan-laptop:buildroot-2009.11$ /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/fakeroot — mknod output/target/dev/mtd0 c 254 0
crifan@crifan-laptop:buildroot-2009.11$ ls output/target/dev -lh
总用量 0
-rw-r–r– 1 crifan crifan 0 2010-04-16 22:44 mtd0
crifan@crifan-laptop:buildroot-2009.11$ mknod output/target/dev/mtd c 254 1
mknod: "output/target/dev/mtd": 操作不允许
crifan@crifan-laptop:buildroot-2009.11$ sudo mknod output/target/dev/mtd c 254 1
[sudo] password for crifan:
crifan@crifan-laptop:buildroot-2009.11$ ls output/target/dev -lh
总用量 0
crw-r–r– 1 root    root    254, 1 2010-04-16 22:45 mtd
-rw-r–r– 1 crifan crifan       0 2010-04-16 22:44 mtd0
crifan@crifan-laptop:buildroot-2009.11$ rm output/^C
crifan@crifan-laptop:buildroot-2009.11$ /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/fakeroot
root@crifan-laptop:buildroot-2009.11# mknod output/target/dev/mtdblock0 b 220 0
root@crifan-laptop:buildroot-2009.11# ls output/target/dev -lh
总用量 0
crw-r–r– 1 root root 254, 1 2010-04-16 22:45 mtd
-rw-r–r– 1 root root       0 2010-04-16 22:44 mtd0
brw-r–r– 1 root root 220, 0 2010-04-16 22:50 mtdblock0
root@crifan-laptop:buildroot-2009.11# exit
exit
crifan@crifan-laptop:buildroot-2009.11$ ls output/target/dev -lh
总用量 0
crw-r–r– 1 root    root    254, 1 2010-04-16 22:45 mtd
-rw-r–r– 1 crifan crifan       0 2010-04-16 22:44 mtd0
-rw-r–r– 1 crifan crifan       0 2010-04-16 22:50 mtdblock0
crifan@crifan-laptop:buildroot-2009.11$ /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/fakeroot
root@crifan-laptop:buildroot-2009.11# ls output/target/dev -lh
总用量 0
crw-r–r– 1 root root 254, 1 2010-04-16 22:45 mtd
-rw-r–r– 1 root root       0 2010-04-16 22:44 mtd0
-rw-r–r– 1 root root       0 2010-04-16 22:50 mtdblock0
root@crifan-laptop:buildroot-2009.11# exit
exit
crifan@crifan-laptop:buildroot-2009.11$ ls output/target/dev -lh
总用量 0
crw-r–r– 1 root    root    254, 1 2010-04-16 22:45 mtd
-rw-r–r– 1 crifan crifan       0 2010-04-16 22:44 mtd0
-rw-r–r– 1 crifan crifan       0 2010-04-16 22:50 mtdblock0
crifan@crifan-laptop:buildroot-2009.11$

从上面的操作中,我们很容易看出,
本身makedevs是可以正常工作的。
而且fakeroot看起来,也是可以正常帮你伪装成root用户的,可以去mknod创建设备节点,不过实际上,有个问题,就是虽然在fakeroot伪装下,可以创建设备文件,但是,当从fakeroot中退出,回到普通用户的时候,此时那些在fakeroot的时候是设备的文件的那些文件,就变成了普通文件,也就是说,在fakeroot伪装成的root状态下,创建的那些设备文件,其作用范围,或者说有效范围,仅仅是当你是处于fakeroot的时候,一旦退出此伪装的root,回到普通的users,我这里是crifan用户,那么那些文件,就失去了特殊的设备文件的属性,变成普通的,属于当前用户的文件了。
因此,之前的问题,即在buildroot下,make出来的rootfs中的设备文件,都是普通文件,而不是特殊的带设备主次设备号的设备文件,的根据原因就是:
[问题根本原因]
因为我们要制作rootfs,需要设备文件/设备节点,
所以要用到makedevs或mknod去生成这些设备节点,
但是对于制作设备节点,Linux下面必须要root权限才可以,而我们buildroot本身设计的时候,就是期望让你使用普通用户权限也可以完全操作buildroot,而不是非要你用root不可,这样便于buildroot的编译开发,
因此,就利用到了一个叫做fakeroot的工具,就是帮助你在非root用户,即普通用户的权限下,可以暂时伪装成root用户,去做一些只有在root权限下才可以做的事情,包括这里所需要的,制作设备节点,而fakeroot工具的核心机制,就是只是假装成root,而非真正的root:
“Of course, the programs run from a fakeroot session cannot really do privileged system calls; fakeroot keeps an in-memory database of file ownerships and such things.”
关于fakeroot的特性,详情请参见:
http://www.scratchbox.org/documentation/user/scratchbox-1.0/html/fakeroot.html
所以,在退出fakeroot状态,回到普通用户的时候,之前在fakeroot情况下,创建的那些设备文件,就变成了普通文件了,不过如果此时在进入fakeroot,还可以看到之前设置的状态,即的确是我们所期望的设备文件,只不过是退出fakeroot,就回到普通文件而已。
这个问题,我觉得,怎么说,也算是一个比较大的bug了,但是很奇怪的,网上找了N 久,竟然没见到有人说起这个事情。这是无语了。
[workaround(workaround,中文可以理解为:暂时能凑合用的所谓的办法,但是实际上没有根本性地解决问题)]
知道原因了,按理来说就应该很好解决,但是对于此问题,却是比较麻烦,好像目前看来,没有特别的好的,根本性的解决办法,只能是在第一次buildroot的make编译完成之后,去先删除旧的那些只是普通文件的设备文件,然后,自己以root权限,重新生成我们所要的,真正的设备文件,即要做,前面已经写过的,类似于下面这些动作:
crifan@crifan-laptop:buildroot-2009.11$ rm output/target/dev/* -rf
crifan@crifan-laptop:buildroot-2009.11$ sudo /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/host/usr/bin/makedevs -d target/generic/device_table.txt /home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target
[sudo] password for crifan:
rootdir=/home/crifan/develop/buildroot/as353x/buildroot-2009.11/output/target
table='target/generic/device_table.txt'

但要注意,这些文件,也都是root所拥有,所以,以后用其他工具去根据此root文件夹及其下面的内容,去制作rootfs镜像的时候,比如我用mkyaffs2image,就要以root权限去制作,否则会出现那些设备文件没权限访问的问题。然后制作出来的rootfs镜像文件,如果想要拷贝到别的地方,也别忘了在拷贝之后,进行chown去将此文件权限换成对应的用户,否则,对应的用户,就是连最普通的读该rootfs,都没权限,这样的问题,会很让人崩溃的。。。
这样的buildroot中的,应该可以称作bug的问题,期待别人的解决ing….,不过,想必,就是fakeroot的作者,好像,也很难有太好的彻底解决此问题的办法吧,否则,就违背了Linux的文件权限管理了。。。

转载请注明:在路上 » 【workaround】buildroot下面make编译,最后生成的rootfs中的特殊的设备文件,实际是普通文件

与本文相关的文章

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. YY心若冰清13年前 (2011-10-24)回复
  2. 好文章! 谢谢。
    ryan321614年前 (2010-09-15)回复
86 queries in 0.175 seconds, using 23.09MB memory