热度 7 |
在上一篇方案中,讲解了如何查看initrd中的文件。其中init这个文件就是加载initrd时执行的脚本,这里记录了加载时的顺序。最近在看这个,所以分享给大家。如果有介绍得不对的地方,还请大家指点。
我用的是ubuntu10.04.下面就是init这个文件的内容。
#!/bin/sh
[ -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
grep -q '\<quiet\>' /proc/cmdline || echo "Loading, please wait..."
# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
if ! mount -t devtmpfs -o mode=0755 none /dev; then
mount -t tmpfs -o mode=0755 none /dev
mknod -m 0600 /dev/console c 5 1
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
# 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 IPOPTS=
export HWADDR=
export break=
export init=/sbin/init
export quiet=n
export readonly=y
export rootmnt=/root
export debug=
export panic=
export blacklist=
export resume_offset=
# Bring in the main config
. /conf/initramfs.conf
for conf in conf/conf.d/*; do
[ -f ${conf} ] && . ${conf}
done
. /scripts/functions
# 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=}"
# support / in LABEL= paths (escape to \x2f)
case "${ROOT}" in
*[/]*)
if [ -x "$(command -v sed)" ]; then
ROOT="$(echo ${ROOT} | sed 's,/,\\x2f,g')"
else
if [ "${ROOT}" != "${ROOT#/}" ]; then
ROOT="\x2f${ROOT#/}"
fi
if [ "${ROOT}" != "${ROOT%/}" ]; then
ROOT="${ROOT%/}\x2f"
fi
IFS='/'
newroot=
for s in $ROOT; do
if [ -z "${newroot}" ]; then
newroot="${s}"
else
newroot="${newroot}\\x2f${s}"
fi
done
unset IFS
ROOT="${newroot}"
fi
esac
ROOT="/dev/disk/by-label/${ROOT}"
;;
UUID=*)
ROOT="/dev/disk/by-uuid/${ROOT#UUID=}"
;;
/dev/nfs)
[ -z "${BOOT}" ] && BOOT=nfs
;;
esac
;;
rootflags=*)
ROOTFLAGS="-o ${x#rootflags=}"
;;
rootfstype=*)
ROOTFSTYPE="${x#rootfstype=}"
;;
rootdelay=*)
ROOTDELAY="${x#rootdelay=}"
case ${ROOTDELAY} in
*[![:digit:].]*)
ROOTDELAY=
;;
esac
;;
resumedelay=*)
RESUMEDELAY="${x#resumedelay=}"
;;
loop=*)
LOOP="${x#loop=}"
;;
loopflags=*)
LOOPFLAGS="-o ${x#loopflags=}"
;;
loopfstype=*)
LOOPFSTYPE="${x#loopfstype=}"
;;
cryptopts=*)
cryptopts="${x#cryptopts=}"
;;
nfsroot=*)
NFSROOT="${x#nfsroot=}"
;;
netboot=*)
NETBOOT="${x#netboot=}"
;;
ip=*)
IPOPTS="${x#ip=}"
;;
hwaddr=*)
HWADDR="${x#hwaddr=}"
;;
boot=*)
BOOT=${x#boot=}
;;
resume=*)
RESUME="${x#resume=}"
;;
resume_offset=*)
resume_offset="${x#resume_offset=}"
;;
noresume)
noresume=y
;;
panic=*)
panic="${x#panic=}"
case ${panic} in
*[![:digit:].]*)
panic=
;;
esac
;;
quiet)
quiet=y
;;
ro)
readonly=y
;;
rw)
readonly=n
;;
debug)
debug=y
quiet=n
exec >/dev/.initramfs/initramfs.debug 2>&1
set -x
;;
debug=*)
debug=y
quiet=n
set -x
;;
break=*)
break=${x#break=}
;;
break)
break=premount
;;
blacklist=*)
blacklist=${x#blacklist=}
;;
netconsole=*)
netconsole=${x#netconsole=}
;;
esac
done
if [ -z "${noresume}" ]; then
export resume=${RESUME}
else
export noresume
fi
[ -n "${netconsole}" ] && modprobe netconsole netconsole=${netconsole}
maybe_break top
# export BOOT variable value for compcache,
# so we know if we run from casper
export BOOT
# Don't do log messages here to avoid confusing usplash
run_scripts /scripts/init-top
maybe_break modules
log_begin_msg "Loading essential drivers..."
load_modules
log_end_msg
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}
mountroot
log_end_msg
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
# Check init bootarg
if [ -n "${init}" ] && [ ! -x "${rootmnt}${init}" ]; then
echo "Target filesystem doesn't have ${init}."
init=
fi
# Search for valid init
if [ -z "${init}" ] ; then
for init in /sbin/init /etc/init /bin/init /bin/sh; do
if [ ! -x "${rootmnt}${init}" ]; then
continue
fi
break
done
fi
# No init on rootmount
if [ ! -x "${rootmnt}${init}" ]; then
panic "No init found. Try passing init= bootarg."
fi
# Confuses /etc/init.d/rc
if [ -n ${debug} ]; then
unset debug
fi
# Chain to real filesystem
maybe_break init
exec run-init ${rootmnt} ${init} "$@" <${rootmnt}/dev/console >${rootmnt}/dev/console 2>&1
panic "Could not execute run-init."
这章主要是介绍前面几行内容:
#!/bin/sh [ -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
第一行是介绍说用bash执行这个脚本,在fedora中这行是#!/bin/nash.nash是linux内核引导initrd中常用的一个简单的类似shell的工具,它只能执行一些内嵌的命令,如mount,mkdir等。之所以fedora使用nash,是不想initrd太大了。
下面的代码就是要建立目录,其中/proc和/sys是kernel必需的。所以下面的内容主要就是讲解这个两个目录。
1. /proc
这个目录主要是用来挂载系统文件中的proc的。proc主要用来存储所有开机后硬件,process相关信息的,全名为process file system.
我们可以查看一下/proc下的文件有哪些
root@alice-desktop:/tmp/initrd/etc# ls /proc 1 1334 1550 1617 1661 1710 18 233 316 38 535 788 928 driver kmsg mtrr sys zoneinfo 10 1362 1581 1618 1667 1711 1801 234 32 3859 6 8 acpi execdomains kpagecount net sysrq-trigger 1084 1365 1585 1619 1669 1721 1829 24 3345 4 638 834 asound fb kpageflags pagetypeinfo sysvipc 11 14 1588 1620 1671 1723 19 251 3413 41 666 839 buddyinfo filesystems latency_stats partitions timer_list 1102 1469 1589 1622 1673 1725 1989 252 3418 42 672 844 bus fs loadavg sched_debug timer_stats 12 1487 1592 1623 1675 1728 1990 27 3422 43 684 845 cgroups interrupts locks schedstat tty 1276 1490 1593 1626 1686 1730 2 28 35 432 7 848 cmdline iomem mdstat scsi uptime 13 1492 16 1643 1689 1732 20 29 37 433 707 849 cpuinfo ioports meminfo self version 1312 1493 1600 1647 1697 1736 21 3 3752 44 711 854 crypto irq misc slabinfo version_signature 1323 15 1602 1653 17 1737 22 30 3753 45 715 855 devices kallsyms modules softirqs vmallocinfo 1328 1524 1607 1655 1708 1782 23 31 3754 46 719 9 diskstats kcore mounts stat vmmemctl 1330 1532 1616 1658 1709 1787 232 311 3770 5 728 925 dma key-users mpt swaps vmstat
目录下的一些数字就是系统在运行时中内存的process ID, 我们可以有ps来查看一下这里面的内容:
root@alice-desktop:/tmp/initrd/etc# ps ax|grep 1532 1532 ? Sl 0:00 /usr/bin/gnome-keyring-daemon --daemonize --login 3877 pts/0 S+ 0:00 grep --color=auto 1532 root@alice-desktop:/tmp/initrd/etc# ps ax|grep 1608 3879 pts/0 S+ 0:00 grep --color=auto 1608
当系统运行时,不论有多少process,都会在/proc下建立相应的目录。
/proc/partitions是用来记录硬盘分区的
root@alice-desktop:/tmp/initrd/etc# cat /proc/partitions major minor #blocks name 8 0 20971520 sda 8 1 20237312 sda1 8 2 1 sda2 8 5 731136 sda5
每一项有两个名称,一个是major,一个是minor.major是从广义上来分的,因为同一个硬盘上的所有分区都是由主板上的SCSI controller管理的,所以所有分区的major都是8.
2. /sys
ls /sys/ block bus class dev devices firmware fs kernel module power
/sys/block是以块设备分类,比如常使用的硬盘,内存和磁盘驱动器
root@alice-desktop:/tmp/initrd/etc# ls /sys/block fd0 loop1 loop3 loop5 loop7 ram1 ram11 ram13 ram15 ram3 ram5 ram7 ram9 sr0 loop0 loop2 loop4 loop6 ram0 ram10 ram12 ram14 ram2 ram4 ram6 ram8 sda sr1这里讲解一下loop这个设备。这个设备是用来挂载文件,把文件当成是块设备来用的。比如你可将一个img文件挂载到/mnt.然后你就可以img操作了。
在fedora中,initrd在自己的目录下创建空的/proc和/sys,当kernel加载完成后,会在里面创建相应的文件。这个与ubuntu不同。
mount -t sysfs -o nodev,noexec,nosuid none /sys mount -t proc -o nodev,noexec,nosuid none /proc上面这段代码就是将相应的系统文件挂载到已经创建好的目录当中。