製做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. }  









閱讀全文

相關文章
相關標籤/搜索