制做initrd(2):update-initramfs和mkinitramfs脚本分析

 前一篇文章<制做initrd(1):向initrd内部更新驱动模块>提到更新initrd.img镜像时须要运行update-initramfs命令。起初觉得是二进制文件,网上胡乱搜索一通发现update-initramfs和mkinitramfs两个命令同为脚本文件,既然是shell脚本那必须得分析内容并备忘。html


[cpp] view plain copynode

  1. root@ubuntu:~# file `which update-initramfs`  linux

  2. /usr/sbin/update-initramfs: POSIX shell script, ASCII text executable  web

  3. root@ubuntu:~# file `which mkinitramfs`  shell

  4. /usr/sbin/mkinitramfs: POSIX shell script, ASCII text executable  ubuntu

    总的来讲,编译内核的最后一步执行make install时会调用update-initramfs,update-initramfs继而调用mkinitramfs生成initrd.img。所以,mkinitramfs是核心脚本,他的做用是啥?若是你有手工作过initrd.img的经历,必定记得这是一个往临时initrd目录copy文件的繁琐过程,mkinitramfs则用脚本替代了手工操做(真伟大,还把人逼失业了!):1).在临时initrd目录下构建FHS规定的文件系统;2).按/etc/initramfs-tools/module和/etc/modules文件的配置,往lib/modules/目录拷贝模块,同时生成模块依赖文件modules.dep,之后内核启动后会从initramfs中(initrd.img被解压到内存中)按模块依赖关系modprobe模块;3).拷贝/etc/initramfs-tools/scripts和/usr/share/initramfs-tools/scripts下的配置文件到conf/目录下,之后内核启动,建立第一个进程init(initrd.img根目录下init.sh文件)会从conf/*读取配置,按必定的顺序加载模块/执行程序;4).模块的加载离不开modprobe工具集,所以须要拷贝modprobe工具集及其余工具到initrd目录结构下,同时解决这些工具的依赖关系(依赖的so文件的路径);5).全部步骤完成,调用cpio和gzip工具打包压缩临时initrd目录结构。c#


    上面是mkinitramfs总体流程的归纳,下面直接贴注释后脚本,如注释有误请在留言栏告诉我,谢谢~缓存

    首先是update-initramfs脚本,仅注释了执行update-initramfs -u更新initrd.img时的脚本执行流。脚本的开始定义了一些变量,而后跳去执行L400+以后的while getopts... do--按命令参数设置不一样的运行模式。以后,按运行模式,进入不一样的函数,以执行update-initramfs -u为例,进入update函数。 ide


[cpp] view plain copy函数

  1. #!/bin/sh  

  2.   

  3. STATEDIR=/var/lib/initramfs-tools  

  4. BOOTDIR=/boot  

  5. CONF=/etc/initramfs-tools/update-initramfs.conf  

  6. USETRIGGERS=true  

  7. mode=""  

  8. version=""  

  9. update_initramfs=yes  

  10. backup_initramfs=no  

  11.   

  12. set -e  

  13. #CONF存在且可读 则source ${CONF}中的设置 即source <span style="font-family: Arial, Helvetica, sans-serif;">/etc/initramfs-tools/update-initramfs.conf文件里的变量</span>  

  14.   

  15. [ -r ${CONF} ] && . ${CONF}  

  16.   

  17. case "$DPKG_MAINTSCRIPT_PACKAGE" in  

  18. linux-image-*)  

  19.     #INITRAMFS_TOOLS_KERNEL_HOOK 长度为0  

  20.     if [ -z "$INITRAMFS_TOOLS_KERNEL_HOOK" ]; then  

  21.         # kernel maintainer script called us directly; ignore  

  22.         # it and let the hook script handle it instead  

  23.         echo "update-initramfs: deferring update (hook will be called later)"  

  24.         exit 0  

  25.     fi  

  26.     ;;  

  27. ?*)  

  28.     if     $USETRIGGERS                     \ #USETRIGGERS=true  

  29.         && [ $# = 1 ]                       \ #参数数量==1  

  30.         && [ x"$1" = x-u ]                  \ #第一个参数是-u  

  31.         && dpkg-trigger --check-supported 2>/dev/null  

  32.     then  

  33.         if dpkg-trigger --no-await update-initramfs; then  

  34.             echo "update-initramfs: deferring update (trigger activated)"  

  35.             exit 0  

  36.         fi  

  37.     fi  

  38.     ;;  

  39. esac  

  40. #开始定义一些函数 先搜索getopts,定位到那继续  

  41. usage()  

  42. {  

  43.     if [ -n "${1:-}" ]; then  

  44.         printf "${*}\n\n" >&2  

  45.     fi  

  46.     cat >&2 << EOF  

  47. Usage: ${0} [OPTION]...  

  48.   

  49. Options:  

  50.  -k [version]   Specify kernel version or 'all'  

  51.  -c     Create a new initramfs  

  52.  -u     Update an existing initramfs  

  53.  -d     Remove an existing initramfs  

  54.  -t     Take over a custom initramfs with this one  

  55.  -b     Set alternate boot directory  

  56.  -v     Be verbose  

  57.  -h     This message  

  58.   

  59. EOF  

  60.     exit 1  

  61. }  

  62.   

  63. # chroot check  

  64. chrooted()  

  65. {  

  66.     # borrowed from udev's postinst  

  67.     if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then  

  68.         # the devicenumber/inode pair of / is the same as that of  

  69.         # /sbin/init's root, so we're *not* in a chroot and hence  

  70.         # return false.  

  71.         return 1  

  72.     fi  

  73. return 0  

  74. }  

  75.   

  76. mild_panic()  

  77. {  

  78.     if [ -n "${1:-}" ]; then  

  79.         printf "${*}\n" >&2  

  80.     fi  

  81.     exit 0  

  82. }  

  83.   

  84. panic()  

  85. {  

  86.     if [ -n "${1:-}" ]; then  

  87.         printf "${*}\n" >&2  

  88.     fi  

  89.     exit 1  

  90. }  

  91.   

  92. verbose()  

  93. {  

  94.     if [ "${verbose}" = 1 ]; then  

  95.         printf "${*}\n"  

  96.     fi  

  97. }  

  98.   

  99. version_exists()  

  100. {  

  101.     [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]  

  102.     return $?  

  103. }  

  104.   

  105. set_initramfs()  

  106. {  

  107.     initramfs="${BOOTDIR}/initrd.img-${version}"  

  108. }  

  109.   

  110.   

  111. # backup initramfs while running  

  112. backup_initramfs()  

  113. {  

  114.     [ ! -r "${initramfs}" ] && return 0  

  115.     initramfs_bak="${initramfs}.dpkg-bak"  

  116.     [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"  

  117.     ln -f "${initramfs}" "${initramfs_bak}" \  

  118.         || cp -a "${initramfs}" "${initramfs_bak}"  

  119.     verbose "Keeping ${initramfs_bak}"  

  120. }  

  121.   

  122. # keep booted initramfs  

  123. backup_booted_initramfs()  

  124. {  

  125.     initramfs_bak="${initramfs}.dpkg-bak"  

  126.   

  127.     # first time run thus no backup  

  128.     [ ! -r "${initramfs_bak}" ] && return 0  

  129.   

  130.     # chroot with no /proc  

  131.     [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0  

  132.   

  133.     # no kept backup wanted  

  134.     [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0  

  135.   

  136.     # no backup yet  

  137.     if [ ! -r "${initramfs}.bak" ]; then  

  138.         mv -f ${initramfs_bak} "${initramfs}.bak"  

  139.         verbose "Backup ${initramfs}.bak"  

  140.         return 0  

  141.     fi  

  142.   

  143.     # keep booted initramfs  

  144.     boot_initramfs=  

  145.     uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)  

  146.     if [ -n "$uptime_days" ]; then  

  147.         boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})  

  148.     fi  

  149.     if [ -n "${boot_initramfs}" ]; then  

  150.         mv -f "${initramfs_bak}" "${initramfs}.bak"  

  151.         verbose "Backup ${initramfs}.bak"  

  152.         return 0  

  153.     fi  

  154.     verbose "Removing current backup ${initramfs_bak}"  

  155.     rm -f ${initramfs_bak}  

  156. }  

  157.   

  158. # nuke generated copy  

  159. remove_initramfs_bak()  

  160. {  

  161.     [ -z "${initramfs_bak:-}" ] && return 0  

  162.     rm -f "${initramfs_bak}"  

  163.     verbose "Removing ${initramfs_bak}"  

  164. }  

  165.   

  166.   

  167. generate_initramfs()  

  168. {  

  169.     echo "update-initramfs: Generating ${initramfs}"  

  170.     OPTS="-o"  

  171.     if [ "${verbose}" = 1 ]; then  

  172.         OPTS="-v ${OPTS}"  

  173.     fi  

  174.     #if分支其实作这两件事  

  175.     #mkinitramfs -o /boot/initrd.img-`uname -r`.new  ${version}  

  176.     #mv /boot/initrd.img-`uname -r`.new /boot/initrd.img-`uname -r`  

  177.       

  178.     if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then  

  179.         mv -f "${initramfs}.new" "${initramfs}"  

  180.         set_sha1  

  181.     else  

  182.         mkinitramfs_return="$?"  

  183.         remove_initramfs_bak  

  184.         rm -f "${initramfs}.new"  

  185.         if [ "$mkinitramfs_return" = "2" ]; then  

  186.             # minversion wasn't met, exit 0  

  187.             exit 0  

  188.         fi  

  189.         echo "update-initramfs: failed for ${initramfs} with $mkinitramfs_return." >&2  

  190.         exit $mkinitramfs_return  

  191.     fi  

  192. }  

  193.   

  194. # lilo call  

  195. run_lilo()  

  196. {  

  197.     # show lilo errors on failure  

  198.     if ! lilo -t  > /dev/null 2>&1 ; then  

  199.         echo "ERROR lilo fails for new ${initramfs}:" >&2  

  200.         echo  

  201.         lilo -t  

  202.     fi  

  203.     lilo  

  204. }  

  205.   

  206. # Invoke bootloader  

  207. run_bootloader()  

  208. {  

  209.     # invoke policy conformant bootloader hooks  

  210.     if [ -d /etc/initramfs/post-update.d/ ]; then  

  211.         run-parts --arg=${version} --arg=${initramfs} \  

  212.             /etc/initramfs/post-update.d/  

  213.         return 0  

  214.     fi  

  215. }  

  216.   

  217. compare_sha1()  

  218. {  

  219.     sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1  

  220.     return $?  

  221. }  

  222.   

  223. # Note that this must overwrite so that updates work.  

  224. set_sha1()  

  225. {  

  226.     sha1sum "${initramfs}" > "${STATEDIR}/${version}"  

  227. }  

  228.   

  229. delete_sha1()  

  230. {  

  231.     rm -f "${STATEDIR}/${version}"  

  232. }  

  233.   

  234. # ro /boot is not modified  

  235. ro_boot_check()  

  236. {  

  237.     # check irrelevant inside of a chroot  

  238.     if [ ! -r /proc/mounts ] || chrooted; then  

  239.         return 0  

  240.     fi  

  241.   

  242.     boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \  

  243.         && $2 == "/boot") print "ro"}' /proc/mounts)  

  244.     if [ -n "${boot_opts}" ]; then  

  245.         echo "WARNING: /boot is ro mounted."  

  246.         echo "update-initramfs: Not updating ${initramfs}"  

  247.         exit 0  

  248.     fi  

  249. }  

  250.   

  251. get_sorted_versions()  

  252. {  

  253.     version_list=""  

  254.   

  255.     for gsv_x in "${STATEDIR}"/*; do  

  256.         gsv_x="$(basename "${gsv_x}")"  

  257.         if [ "${gsv_x}" = '*' ]; then  

  258.             return 0  

  259.         fi  

  260.         worklist=""  

  261.         for gsv_i in $version_list; do  

  262.             if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then  

  263.                 worklist="${worklist} ${gsv_x} ${gsv_i}"  

  264.                 gsv_x=""  

  265.             else  

  266.                 worklist="${worklist} ${gsv_i}"  

  267.             fi  

  268.         done  

  269.         if [ "${gsv_x}" != "" ]; then  

  270.             worklist="${worklist} ${gsv_x}"  

  271.         fi  

  272.         version_list="${worklist}"  

  273.     done  

  274.   

  275.     verbose "Available versions: ${version_list}"  

  276. }  

  277.   

  278. set_current_version()  

  279. {  

  280.     if [ -f /boot/initrd.img-`uname -r` ]; then  

  281.         version=`uname -r`  

  282.     fi  

  283. }  

  284.   

  285. set_linked_version()  

  286. {  

  287.     linktarget=  

  288.     if [ -e /initrd.img ] && [ -L /initrd.img ]; then  

  289.         linktarget="$(basename "$(readlink /initrd.img)")"  

  290.     fi  

  291.   

  292.     if [ -e /boot/initrd.img ] && [ -L /boot/initrd.img ]; then  

  293.         linktarget="$(basename "$(readlink /boot/initrd.img)")"  

  294.     fi  

  295.   

  296.     if [ -z "${linktarget}" ]; then  

  297.         return  

  298.     fi  

  299.   

  300.     version="${linktarget##initrd.img-}"  

  301. }  

  302.   

  303. set_highest_version()  

  304. {  

  305.     get_sorted_versions  

  306.     if [ -z "${version_list}" ]; then  

  307.         version=  

  308.         return  

  309.     fi  

  310.     set -- ${version_list}  

  311.     version=${1}  

  312. }  

  313.   

  314. create()  

  315. {  

  316.     if [ -z "${version}" ]; then  

  317.         usage "Create mode requires a version argument"  

  318.     fi  

  319.   

  320.     set_initramfs  

  321.   

  322.     if [ "${takeover}" = 0 ]; then  

  323.         if version_exists "${version}"; then  

  324.             panic "Cannot create version ${version}: already exists"  

  325.         fi  

  326.   

  327.         if [ -e "${initramfs}" ]; then  

  328.             panic "${initramfs} already exists, cannot create."  

  329.         fi  

  330.     fi  

  331.   

  332.     generate_initramfs  

  333. }  

  334.   

  335. update()  

  336. {  

  337.     #update_initramfs定义在/etc/initramfs-tools/update_initramfs.conf文件中  

  338.     #在本文件开始处被包含进来,值为update_initramfs=yes  

  339.     if [ "${update_initramfs}" = "no" ]; then  

  340.         echo "update-initramfs: Not updating initramfs."  

  341.         exit 0  

  342.     fi  

  343.   

  344.     if [ -z "${version}" ]; then  

  345.         set_highest_version  

  346.     fi  

  347.   

  348.     if [ -z "${version}" ]; then  

  349.         set_linked_version  

  350.     fi  

  351.   

  352.     if [ -z "${version}" ]; then  

  353.         #等效version=`uname -r`  

  354.         set_current_version  

  355.     fi  

  356.   

  357.     if [ -z "${version}" ]; then  

  358.         verbose "Nothing to do, exiting."  

  359.         exit 0  

  360.     fi  

  361.     #initramfs="/boot/initrd.img-`uname -r`"  

  362.     set_initramfs  

  363.   

  364.     ro_boot_check  

  365.   

  366.     altered_check  

  367.   

  368.     backup_initramfs  

  369.     #准备调用mkinitramfs,进入函数generate_initramfs  

  370.     generate_initramfs  

  371.     #若是系统中存在/etc/initramfs/post-update.d/,就调用函数run_bootloader,ubuntu12.04并不存在这个目录  

  372.     run_bootloader  

  373.   

  374.     backup_booted_initramfs  

  375. }  

  376.   

  377. delete()  

  378. {  

  379.     if [ -z "${version}" ]; then  

  380.         usage "Delete mode requires a version argument"  

  381.     fi  

  382.   

  383.     set_initramfs  

  384.   

  385.     if [ "${takeover}" = 0 ]; then  

  386.         if [ ! -e "${initramfs}" ]; then  

  387.             panic "Cannot delete ${initramfs}, doesn't exist."  

  388.         fi  

  389.   

  390.         if ! version_exists "${version}"; then  

  391.             panic "Cannot delete version ${version}: Not created by this utility."  

  392.         fi  

  393.     fi  

  394.   

  395.     altered_check  

  396.   

  397.     echo "update-initramfs: Deleting ${initramfs}"  

  398.   

  399.     delete_sha1  

  400.   

  401.     rm -f "${initramfs}" "${initramfs}.bak"  

  402. }  

  403.   

  404. # Check for update mode on existing and modified initramfs  

  405. altered_check()  

  406. {  

  407.     # No check on takeover  

  408.     [ "${takeover}" = 1 ] && return 0  

  409.     if [ ! -e "${initramfs}" ]; then  

  410.         mild_panic "${initramfs} does not exist. Cannot update."  

  411.     fi  

  412.     if ! compare_sha1; then  

  413.         echo "update-initramfs: ${initramfs} has been altered." >&2  

  414.         mild_panic "update-initramfs: Cannot update. Override with -t option."  

  415.     fi  

  416. }  

  417.   

  418. # Defaults  

  419. verbose=0  

  420. yes=0  

  421. # We default to takeover=1 in Ubuntu, but not Debian  

  422. takeover=1  

  423.   

  424. ##  

  425. #可选参数-k和-b后面带其余参数  

  426. #参数存放到flag中,供case判断  

  427. while getopts "k:cudyvtb:h?" flag; do  

  428.     case "${flag}" in  

  429.     k)  

  430.         #-k 后面有值,则保存在OPTARG(-k kernel version)  

  431.         version="${OPTARG}"  

  432.         ;;  

  433.     c)  

  434.         mode="c"  

  435.         ;;  

  436.     d)  

  437.         mode="d"  

  438.         ;;  

  439.     u)  

  440.         mode="u"  

  441.         ;;  

  442.     v)  

  443.         verbose="1"  

  444.         ;;  

  445.     y)  

  446.         yes="1"  

  447.         ;;  

  448.     t)  

  449.         takeover="1"  

  450.         ;;  

  451.     b)  

  452.         BOOTDIR="${OPTARG}"  

  453.         if [ ! -d "${BOOTDIR}" ]; then  

  454.             echo "Error: ${BOOTDIR} is not a directory." >&2  

  455.             exit 1  

  456.         fi  

  457.         ;;  

  458.     h|?)  

  459.         usage  

  460.         ;;  

  461.     esac  

  462. done  

  463. #常见的获取参数的最后一项的方法  

  464. shift $((${OPTIND} - 1))  

  465.   

  466. if [ $# -ne 0 ]; then  

  467.     echo "Invalid argument for option -k." >&2  

  468.     usage  

  469. fi  

  470.   

  471. # Validate arguments  

  472. #${mode}为空  

  473. if [ -z "${mode}" ]; then  

  474.     usage "You must specify at least one of -c, -u, or -d."  

  475. fi  

  476.   

  477. #若是输入-k all 或者/etc/initramfs-tools/update-initramfs中的update_initramfs的值为all  

  478. if [ "${version}" = "all" ] \  

  479.     || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then  

  480.     : FIXME check for --yes, and if not ask are you sure  

  481.     get_sorted_versions  

  482.     if [ -z "${version_list}" ]; then  

  483.         verbose "Nothing to do, exiting."  

  484.         exit 0  

  485.     fi  

  486.   

  487.     OPTS="-b ${BOOTDIR}"  

  488.     if [ "${verbose}" = "1" ]; then  

  489.         OPTS="${OPTS} -v"  

  490.     fi  

  491.     if [ "${takeover}" = "1" ]; then  

  492.         OPTS="${OPTS} -t"  

  493.     fi  

  494.     if [ "${yes}" = "1" ]; then  

  495.         OPTS="${OPTS} -y"  

  496.     fi  

  497.     for u_version in ${version_list}; do  

  498.         verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"  

  499.         "${0}" -${mode} -k "${u_version}" ${OPTS}  

  500.     done  

  501.     exit 0  

  502. fi  

  503.   

  504. #只讨论update-initramfs -u的状况  

  505. case "${mode}" in  

  506.     c)  

  507.         create  

  508.         ;;  

  509.     d)  

  510.         delete  

  511.         ;;  

  512.     u)  

  513.         #-u 则调用update函数  

  514.         update  

  515.         ;;  

  516. esac  

    若是你耐心够好,看到这,差很少也该跟着执行流进入到mkinitramfs脚本。update函数的结尾依次执行generate_initramfs函数和mkinitramfs命令。就此进入mkinitramfs脚本。mkinitramfs脚本开始处也是定义一些变量,而后include两个重要的辅助脚本/usr/share/initramfs-tools/scripts/functions和/usr/share/initramfs-tools/hook-functions。一些重要的函数定义在这两个脚本中。mkinitramfs在这两个脚本的辅助下完成了前述临时initrd目录的制做

[cpp] view plain copy

  1. #!/bin/sh  

  2.   

  3. umask 0022  

  4. export PATH='/usr/bin:/sbin:/bin'  

  5.   

  6. # Defaults  

  7. keep="n"  

  8. CONFDIR="/etc/initramfs-tools"  

  9. verbose="n"  

  10. #若是/bin/busybox文件夹存在 变量BUSYBOXDIR=/bin  

  11. test -e /bin/busybox && BUSYBOXDIR=/bin  

  12. test -e /usr/lib/initramfs-tools/bin/busybox && BUSYBOXDIR=/usr/lib/initramfs-tools/bin  

  13. export BUSYBOXDIR  

  14.   

  15. OPTIONS=`getopt -o c:d:ko:r:v -n "$0" -- "$@"`  

  16.   

  17. # Check for non-GNU getopt  

  18. if [ $? != 0 ] ; then echo "W: non-GNU getopt" >&2 ; exit 1 ; fi  

  19.   

  20. eval set -- "$OPTIONS"  

  21. #update-initramfs调用mkinitramfs时命令为  

  22. #mkinitramfs -o /boot/initrd.img-`uname -r`.new ${version},所以进入-o分支  

  23. while truedo  

  24.     case "$1" in  

  25.     -c)  

  26.         compress="$2"  

  27.         shift 2  

  28.         ;;  

  29.     -d)  

  30.         CONFDIR="$2"  

  31.         shift 2  

  32.         if [ ! -d "${CONFDIR}" ]; then  

  33.             echo "${0}: ${CONFDIR}: Not a directory" >&2  

  34.             exit 1  

  35.         fi  

  36.         ;;  

  37.     -o)  

  38.         #outfile=/boot/initrd.img-`uname -r`.new  

  39.         outfile="$2"  

  40.         shift 2  

  41.         ;;  

  42.     -k)  

  43.         keep="y"  

  44.         shift  

  45.         ;;  

  46.     -r)  

  47.         ROOT="$2"  

  48.         shift 2  

  49.         ;;  

  50.     -v)  

  51.         verbose="y"  

  52.         shift  

  53.         ;;  

  54.     --)  

  55.         shift  

  56.         break  

  57.         ;;  

  58.     *)  

  59.         echo "Internal error!" >&2  

  60.         exit 1  

  61.         ;;  

  62.     esac  

  63. done  

  64.   

  65. # For dependency ordered mkinitramfs hook scripts.  

  66. #引用这两处的文件 这是一些帮助函数  

  67. . /usr/share/initramfs-tools/scripts/functions  

  68. . /usr/share/initramfs-tools/hook-functions  

  69.   

  70. #引用/etc/initramfs-tools/initramfs.conf 这个文件有关于本地启动或者nfs启动的信息  

  71. "${CONFDIR}/initramfs.conf"  

  72. EXTRA_CONF=''  

  73. #/usr/share/initramfs-tools/conf.d/目录下为空  

  74. #/etc/initramfs-tools/initramfs.conf/conf.d/ 目录下只有resume文件  

  75. for i in /usr/share/initramfs-tools/conf.d/* ${CONFDIR}/conf.d/*; do 

  76.     [ -e $i ] && EXTRA_CONF="${EXTRA_CONF} $(basename $i \ 

  77.         | grep '^[[:alnum:]][[:alnum:]\._-]*$' | grep -v '\.dpkg-.*$')"; 

  78. done 

  79. # FIXME: deprecated those settings on mkinitramfs run 

  80. #    these conf dirs are for boot scripts and land on initramfs 

  81. for i in ${EXTRA_CONF}; do 

  82.     if [ -e  ${CONFDIR}/conf.d/${i} ]; then 

  83.         . ${CONFDIR}/conf.d/${i} 

  84.     elif [ -e  /usr/share/initramfs-tools/conf.d/${i} ]; then 

  85.         . /usr/share/initramfs-tools/conf.d/${i} 

  86.     fi 

  87. done 

  88.  

  89. # source package confs 

  90. for i in /usr/share/initramfs-tools/conf-hooks.d/*; do 

  91.     if [ -e "${i}" ]; then 

  92.         . "${i}" 

  93.     fi 

  94. done 

  95. #UMASK 非空 不过没找到何处设置了这个变量 

  96. if [ -n "${UMASK:-}" ]; then 

  97.     umask "${UMASK}" 

  98. fi 

  99. #outfile为空 也不成立 

  100. if [ -z "${outfile}" ]; then 

  101.     usage 

  102. fi 

  103.  

  104. #生成新的空的initrd.img-`uname -r`文件 

  105. touch "$outfile" 

  106. outfile="$(readlink -f "$outfile")" 

  107.  

  108. # And by "version" we really mean path to kernel modules 

  109. # This is braindead, and exists to preserve the interface with mkinitrd 

  110. if [ ${#} -ne 1 ]; then 

  111.     version="$(uname -r)" 

  112. else 

  113.     version="${1}" 

  114. fi 

  115.  

  116. # Check that we're using a new enough kernel version, first for ourselves, 

  117. # then for each of the hooks, which can have a MINKVER variable defined 

  118. check_minkver ${version} 

  119. check_minkver ${version} /usr/share/initramfs-tools/hooks 

  120. check_minkver ${version} ${CONFDIR}/hooks 

  121.  

  122. case "${version}" in 

  123. #/lib/modules/*/目录下除了/之外的文件,这是指除了该目录下除了子目录之外的全部文件?  

  124. /lib/modules/*/[!/]*) 

  125.     ;; 

  126. /lib/modules/[!/]*) 

  127.     version="${version#/lib/modules/}" 

  128.     version="${version%%/*}" 

  129.     ;; 

  130. esac 

  131.  

  132. case "${version}" in 

  133. */*)  

  134.     echo "$PROG: ${version} is not a valid kernel version" >&2  

  135.     exit 1  

  136.     ;;  

  137. esac  

  138.   

  139. # Check userspace and kernel support for compressed initramfs images  

  140. if [ -z "${compress:-}" ]; then  

  141.     #COMPRESS=gzip gzip压缩  

  142.     compress=${COMPRESS}  

  143. else  

  144.     COMPRESS=${compress}  

  145. fi  

  146.   

  147. if ! command -v "${compress}" >/dev/null 2>&1; then  

  148.     compress=gzip  

  149.     [ "${verbose}" = y ] && \  

  150.         echo "No ${COMPRESS} in ${PATH}, using gzip"  

  151.     COMPRESS=gzip  

  152. fi  

  153.   

  154. #/boot/config-${version}匹配以config_rd_${COMPRESS%p}开头  

  155. if ! `grep -q -i ^config_rd_${COMPRESS%p} /boot/config-${version}` ; then  

  156.     compress=gzip  

  157.     [ "${verbose}" = y ] && \  

  158.         echo "linux-2.6 misses ${COMPRESS} support, using gzip"  

  159. fi  

  160.   

  161. "${compress}" = lzop ] && compress="lzop -9"  

  162. "${compress}" = xz ] && compress="xz -8 --check=crc32"  

  163.   

  164. if [ -d "${outfile}" ]; then  

  165.     echo "${outfile} is a directory" >&2  

  166.     exit 1  

  167. fi  

  168. #要编译内核的版本  

  169. MODULESDIR="/lib/modules/${version}"  

  170.   

  171. if [ ! -e "${MODULESDIR}" ]; then  

  172.     echo "WARNING: missing ${MODULESDIR}"  

  173.     echo "Device driver support needs thus be built-in linux image!"  

  174. fi  

  175. #检测模块依赖性 不存在模块依赖文件 怎生成  

  176. if [ ! -e "${MODULESDIR}/modules.dep" ]; then  

  177.     depmod ${version}  

  178. fi  

  179. #在/tmp下生成名为mkinitramfs_fb9BN这样的文件  

  180. DESTDIR="$(mktemp -d ${TMPDIR:-/tmp}/mkinitramfs_XXXXXX)" || exit 1  

  181. chmod 755 "${DESTDIR}"  

  182.   

  183. # do not execute cache_run_scripts() if mounted with noexec  

  184. NOEXEC=""  

  185. #找到临时文件的挂载点 fs=/  

  186. fs=$(df -P $DESTDIR | tail -1 | awk '{print $6}')  

  187. if [ -n "$fs" ] && mount | grep -q "on $fs .*noexec" ; then  

  188.     NOEXEC=1  

  189. fi  

  190.   

  191. __TMPCPIOGZ="$(mktemp ${TMPDIR:-/tmp}/mkinitramfs-OL_XXXXXX)" || exit 1  

  192.   

  193. DPKG_ARCH=`dpkg --print-architecture`  

  194.   

  195. # Export environment for hook scripts.  

  196. #  

  197. export MODULESDIR  

  198. export version  

  199. export CONFDIR  

  200. export DESTDIR  

  201. export DPKG_ARCH  

  202. export verbose  

  203. export MODULES  

  204. export BUSYBOX  

  205. export COMPCACHE_SIZE  

  206.   

  207. # Private, used by 'catenate_cpiogz'.  

  208. export __TMPCPIOGZ  

  209.   

  210. #在/tmp/mkinitramfs_fb9BNB文件夹下生成bin conf/conf.d etc lib/modules run sbin scripts /lib/modules/${version}这些文件夹  

  211. #这是在制做根文件系统  

  212. for d in bin conf/conf.d etc lib/modules run sbin scripts ${MODULESDIR}; do  

  213.     mkdir -p "${DESTDIR}/${d}"  

  214. done  

  215.   

  216. # Copy the modules.order file in  

  217. if [ -f "${MODULESDIR}/modules.order" ]; then  

  218.     cp -p "${MODULESDIR}/modules.order" \  

  219.         "${DESTDIR}${MODULESDIR}/modules.order"  

  220. fi  

  221.   

  222. # MODULES=list case.  Always honour.  

  223. for x in "${CONFDIR}/modules" /usr/share/initramfs-tools/modules.d/*; do 

  224.     if [ -f "${x}" ]; then 

  225.         #add_modules_from_file定义在/usr/share/initramfs-tools/hook-functions中 

  226.         #这里就是add_modules_from_file /etc/initramfs-tools/modules 

  227.         #/etc/initramfs-tools/modules中含有要添加到initrd镜像中的modules 

  228.         add_modules_from_file "${x}" 

  229.     fi 

  230. done 

  231.  

  232. # 没有找到MODULES定义的文件 按注释MODULES=most 

  233. # MODULES=most is default 

  234. case "${MODULES}" in 

  235. dep) 

  236.     dep_add_modules 

  237.     ;; 

  238. most) 

  239.     #auto_add_modules仍然定义在/usr/share/initramfs-tools/hook-functions中 

  240.     auto_add_modules 

  241.     ;; 

  242. netboot) 

  243.     auto_add_modules base 

  244.     auto_add_modules net 

  245.     ;; 

  246. list) 

  247.     # nothing to add 

  248.     ;; 

  249. *) 

  250.     echo "W: mkinitramfs: unsupported MODULES setting: ${MODULES}." 

  251.     echo "W: mkinitramfs: Falling back to MODULES=most." 

  252.     auto_add_modules 

  253.     ;; 

  254. esac 

  255.  

  256. # Resolve hidden dependencies 

  257. hidden_dep_add_modules 

  258.  

  259. # First file executed by linux-2.6 

  260. #拷贝init文件,init是系统启动后进入根文件系统以后启动的第一个进程 

  261. cp -p /usr/share/initramfs-tools/init ${DESTDIR}/init 

  262.  

  263. # add existant boot scripts 

  264. #递归搜索/usr/share/initramfs-tools/scripts/目录下全部配置文件(init-top/all_generic_ide udev...),若是文件中不含有"OPTION="字段, 

  265. #则在${DESTDIR}/scripts/目录中建立对应目录,并把文件拷贝到该目录中 

  266. for b in $(cd /usr/share/initramfs-tools/scripts/ && find . \ 

  267.     -regextype posix-extended -regex '.*/[[:alnum:]\._-]+$' -type f); do  

  268.     option=$(sed '/^OPTION=/!d;$d;s/^OPTION=//;s/[[:space:]]*$//' "/usr/share/initramfs-tools/scripts/${b}")  

  269.     [ -z "${option}" ] || eval test -n \"\${$option}\" -a \"\${$option}\" != \"n\" || continue  

  270.   

  271.     [ -d "${DESTDIR}/scripts/$(dirname "${b}")" ] \  

  272.         || mkdir -p "${DESTDIR}/scripts/$(dirname "${b}")"  

  273.     cp -p "/usr/share/initramfs-tools/scripts/${b}" \  

  274.         "${DESTDIR}/scripts/$(dirname "${b}")/"  

  275. done  

  276. #对于/etc/initramfs-tools/scripts下的文件使用一样的操做  

  277. for b in $(cd "${CONFDIR}/scripts" && find . \  

  278.     -regextype posix-extended -regex '.*/[[:alnum:]\._-]+$' -type f); do  

  279.     option=$(sed '/^OPTION=/!d;$d;s/^OPTION=//;s/[[:space:]]*$//' "${CONFDIR}/scripts/${b}")  

  280.     [ -z "${option}" ] || eval test -n \"\${$option}\" -a \"\${$option}\" != \"n\" || continue  

  281.   

  282.     [ -d "${DESTDIR}/scripts/$(dirname "${b}")" ] \  

  283.         || mkdir -p "${DESTDIR}/scripts/$(dirname "${b}")"  

  284.     cp -p "${CONFDIR}/scripts/${b}" "${DESTDIR}/scripts/$(dirname "${b}")/"  

  285. done  

  286.   

  287. echo "DPKG_ARCH=${DPKG_ARCH}" > ${DESTDIR}/conf/arch.conf  

  288. #把/etc/initramfs-tools/initramfs.conf拷贝到${DESTDIR}/conf目录下,  

  289. #这个文件涉及本地启动和nfs启动,以及加载的驱动MODULES=most  

  290. cp -p "${CONFDIR}/initramfs.conf" ${DESTDIR}/conf  

  291. for i in ${EXTRA_CONF}; do  

  292.     if [ -e "${CONFDIR}/conf.d/${i}" ]; then  

  293.         copy_exec "${CONFDIR}/conf.d/${i}" /conf/conf.d  

  294.     elif [ -e "/usr/share/initramfs-tools/conf.d/${i}" ]; then  

  295.         copy_exec "/usr/share/initramfs-tools/conf.d/${i}" /conf/conf.d  

  296.     fi  

  297. done  

  298.   

  299. # ROOT hardcoding  

  300. if [ -n "${ROOT:-}" ]; then  

  301.     echo "ROOT=${ROOT}" > ${DESTDIR}/conf/conf.d/root  

  302. fi  

  303.   

  304. if ! command -v ldd >/dev/null 2>&1 ; then  

  305.     echo "WARNING: no ldd around - install libc-bin" >&2  

  306.     exit 1  

  307. fi  

  308. #copy_exec定义在hook-functions中  

  309. copy_exec /usr/lib/initramfs-tools/bin/wait-for-root /sbin  

  310.   

  311. # module-init-tools  

  312. copy_exec /sbin/modprobe /sbin  

  313. copy_exec /sbin/rmmod /sbin  

  314. mkdir -p "${DESTDIR}/etc/modprobe.d"  

  315. #拷贝/etc/modprobe.d/下文件到${DESTDIR}/etc/modprobe.d/下  

  316. #这些文件关系到modprobe mod时的行为  

  317. cp -a /etc/modprobe.d/* "${DESTDIR}/etc/modprobe.d/"  

  318.   

  319. # util-linux  

  320. copy_exec /sbin/blkid /sbin  

  321.   

  322. # workaround: libgcc always needed on old-abi arm  

  323. if [ "$DPKG_ARCH" = arm ] || [ "$DPKG_ARCH" = armeb ]; then  

  324.     cp -a /lib/libgcc_s.so.1 "${DESTDIR}/lib/"  

  325. fi  

  326.   

  327. run_scripts /usr/share/initramfs-tools/hooks optional  

  328. run_scripts "${CONFDIR}"/hooks optional  

  329.   

  330. # cache boot run order  

  331. if [ -n "$NOEXEC" ]; then  

  332.     echo "W: TMPDIR is mounted noexec, will not cache run scripts."  

  333. else  

  334.     for b in $(cd "${DESTDIR}/scripts" && find . -mindepth 1 -type d); do  

  335.         cache_run_scripts "${DESTDIR}" "/scripts/${b#./}"  

  336.     done  

  337. fi  

  338.   

  339. # generate module deps  

  340. #生成模块依赖文件  

  341. depmod -a -b "${DESTDIR}" ${version}  

  342. rm -f "${DESTDIR}/lib/modules/${version}"/modules.*map  

  343.   

  344. # make sure that library search path is up to date  

  345. #拷贝/etc/ld.so.conf*到initrd目录结构中对应位置,可执行程序可能依赖非标准路径下的so文件,  

  346. #所以在此调用ldconfig -r分析/${DESTDIR}/etc/ld.so.conf*中列出的非标准搜索路径,并生成  

  347. #缓存文件加速连接速度  

  348. #ldconfig -r ROOT : 此选项改变应用程序的根目录为ROOT(是调用chroot函数实现的).选择此项时,系统默认的配置文件  

  349. #/etc/ld.so.conf,实际对应的为 ROOT/etc/ld.so.conf.如用-r /usr/zzz时,打开配置文件 /etc/ld.so.conf时,实际打开的  

  350. #是/usr/zzz/etc/ld.so.conf文件.用此选项,能够大大增长动态连接库管理的灵活性  

  351. cp -ar /etc/ld.so.conf* "$DESTDIR"/etc/  

  352. if ! ldconfig -r "$DESTDIR" ; then  

  353.     [ $(id -u) != "0" ] \  

  354.     && echo "ldconfig might need uid=0 (root) for chroot()" >&2  

  355. fi  

  356.   

  357. # Apply DSDT to initramfs  

  358. if [ -e "${CONFDIR}/DSDT.aml" ]; then  

  359.     copy_exec "${CONFDIR}/DSDT.aml" /  

  360. fi  

  361.   

  362. # Remove any looping or broken symbolic links, since they break cpio.  

  363. "${verbose}" = y ] && xargs_verbose="-t"  

  364. (cd "${DESTDIR}" && find . -type l -printf '%p %Y\n' | sed -n 's/ [LN]$//p' \  

  365.     | xargs ${xargs_verbose:-} -rL1 rm -f)  

  366.   

  367. # dirty hack for armhf's double-linker situation; if we have one of  

  368. # the two known eglibc linkers, nuke both and re-create sanity  

  369. if [ "$DPKG_ARCH" = armhf ]; then  

  370.     if [ -e "${DESTDIR}/lib/arm-linux-gnueabihf/ld-linux.so.3" ] || \  

  371.        [ -e "${DESTDIR}/lib/ld-linux-armhf.so.3" ]; then  

  372.         rm -f "${DESTDIR}/lib/arm-linux-gnueabihf/ld-linux.so.3"  

  373.         rm -f "${DESTDIR}/lib/ld-linux-armhf.so.3"  

  374.         cp -aL /lib/ld-linux-armhf.so.3 "${DESTDIR}/lib/"  

  375.         ln -sf /lib/ld-linux-armhf.so.3 "${DESTDIR}/lib/arm-linux-gnueabihf/ld-linux.so.3"  

  376.     fi  

  377. fi  

  378.   

  379. "${verbose}" = y ] && echo "Building cpio ${outfile} initramfs"  

  380. (  

  381. # work around lack of "set -o pipefail" for the following pipe:  

  382. # cd "${DESTDIR}" && find . | cpio --quiet -R 0:0 -o -H newc | gzip >"${outfile}" || exit 1  

  383. #这是建立initramfs的最后一步了 调用cpio和gzip 打包并压缩initramfs目录  

  384. exec 3>&1  

  385. eval `  

  386.     # http://cfaj.freeshell.org/shell/cus-faq-2.html  

  387.     exec 4>&1 >&3 3>&-  

  388.     cd  "${DESTDIR}"  

  389.     {  

  390.         find . 4>&-; echo "ec1=$?;" >&4  

  391.     } | {  

  392.         cpio --quiet -R 0:0 -o -H newc 4>&-; echo "ec2=$?;" >&4  

  393.     } | ${compress} >"${outfile}"  

  394.     echo "ec3=$?;" >&4  

  395. `  

  396. if [ "$ec1" -ne 0 ]; then  

  397.     echo "E: mkinitramfs failure find $ec1 cpio $ec2 $compress $ec3"  

  398.     exit "$ec1"  

  399. fi  

  400. if [ "$ec2" -ne 0 ]; then  

  401.     echo "E: mkinitramfs failure cpio $ec2 $compress $ec3"  

  402.     exit "$ec2"  

  403. fi  

  404. if [ "$ec3" -ne 0 ]; then  

  405.     echo "E: mkinitramfs failure $compress $ec3"  

  406.     exit "$ec3"  

  407. fi  

  408. ) || exit 1  

  409.   

  410. if [ -s "${__TMPCPIOGZ}" ]; then  

  411.     cat "${__TMPCPIOGZ}" >>"${outfile}" || exit 1  

  412. fi  

  413.   

  414. if [ "${keep}" = "y" ]; then  

  415.     echo "Working files in ${DESTDIR} and overlay in ${__TMPCPIOGZ}"  

  416. else  

  417.     rm -rf "${DESTDIR}"  

  418.     rm -rf "${__TMPCPIOGZ}"  

  419. fi  

  420.   

  421. exit 0  

最后贴出hook-functions中用到的几个函数的注释



[cpp] view plain copy

  1. force_load()  

  2. {  

  3.         manual_add_modules ${@}  

  4.         #调用mkinitramfs时设置DESTDIR=/tmp/mkinitramfs_fb9BNB---一个临时根文件系统结构,  

  5.         #把/etc/initramfs-tools/modules中读到的modules加入到/tmp/mkinitramfs_fb9BNB/conf/modules中  

  6.         #前面已经说过update-initramfs -u时会将/etc/initramfs-tools/modules文件中的模块加入到initrd  

  7.         #文件,做为引导加载modules,看来就是在这实现的  

  8.         echo "${@}" >>"${DESTDIR}/conf/modules"  

  9. }  

[cpp] view plain copy

  1. add_modules_from_file()  

  2. {  

  3. # Sanity check  

  4. if [ ! -e "${1}" ]; then  

  5. echo "W: add_modules_from_file: arg1='${1}' does not exist." >&2  

  6. return  

  7. fi  

  8. #从/etc/initramfs-tools/modules中读取非注释的行,模块名和参数分别读入module和args  

  9. #并调用force_load函数  

  10. grep '^[^#]' ${1} | while read module args; do  

  11. [ -n "$module" ] || continue  

  12. force_load "${module}" "${args}"  

  13. done  

  14. }  

[cpp] view plain copy

  1. # $1 = file to copy to ramdisk  

  2. # $2 (optional) Name for the file on the ramdisk  

  3. # Location of the image dir is assumed to be $DESTDIR  

  4. # We never overwrite the target if it exists.  

  5. #拷贝可执行程序到$DESTDIR对应目录下,同时解决可执行程序的依赖库(ldd)  

  6. copy_exec() {  

  7. local src target x nonoptlib  

  8. local libname dirname  

  9.   

  10.   

  11. src="${1}"  

  12. #若是$2(可执行程序所在的目录)为空 则返回$1的值   

  13. target="${2:-$1}"  

  14. #可执行程序不存在就return,不然往下执行  

  15. [ -f "${src}" ] || return 1  

  16. if [ -d "${DESTDIR}/${target}" ]; then  

  17. # check if already copied  

  18. #目录存在而且exe存在则返回  

  19. [ -e "${DESTDIR}/$target/${src##*/}" ] && return 0  

  20. else  

  21. #目录不存在 则建立目录  

  22. [ -e "${DESTDIR}/$target" ] && return 0  

  23. #FIXME: inst_dir  

  24. mkdir -p "${DESTDIR}/${target%/*}"  

  25. fi  

  26. #拷贝host系统的exe文件到initrd目录结构中  

  27. "${verbose}" = "y" ] && echo "Adding binary ${src}"  

  28. cp -pL "${src}" "${DESTDIR}/${target}"  

  29. # Copy the dependant libraries  

  30. #ldd的输出形式为 xxx ==> yyy  

  31. #for循环中的第一个sed是提取第3列中的yyy  

  32. for x in $(ldd ${src} 2>/dev/null | sed -e '  

  33. /\//!d;/linux-gate/d;/ {s/.*=>[[:blank:]]*[[:blank:]].*/\1/};s/[[:blank:]]*[[:blank:]] (.*)/\1/' 2>/dev/null); do  

  34.   

  35.   

  36. # Try to use non-optimised libraries where possible.  

  37. # We assume that all HWCAP libraries will be in tls,  

  38. # sse2, vfp or neon.  

  39. nonoptlib=$(echo "${x}" | sed -e 's#/lib/tlsi686sse2neonvfp.*/lib.#/lib/\2#')  

  40.   

  41. if [ -e "${nonoptlib}" ]; then  

  42. x="${nonoptlib}"  

  43. fi  

  44.   

  45.   

  46. libname=$(basename "${x}")  

  47. dirname=$(dirname "${x}")  

  48. # FIXME inst_lib  

  49. #从host机上拷贝依赖库到initrd目录结构中  

  50. mkdir -p "${DESTDIR}/${dirname}"  

  51. if [ ! -e "${DESTDIR}/${dirname}/${libname}" ]; then  

  52. cp -pL "${x}" "${DESTDIR}/${dirname}"  

  53. "${verbose}" = "y" ] && echo "Adding library ${x}" || true  

  54. fi  

  55. done  

  56. }  









阅读全文

相关文章
相关标签/搜索