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

[cpp] view plain copy

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

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

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

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

总的来说,编译内核的最后一步执行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目录结构。

上面是mkinitramfs整体流程的概括,下面直接贴注释后脚本,如注释有误请在留言栏告诉我,谢谢~

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

[cpp] view plain copy

  1. #!/bin/sh

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

  3. BOOTDIR=/boot

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

  5. USETRIGGERS=true

  6. mode=""

  7. version=""

  8. update_initramfs=yes

  9. backup_initramfs=no

  10. set -e

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

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

  13. case "$DPKG_MAINTSCRIPT_PACKAGE" in

  14. linux-image-*)

  15. #INITRAMFS_TOOLS_KERNEL_HOOK 长度为0

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

  17. # kernel maintainer script called us directly; ignore

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

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

  20. exit 0

  21. fi

  22. ;;

  23. ?*)

  24. if     $USETRIGGERS                     \ #USETRIGGERS=true

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

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

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

  28. then

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

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

  31. exit 0

  32. fi

  33. fi

  34. ;;

  35. esac

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

  37. usage()

  38. {

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

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

  41. fi

  42. cat >&2 << EOF

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

  44. Options:

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

  46. -c     Create a new initramfs

  47. -u     Update an existing initramfs

  48. -d     Remove an existing initramfs

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

  50. -b     Set alternate boot directory

  51. -v     Be verbose

  52. -h     This message

  53. EOF

  54. exit 1

  55. }

  56. # chroot check

  57. chrooted()

  58. {

  59. # borrowed from udev's postinst

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

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

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

  63. # return false.

  64. return 1

  65. fi

  66. return 0

  67. }

  68. mild_panic()

  69. {

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

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

  72. fi

  73. exit 0

  74. }

  75. panic()

  76. {

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

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

  79. fi

  80. exit 1

  81. }

  82. verbose()

  83. {

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

  85. printf "${*}\n"

  86. fi

  87. }

  88. version_exists()

  89. {

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

  91. return $?

  92. }

  93. set_initramfs()

  94. {

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

  96. }

  97. # backup initramfs while running

  98. backup_initramfs()

  99. {

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

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

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

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

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

  105. verbose "Keeping ${initramfs_bak}"

  106. }

  107. # keep booted initramfs

  108. backup_booted_initramfs()

  109. {

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

  111. # first time run thus no backup

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

  113. # chroot with no /proc

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

  115. # no kept backup wanted

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

  117. # no backup yet

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

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

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

  121. return 0

  122. fi

  123. # keep booted initramfs

  124. boot_initramfs=

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

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

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

  128. fi

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

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

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

  132. return 0

  133. fi

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

  135. rm -f ${initramfs_bak}

  136. }

  137. # nuke generated copy

  138. remove_initramfs_bak()

  139. {

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

  141. rm -f "${initramfs_bak}"

  142. verbose "Removing ${initramfs_bak}"

  143. }

  144. generate_initramfs()

  145. {

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

  147. OPTS="-o"

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

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

  150. fi

  151. #if分支其实做这两件事

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

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

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

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

  156. set_sha1

  157. else

  158. mkinitramfs_return="$?"

  159. remove_initramfs_bak

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

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

  162. # minversion wasn't met, exit 0

  163. exit 0

  164. fi

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

  166. exit $mkinitramfs_return

  167. fi

  168. }

  169. # lilo call

  170. run_lilo()

  171. {

  172. # show lilo errors on failure

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

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

  175. echo

  176. lilo -t

  177. fi

  178. lilo

  179. }

  180. # Invoke bootloader

  181. run_bootloader()

  182. {

  183. # invoke policy conformant bootloader hooks

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

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

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

  187. return 0

  188. fi

  189. }

  190. compare_sha1()

  191. {

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

  193. return $?

  194. }

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

  196. set_sha1()

  197. {

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

  199. }

  200. delete_sha1()

  201. {

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

  203. }

  204. # ro /boot is not modified

  205. ro_boot_check()

  206. {

  207. # check irrelevant inside of a chroot

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

  209. return 0

  210. fi

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

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

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

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

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

  216. exit 0

  217. fi

  218. }

  219. get_sorted_versions()

  220. {

  221. version_list=""

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

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

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

  225. return 0

  226. fi

  227. worklist=""

  228. for gsv_i in $version_list; do

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

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

  231. gsv_x=""

  232. else

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

  234. fi

  235. done

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

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

  238. fi

  239. version_list="${worklist}"

  240. done

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

  242. }

  243. set_current_version()

  244. {

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

  246. version=`uname -r`

  247. fi

  248. }

  249. set_linked_version()

  250. {

  251. linktarget=

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

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

  254. fi

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

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

  257. fi

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

  259. return

  260. fi

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

  262. }

  263. set_highest_version()

  264. {

  265. get_sorted_versions

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

  267. version=

  268. return

  269. fi

  270. set -- ${version_list}

  271. version=${1}

  272. }

  273. create()

  274. {

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

  276. usage "Create mode requires a version argument"

  277. fi

  278. set_initramfs

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

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

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

  282. fi

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

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

  285. fi

  286. fi

  287. generate_initramfs

  288. }

  289. update()

  290. {

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

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

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

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

  295. exit 0

  296. fi

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

  298. set_highest_version

  299. fi

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

  301. set_linked_version

  302. fi

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

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

  305. set_current_version

  306. fi

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

  308. verbose "Nothing to do, exiting."

  309. exit 0

  310. fi

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

  312. set_initramfs

  313. ro_boot_check

  314. altered_check

  315. backup_initramfs

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

  317. generate_initramfs

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

  319. run_bootloader

  320. backup_booted_initramfs

  321. }

  322. delete()

  323. {

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

  325. usage "Delete mode requires a version argument"

  326. fi

  327. set_initramfs

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

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

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

  331. fi

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

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

  334. fi

  335. fi

  336. altered_check

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

  338. delete_sha1

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

  340. }

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

  342. altered_check()

  343. {

  344. # No check on takeover

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

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

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

  348. fi

  349. if ! compare_sha1; then

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

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

  352. fi

  353. }

  354. # Defaults

  355. verbose=0

  356. yes=0

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

  358. takeover=1

  359. ##

  360. #可选参数-k和-b后面带其他参数

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

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

  363. case "${flag}" in

  364. k)

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

  366. version="${OPTARG}"

  367. ;;

  368. c)

  369. mode="c"

  370. ;;

  371. d)

  372. mode="d"

  373. ;;

  374. u)

  375. mode="u"

  376. ;;

  377. v)

  378. verbose="1"

  379. ;;

  380. y)

  381. yes="1"

  382. ;;

  383. t)

  384. takeover="1"

  385. ;;

  386. b)

  387. BOOTDIR="${OPTARG}"

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

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

  390. exit 1

  391. fi

  392. ;;

  393. h|?)

  394. usage

  395. ;;

  396. esac

  397. done

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

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

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

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

  402. usage

  403. fi

  404. # Validate arguments

  405. #${mode}为空

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

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

  408. fi

  409. #如果输入-k all 或者/etc/initramfs-tools/update-initramfs中的update_initramfs的值为all

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

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

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

  413. get_sorted_versions

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

  415. verbose "Nothing to do, exiting."

  416. exit 0

  417. fi

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

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

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

  421. fi

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

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

  424. fi

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

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

  427. fi

  428. for u_version in ${version_list}; do

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

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

  431. done

  432. exit 0

  433. fi

  434. #只讨论update-initramfs -u的情况

  435. case "${mode}" in

  436. c)

  437. create

  438. ;;

  439. d)

  440. delete

  441. ;;

  442. u)

  443. #-u 则调用update函数

  444. update

  445. ;;

  446. 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. umask 0022

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

  4. # Defaults

  5. keep="n"

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

  7. verbose="n"

  8. #如果/bin/busybox文件夹存在 变量BUSYBOXDIR=/bin

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

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

  11. export BUSYBOXDIR

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

  13. # Check for non-GNU getopt

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

  15. eval set -- "$OPTIONS"

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

  17. #mkinitramfs -o /boot/initrd.img-`uname -r`.new ${version},因此进入-o分支

  18. while true; do

  19. case "$1" in

  20. -c)

  21. compress="$2"

  22. shift 2

  23. ;;

  24. -d)

  25. CONFDIR="$2"

  26. shift 2

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

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

  29. exit 1

  30. fi

  31. ;;

  32. -o)

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

  34. outfile="$2"

  35. shift 2

  36. ;;

  37. -k)

  38. keep="y"

  39. shift

  40. ;;

  41. -r)

  42. ROOT="$2"

  43. shift 2

  44. ;;

  45. -v)

  46. verbose="y"

  47. shift

  48. ;;

  49. --)

  50. shift

  51. break

  52. ;;

  53. *)

  54. echo "Internal error!" >&2

  55. exit 1

  56. ;;

  57. esac

  58. done

  59. # For dependency ordered mkinitramfs hook scripts.

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

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

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

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

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

  65. EXTRA_CONF=''

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

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

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

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

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

  71. done

  72. # FIXME: deprecated those settings on mkinitramfs run

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

  74. for i in ${EXTRA_CONF}; do

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

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

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

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

  79. fi

  80. done

  81. # source package confs

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

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

  84. . "${i}"

  85. fi

  86. done

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

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

  89. umask "${UMASK}"

  90. fi

  91. #outfile为空 也不成立

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

  93. usage

  94. fi

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

  96. touch "$outfile"

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

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

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

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

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

  102. else

  103. version="${1}"

  104. fi

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

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

  107. check_minkver ${version}

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

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

  110. case "${version}" in

  111. #/lib/modules/*/目录下除了/以外的文件,这是指除了该目录下除了子目录以外的所有文件?

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

  113. ;;

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

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

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

  117. ;;

  118. esac

  119. case "${version}" in

  120. */*)

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

  122. exit 1

  123. ;;

  124. esac

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

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

  127. #COMPRESS=gzip gzip压缩

  128. compress=${COMPRESS}

  129. else

  130. COMPRESS=${compress}

  131. fi

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

  133. compress=gzip

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

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

  136. COMPRESS=gzip

  137. fi

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

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

  140. compress=gzip

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

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

  143. fi

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

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

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

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

  148. exit 1

  149. fi

  150. #要编译内核的版本

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

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

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

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

  155. fi

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

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

  158. depmod ${version}

  159. fi

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

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

  162. chmod 755 "${DESTDIR}"

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

  164. NOEXEC=""

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

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

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

  168. NOEXEC=1

  169. fi

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

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

  172. # Export environment for hook scripts.

  173. #

  174. export MODULESDIR

  175. export version

  176. export CONFDIR

  177. export DESTDIR

  178. export DPKG_ARCH

  179. export verbose

  180. export MODULES

  181. export BUSYBOX

  182. export COMPCACHE_SIZE

  183. # Private, used by 'catenate_cpiogz'.

  184. export __TMPCPIOGZ

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

  186. #这是在制作根文件系统

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

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

  189. done

  190. # Copy the modules.order file in

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

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

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

  194. fi

  195. # MODULES=list case.  Always honour.

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

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

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

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

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

  201. add_modules_from_file "${x}"

  202. fi

  203. done

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

  205. # MODULES=most is default

  206. case "${MODULES}" in

  207. dep)

  208. dep_add_modules

  209. ;;

  210. most)

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

  212. auto_add_modules

  213. ;;

  214. netboot)

  215. auto_add_modules base

  216. auto_add_modules net

  217. ;;

  218. list)

  219. # nothing to add

  220. ;;

  221. *)

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

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

  224. auto_add_modules

  225. ;;

  226. esac

  227. # Resolve hidden dependencies

  228. hidden_dep_add_modules

  229. # First file executed by linux-2.6

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

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

  232. # add existant boot scripts

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

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

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

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

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

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

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

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

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

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

  243. done

  244. #对于/etc/initramfs-tools/scripts下的文件使用同样的操作

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

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

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

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

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

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

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

  252. done

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

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

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

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

  257. for i in ${EXTRA_CONF}; do

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

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

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

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

  262. fi

  263. done

  264. # ROOT hardcoding

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

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

  267. fi

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

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

  270. exit 1

  271. fi

  272. #copy_exec定义在hook-functions中

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

  274. # module-init-tools

  275. copy_exec /sbin/modprobe /sbin

  276. copy_exec /sbin/rmmod /sbin

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

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

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

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

  281. # util-linux

  282. copy_exec /sbin/blkid /sbin

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

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

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

  286. fi

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

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

  289. # cache boot run order

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

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

  292. else

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

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

  295. done

  296. fi

  297. # generate module deps

  298. #生成模块依赖文件

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

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

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

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

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

  304. #缓存文件加速链接速度

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

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

  307. #是/usr/zzz/etc/ld.so.conf文件.用此选项,可以大大增加动态链接库管理的灵活性

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

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

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

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

  312. fi

  313. # Apply DSDT to initramfs

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

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

  316. fi

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

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

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

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

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

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

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

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

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

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

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

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

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

  330. fi

  331. fi

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

  333. (

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

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

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

  337. exec 3>&1

  338. eval `

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

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

  341. cd  "${DESTDIR}"

  342. {

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

  344. } | {

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

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

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

  348. `

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

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

  351. exit "$ec1"

  352. fi

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

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

  355. exit "$ec2"

  356. fi

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

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

  359. exit "$ec3"

  360. fi

  361. ) || exit 1

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

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

  364. fi

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

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

  367. else

  368. rm -rf "${DESTDIR}"

  369. rm -rf "${__TMPCPIOGZ}"

  370. fi

  371. 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. src="${1}"

  10. #如果$2(可执行程序所在的目录)为空 则返回$1的值

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

  12. #可执行程序不存在就return,否则往下执行

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

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

  15. # check if already copied

  16. #目录存在并且exe存在则返回

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

  18. else

  19. #目录不存在 则创建目录

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

  21. #FIXME: inst_dir

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

  23. fi

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

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

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

  27. # Copy the dependant libraries

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

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

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

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

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

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

  34. # sse2, vfp or neon.

  35. nonoptlib=$(echo "${x}" | sed -e 's#/lib/tls‖i686‖sse2‖neon‖vfp.*/lib.∗#/lib/\2#')

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

  37. x="${nonoptlib}"

  38. fi

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

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

  41. # FIXME inst_lib

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

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

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

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

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

  47. fi

  48. done

  49. }

