• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
initramfsについて
 

initramfsについて

on

  • 6,003 views

 

Statistics

Views

Total Views
6,003
Views on SlideShare
5,998
Embed Views
5

Actions

Likes
5
Downloads
27
Comments
0

1 Embed 5

http://wiki.onakasuita.org 5

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    initramfsについて initramfsについて Presentation Transcript

    • initramfs について Kansai Debian Meeting 20101024 西山和広 Good-Day Inc.Powered by Rabbit 0.6.4
    • Who am I? twitter: @znz fingerprint sec 4096R/B4222F7A 2010-06-27 [expires: 2040-08-10] Key fingerprint = B863 D6DC C2B9 57B8 5238 6CE0 262E D8DB B422 2F7A uid Kazuhiro NISHIYAMA <zn@...> uid Kazuhiro NISHIYAMA (ZnZ) <zn@...> uid Kazuhiro NISHIYAMA <nisiyama@...> uid Kazuhiro NISHIYAMA (znz) <kzhr.nsym@...> ssb 4096R/FAFB96B8 2010-06-27 1/52
    • Agenda initrd/initramfs とは? いろいろなところからの Linux の起動 initramfs について initramfs のカスタマイズ ./init の処理内容 2/52
    • initrd/initramfs とは? Linux の起動途中に使われる root ファイル システム この中で本当の root ファイルシステム (real root) をマウント 実体は gzip された cpio アーカイブ 昔は ext2 のディスクイメージファイル gzip の代わりに lzma のこともある (casper/initrd.lz) 3/52
    • Linux の起動いろいろなところからの Linux の起動についてinitramfs が起動中のどの部分になるのかの説明のため 4/52
    • USB/HDD から起動 BIOS (起動順位で USB/HDD が上) MBR (grub などのブートローダー) vmlinuz (カーネル) + initrd (の中の /init) real root (/dev/sda1 とか) の /sbin/init (MD, LVM2, LUKS などでも OK) /etc/inittab の処理とか 5/52
    • 光学ドライブから起動 BIOS (起動順位で光学ドライブが上) El Torito (isolinux などのブートローダー) vmlinuz (カーネル) + initrd (の中の /init) real root (filesystem.squashfs + aufs とか) の /sbin/ init /etc/inittab の処理とか 6/52
    • ネットワークから起動 BIOS (起動順位で NIC が上) PXE boot (pxelinux などのブートローダー) vmlinuz (カーネル) + initrd (の中の /init) real root (NFS とか) の /sbin/init /etc/inittab の処理とか 7/52
    • real root の場所カーネルに root=UUID=xxx などで指定 ローカルディスク (root=/dev/sda1 など) 光学ドライブ (root=/dev/hdc など) NFS (nfsroot=192.168.0.1:/path/to/ nfsroot など)など 8/52
    • /proc/cmdline (1) カーネルのコマンドライン引数 カーネルパラメーター 起動後に /proc/cmdline で見えるもの grub などで vmlinuz の後ろに書いている もの 9/52
    • /proc/cmdline (2) initramfs の処理で使うものが多い カーネル自体が処理するものもある real root で起動するプログラムが参照する 目的で使っても良いが、カーネルや initramfs が使うものと衝突しないように注 意 10/52
    • /proc/cmdline (3)良く使われるものの例quiet 起動中のコンソールへの出力を減らすro / rw initramfs の中で real root を readonly mount する かどうか 11/52
    • /proc/cmdline (4)init=/path/to/real_init /sbin/init の代わりに実行するプログラムを指定acpi=off apm=off など カーネルが処理text /etc/init.d/gdm3 が「grep -wqs text /proc/ cmdline」でチェックしている 12/52
    • /proc/cmdline (5)root=/path/to/blockdevice ルートファイルシステムとしてマウントするデバイスを 指定boot=local / boot=nfs / boot=casper /boot=live real root を mount するのに使うスクリプトを指定 13/52
    • update-initramfs initramfs はパッケージの中身ではない update-initramfs コマンドで生成や更新 (カーネルのパッケージのインストール時などは dpkg-trigger で遅延実 行) /usr/share/initramfs-tools/ や /etc/ initramfs-tools/ を元に生成 「sudo update-initramfs -u -k all」などで 更新 14/52
    • initramfs の調べ方 mkdir -p /tmp/initrd && (cd /tmp/initrd && { zcat /boot/initrd.img-* | cpio -idm; }) # initramfs-tools(8) mkdir tmp/initramfs cd tmp/initramfs gunzip -c /boot/initrd.img-2.6.18-1-686 | cpio -i -d -H newc --no-absolute-filenames # linux-2.6/Documentation/initrd.txt mkdir /tmp/imagefile cd /tmp/imagefile gzip -cd /boot/imagefile.img | cpio -imd --quietなどのように展開(カレントディレクトリにばらまかれるので展開場所には注意) 15/52
    • initramfs の中身 (1)./init カーネルが実行するプログラム ✓ Debian 系の場合は /bin/sh のシェルスクリプト ✓ Redhat 系の場合は以前確認したときは nash だっ た./scripts ./init から読み込まれたり実行されたりするプログラム 16/52
    • initramfs の中身 (2)./bin や ./sbin busybox など./conf や ./etc 設定ファイル./lib や ./usr ライブラリやカーネルモジュールなど 17/52
    • initramfs のカスタマイズ /etc/initramfs-tools/ 以下のファイルを編集 したり、ファイルを追加したり。 Debian Live のようにパッケージなら /usr/ share/initramfs-tools/ 以下にファイルを追 加する。 18/52
    • /etc/initramfs-tools (1)initramfs.confupdate-initramfs.conf update-initramfs や mkinitramfs の設定ファイルmodules initramfs の中でロードするモジュール(後でロードす ればいいものは /etc/modules を使う) 19/52
    • /etc/initramfs-tools (2)conf.d/ initramfs の conf/conf.d/ に入る。hooks/ /usr/share/initramfs-tools/hooks/ と同様に initramfs 作成時に実行される。 20/52
    • /etc/initramfs-tools (3)scripts/ /usr/share/initramfs-tools/scripts/ と一緒に initramfs の scripts/ に入る。(リカバリディスクを作成するときに scripts/local-premount/recovery を作った。) 21/52
    • hooks/ /usr/share/initramfs-tools/hook- functions の関数で initramfs の中身を生成 copy_exec で追加しておきたいバイナリをコピー (ldd でわかる範囲内で使っているライブラリを含 めてコピーされる) manual_add_modules でモジュールをコピー その他のファイルを追加や削除など 22/52
    • scripts/ カスタマイズする処理本体 live 関係なら以下のようなものが入る。 (BOOT=live のときに使われる) live live-bottom/ live-functions live-helpers live-premount/ 23/52
    • ./init の処理内容 (1)ソースは initramfs-tools 0.98.4 から。(initramfs-tools 由来のコードのライセンスは GPL2 or later です) #!/bin/sh echo "Loading, please wait..."このメッセージが出たところからが initramfsの中の処理 24/52
    • ./init の処理 (2) dirinitramfs 内の ディレクトリの準備 [ -d /dev ] || mkdir -m 0755 /dev [ -d /root ] || mkdir -m 0700 /root [ -d /sys ] || mkdir /sys [ -d /proc ] || mkdir /proc [ -d /tmp ] || mkdir /tmp mkdir -p /var/lock mount -t sysfs -o nodev,noexec,nosuid none /sys mount -t proc -o nodev,noexec,nosuid none /proc 25/52
    • ./init の処理 (3) devinitramfs 内の /dev や udev の準備 # Note that this only becomes /dev on the real filesystem if udevs scripts # are used; which they will be, but its worth pointing out tmpfs_size="10M" if [ -e /etc/udev/udev.conf ]; then . /etc/udev/udev.conf fi if ! mount -t devtmpfs -o mode=0755 none /dev; then echo "W: devtmpfs not available, falling back to tmpfs for /dev" mount -t tmpfs -o size=$tmpfs_size,mode=0755 udev /dev [ -e /dev/console ] || mknod -m 0600 /dev/console c 5 1 [ -e /dev/null ] || mknod /dev/null c 1 3 fi mkdir /dev/pts mount -t devpts -o noexec,nosuid,gid=5,mode=0620 none /dev/pts || true > /dev/.initramfs-tools mkdir /dev/.initramfs 26/52
    • ./init (4) export後で起動するシェルスクリプトなどのために、いくつかのシェル変数は環境変数に後半はスペースの都合で同じ行に詰めています # Export the dpkg architecture export DPKG_ARCH= . /conf/arch.conf # Set modprobe env export MODPROBE_OPTIONS="-qb" # Export relevant variables export ROOT=; export ROOTDELAY=; export ROOTFLAGS=; export ROOTFSTYPE= export IP=; export BOOT=; export BOOTIF=; export UBIMTD=; export break= export init=/sbin/init; export quiet=n; export readonly=y export rootmnt=/root; export debug=; export panic=; export blacklist= export resume=; export resume_offset= 27/52
    • ./init (5) confconf ファイルの読み込み # Bring in the main config . /conf/initramfs.conf for conf in conf/conf.d/*; do [ -f ${conf} ] && . ${conf} done . /scripts/functions 28/52
    • ./conf/initramfs.conf./conf/initramfs.conf の中身の例(real root を探す処理が BOOT で決まる) % egrep ^[^#] conf/initramfs.conf MODULES=most BUSYBOX=y KEYMAP=n COMPRESS=gzip BOOT=local DEVICE= NFSROOT=auto 29/52
    • ./conf/conf.d の中身の例 % ls conf/conf.d resume % cat conf/conf.d/resume RESUME=UUID=ae891314-2104-480c-bdd8-6de40e6edb72 30/52
    • ./init (6) cmdlineカーネルのコマンドライン引数 (/proc/cmdline) の解析 # Parse command line options for x in $(cat /proc/cmdline); do case $x in init=*) init=${x#init=} ;; root=*) ROOT=${x#root=} case $ROOT in LABEL=*) ROOT="${ROOT#LABEL=}" (省略) 31/52
    • ./init (7) noresume if [ -n "${noresume}" ]; then export noresume unset resume else resume=${RESUME:-} fi # cmdline 処理の一部: resume=*) RESUME="${x#resume=}" ;; resume_offset=*) resume_offset="${x#resume_offset=}" ;; noresume) noresume=y ;; 32/52
    • ./init (8) netconsole [ -n "${netconsole}" ] && modprobe netconsole netconsole="${netconsole}" # cmdline 処理の一部: netconsole=*) netconsole=${x#netconsole=} ;;スペースの都合で改行を入れています 33/52
    • ./init (9) maybe_breakmaybe_break は処理の途中でシェルを起動できる場所 maybe_break top # cmdline 処理の一部: break=*) break=${x#break=} ;; break) break=premount ;; 34/52
    • scripts/functions:maybe_break (1) # scripts/functions の一部: maybe_break() { if [ "${break:-}" = "$1" ]; then panic "Spawning shell within the initramfs" fi } 35/52
    • scripts/functions:maybe_break (2)ubuntu (lucid) の initramfs-tools0.92bubuntu78(以降 ubuntu 版の話がある場合はこのバージョン)の場合、Debian と違って複数指定可能 # scripts/functions の一部: maybe_break() { if echo "${break}" | egrep -q "(,|^)$1(,|$)"; then panic "Spawning shell within the initramfs" fi } 36/52
    • functions: panic (1)起動時に root ファイルシステムが見つからなくて「(initramfs)」で止まることがあるのはこれ。 # scripts/functions の一部: panic() { if [ -x /sbin/usplash_write ]; then /sbin/usplash_write "QUIT" fi if command -v chvt >/dev/null 2>&1; then chvt 1 fi # Disallow console access if [ -n "${panic}" ]; then sleep ${panic} reboot fi modprobe i8042 modprobe atkbd echo "$@" REASON="$@" PS1=(initramfs) /bin/sh -i </dev/console >/dev/console 2>&1 } 37/52
    • functions: panic (2)数字か「.」以外の文字があると無視するようになっている。 # cmdline 処理の一部: panic=*) panic="${x#panic=}" case ${panic} in *[![:digit:].]*) panic= ;; esac ;; 38/52
    • functions: panic (3)ubuntu 版だと run_scripts がある。 # scripts/functions の一部: panic() { if [ -x /sbin/usplash_write ]; then /sbin/usplash_write "QUIT" fi chvt 1 # Disallow console access if [ -n "${panic}" ]; then sleep ${panic} reboot fi modprobe i8042 modprobe atkbd run_scripts /scripts/panic echo $@ PS1=(initramfs) /bin/sh -i </dev/console >/dev/console 2>&1 } 39/52
    • run_scripts (1) 指定されたディレクトリの中の実行可能ファ イルを実行 prereqs で依存関係を指定できる ORDER に tsort (トポロジカルソート) 結果 をキャッシュしている 40/52
    • run_scripts (2) # scripts/functions の一部: run_scripts() { initdir=${1} [ ! -d ${initdir} ] && return if [ -f ${initdir}/ORDER ]; then . ${initdir}/ORDER elif command -v tsort >/dev/null 2>&1; then runlist=$(get_prereq_pairs | tsort) call_scripts ${2:-} else get_prereqs reduce_prereqs call_scripts fi } 41/52
    • prereqs引数が prereqs の時に依存するものを echo する。(複数ある場合はスペース区切りで列挙) PREREQ="" prereqs() { echo "$PREREQ" } case $1 in # get pre-requisites prereqs) prereqs exit 0 ;; esac 42/52
    • ./init (10) init-topフックを実行 # Dont do log messages here to avoid confusing usplash run_scripts /scripts/init-top 43/52
    • init (11) load_modules./conf/modules に書いてあるモジュールをロード(/etc/initramfs-tools/modules で設定) maybe_break modules [ "$quiet" != "y" ] && log_begin_msg "Loading essential drivers" load_modules [ "$quiet" != "y" ] && log_end_msg自動認識できないモジュールやはやめにロードしないといけないモジュールに使う。 44/52
    • ./init (12) mountmountroot は「. /scripts/${BOOT}」で定義される。(parse_numeric は ROOT=major:minor のような指定を処理している) maybe_break premount [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-premount" run_scripts /scripts/init-premount [ "$quiet" != "y" ] && log_end_msg maybe_break mount log_begin_msg "Mounting root file system" . /scripts/${BOOT} parse_numeric ${ROOT} maybe_break mountroot mountroot log_end_msg 45/52
    • ./script/local run_scripts /scripts/local-topのようなフックを実行したり"${ROOT}" で指定されているデバイスをマウントしたりマウントできなかったときに panic "ALERT! ${ROOT} does not exist. Dropping to a shell!"で「(initramfs) 」のシェルに落ちたりする。 46/52
    • ./init (13) bottom最初の方でマウントした sysfs と proc を本当の root ファイルシステム (real root) に移動する。 maybe_break bottom [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-bottom" run_scripts /scripts/init-bottom [ "$quiet" != "y" ] && log_end_msg # Move virtual filesystems over to the real filesystem mount -n -o move /sys ${rootmnt}/sys mount -n -o move /proc ${rootmnt}/proc 47/52
    • ./init (14) check init validate_init() { checktarget="${1}" # Work around absolute symlinks if [ -d "${rootmnt}" ] && [ -h "${rootmnt}${checktarget}" ]; then case $(readlink "${rootmnt}${checktarget}") in /*) checktarget="$(chroot ${rootmnt} readlink ${checktarget} )" ;; esac fi # Make sure the specified init can be executed if [ ! -x "${rootmnt}${checktarget}" ]; then return 1 fi # Upstart uses /etc/init as configuration directory :-/ if [ -d "${rootmnt}${checktarget}" ]; then return 1 fi } 48/52
    • ./init (15) check init # Check init bootarg if [ -n "${init}" ]; then if ! validate_init "$init"; then echo "Target filesystem doesnt have requested ${init}." init= fi fi # Common case: /sbin/init is present if [ ! -x "${rootmnt}/sbin/init" ]; then # ... if its not available search for valid init if [ -z "${init}" ] ; then for inittest in /sbin/init /etc/init /bin/init /bin/sh; do if validate_init "${inittest}"; then init="$inittest" break fi done fi # No init on rootmount if ! validate_init "${init}" ; then panic "No init found. Try passing init= bootarg." fi fi 49/52
    • ./init (16) unsetenv # dont leak too much of env - some init(8) dont clear it # (keep init, rootmnt) unset debug unset MODPROBE_OPTIONS unset DPKG_ARCH unset ROOTFLAGS unset ROOTFSTYPE unset ROOTDELAY unset ROOT unset IP unset BOOT unset BOOTIF unset UBIMTD unset blacklist unset break unset noresume unset panic unset quiet unset readonly unset resume unset resume_offset 50/52
    • ./init (17) exec initklibc-utils パッケージ由来の run-init で realroot の /sbin/init などを実行 # Chain to real filesystem exec run-init ${rootmnt} ${init} "$@" <${rootmnt}/dev/console >${rootmnt}/dev/console panic "Could not execute run-init." 51/52
    • real root での処理 sysvinit /etc/inittab に従って処理 upstart /etc/init/*.conf に従って処理 などPowered by Rabbit 0.6.4 52/52