Tag Archives: binfmt_misc

初探binfmt_misc

为了使用qemu user mode来做opensuse的系统移植而接触到了binfmt_misc这个东西,但是不知道这东西具体是做什么的,所以现在来一探究竟。

要对一个陌生的事物或概念进行初步的了解当然是找wikipedia了。从binfmt_misc的wiki页面上可以得知,binfmt_misc是内核的一个模块,具有让内核执行任何文件类型的功能。具体来说就是用户通过binfmt_misc的接口向内核注册新的可执行文件类型的解释器,内核在运行这种新的可执行文件的时候就把这个文件当作注册进内核的解释器的一个参数来运行这个解释器(说的有点绕……)。比较常见的用法是让windows的exe程序通过wine在Linux中直接运行,要做到这点需要执行如下命令(没有wine,没验证):

# First load module if not loaded
if [ ! -d /proc/sys/fs/binfmt_misc ]; then
 /sbin/modprobe binfmt_misc
fi
if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
 mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
fi
# Register new executable file format
echo ':DOSWin:M::MZ::/usr/bin/wine:' > /proc/sys/fs/binfmt_misc/register
# Then you can launch exe file directly
chmod a+x /path/to/prog.exe
/path/to/prog.exe

现在简要说明下那一长串被echo进去的字符串吧。这个串是用来描述新格式和相应的解释器的(interpreter)。一共分为7个部分,之间用’:’分隔:

  1. name:新类型的名称,注册成功后会在/proc/sys/fs/binfmt_misc 目录下生成一个新文件,来描述这个新类型;
  2. type:注册的类型,有两个有效值’M’和’E’,M表示使用magic number来识别新类型,E表示用extention(扩展名)来识别新类型;
  3. offset:magic number/mask在文件中的偏移量,以byte为单位,这个不是必须的,默认是0,也可以省略,如 ‘:name:type::magic:mask:interpreter:flag’;
  4. magic:是binfmt_misc用来识别文件类型的byte串,相当于特征码(不同类型的文件如何得到特征码还不清楚),如果type是E那么这部分就填写扩展名;
  5. mask:mask部分于magic部分做按位与操作,然后再匹配与操作之后的串,一般都是一串’xff’,也就是都是1;
  6. interpreter:解释器,可执行文件作为解释器的第一个参数来执行,需要解释器的全路径名;
  7. flag:控制解释器行为的一些flag。

详细的说明可以看Documentation/binfmt_misc.txt。

现在可以玩一些好玩的东西了,比如让jpg文件变成可执行的,用eog打开查看:

echo ':jpg:E::jpg::/usr/bin/eog:' > /proc/sys/fs/binfmt_misc/register
chmod +x pic.jpg
./pic.jpg

这样在运行jpg文件的时候,就会用eog打开这个图片文件。

最后来说说binfmt_misc与使用qemu user mode进行opensuse移植的关系。使用qemu user mode可以在比如x86_64环境下直接运行mipsel的二进制可执行文件(前提是准备好相应的运行时库环境),那么就可以把mipsel的二进制文件的interpreter注册为qemu-mipsel,再结合chroot,就可能实现在x86_64环境下得到mipsel的运行环境,这个运行环境比运行qemu-system-mipsel要快很多,在这个环境下编译打包rpm会节省很多时间。这也是去年做opensuse@arm port gsoc项目的那个学生的做法,比我用system level emulator效率高了非常非常多,不用忍受编译gcc用4天时间这种痛苦了。

但是现在我还没运行成功这个chroot环境,需要进一步折腾,离qemu mips64el user mode就更遥远了。有进展了会写日志的。