阅读全文

版权声明:本文为博主原创文章,未经博主允许不得转载。 http://blog.csdn.net/lixiangminghate/article/details/50044033

转载于:https://blog.51cto.com/woshiyu001/2088322

制作initrd(2):update-initramfs和mkinitramfs脚本分析相关推荐

  1. 安装linux系统initrd,制作initrd(5):解剖Ubuntu安装盘

    ubuntu定期更新他们的iso,iso引导系统后会有Try/Install Ubuntu两个选项.特别是选择了livecd,仅仅一张盘子就能运行一个图形化的linux,总觉得挺神奇的.在好奇心的推动 ...

  2. linux生成initrd,linux的initrd机制和initramfs机制之initrd

    以2.6以后的内核讨论 一.概念 什么是initrd? initrd的解释是initialized RAM disk,就是启动的时候由uboot来初始化内存,当做disk来使用.在uboot启动的时候 ...

  3. 制作initrd.img

    只是缺失libtinfo.so.5.9和libncurses.so.5.9 [root@localhost sandisk]# ldd opt/MegaRAID/MegaCli/MegaCli64li ...

  4. bat自动输入密码登录_如何制作自动设置计算机管理员密码的脚本

    如何制作自动设置计算机管理员密码的脚本 首先新建一个txt文档,输入以下代码 @echo offecho 更改管理员administrator密码net user administrator /act ...

  5. linux程序安装包怎么用,制作Linux下程序安装包——使用脚本打包bin、run等安装包...

    制作简单的安装包的时候可以简单的用cat命令连接两个文件,然后头部是脚本文件,执行的时候把下面的文件分解出来就行了.一般这个后部分的文件是个压缩 包,那样,就能够打包很多文件了,在脚本中解压出来即可. ...

  6. Linux系统脚本分析之rc.sysinit

    Linux系统脚本分析之rc.sysinit #!/bin/bash # # /etc/rc.d/rc.sysinit - run once at boot time #  # # Rerun our ...

  7. STM32跑MicroPython的链接脚本分析

    一.链接脚本的简单常识   有时候我们很多文件需要链接到指定的区域,或者叫做段里面,比如在 Linux 里面初始化函数就会放到 init 段里面.因此我们需要能够自定义一些段,这些段的起始地址我们可以 ...

  8. 【Android 高性能音频】hello-oboe 示例解析 ( Oboe 源代码依赖 | CMakeList.txt 构建脚本分析 | Oboe 源代码构建脚本分析 )

    文章目录 一.Oboe 源码路径 二.阅读 CMakeList.txt 查看依赖 三.hello-oboe 中 NDK 的 CMakeList.txt 构建脚本 四.Oboe 源码 的 CMakeLi ...

  9. build/envsetup.sh脚本分析

    1. Android编译系统分析 编译脚本及系统变量 build/envsetup.sh脚本分析 在编译源代码之前通常需要在android源代码顶层目录执行 . ./build/envsetup.sh ...

最新文章

  1. 国内大数据开发中比较受欢迎的几款工具
  2. 中国钢铁行业产量规模与十四五建设动态分析报告2022-2027年
  3. linux ffmpeg 64下载,linux ffmpeg 怎么编64位
  4. 提高效能 自我关怀的六个习惯
  5. USACO Training Section 1.1 贪婪的送礼者Greedy Gift Givers
  6. 2016 server sql 错误53_MS SQL Server 错误53 错误17是什么?如何解决
  7. linux重启was控制台报错,IHS启动时报错,从was控制台传播插件失败
  8. 集结500+CEO北京共“吹牛”,移动认证又搞什么大事情?
  9. 过滤程序的html代码,值得收藏的html过滤代码
  10. Gartner 2020年十大战略科技发展趋势:边缘赋能、区块链、超自动化、人工智能安全等...
  11. CentOS 6.5忘记root密码,怎么办?
  12. WordPress简单好看的线报主题baolog
  13. 怎么获取echarts需要的geoJson数据去渲染地图:以广州市白云区24镇街为例(内附资源)
  14. 产品经理的自我修养:认知模式
  15. R语言length()和lengths()的区别
  16. c/c++ 头文件(.h)、源文件(.cpp)书写及接口与实现分离实例
  17. 靠这个方法,我终于月入3万!
  18. 项目启动报错 Error running ‘xxxApplication‘;Command line is too long,Shoerten command line for........
  19. 武汉理工大学计算机考研复试资料,武汉理工大学计算机考研复试
  20. CVE-2012-0158漏洞分析

热门文章

  1. linux上安全狗的安装
  2. Spring PropertyPlaceholderConfigurer
  3. SQLite的数据类型总结
  4. 搭建squid代理服务器
  5. WaitHandle.WaitAll 方法在WPF工程中的应用
  6. 关于Heritrix学习的问题记录
  7. 如何修改WINDOWS默认的3389远程端口
  8. 开发板运行linux下虚拟机ubuntu的ping
  9. Python到底有多强大?只需 15 行代码即可进行人脸检测
  10. _linux运维正确安装oracle流程