reboot流程分析

本文基于reboot命令的具体实现,具体的硬件是mips架构的CAVIUM的CN63XX的CPU,内核版本为2.6.32.27 

1,系统下面的命令
     linux下面的一切都是文件,所以我们对应的命令也对应着文件,而命令如何链接到文件,这就是系统的配置问题了,主要是环境变量的PATH的配置,shell解析会自动去PATH环境变量下面的路径去寻找对应的处理。
     如果是单个的命令,可能对应着一个单独的可执行程序,也可能是一个可执行程序对应着一批的命令,例如reboot,poweroff等命令都连接到了busybox文件系统里面,里面对命令再进行解析 
     A ,单个命令对应单个的可执行程序,例如:
-rwxr-xr-x    1 root     root        174391 May 24 12:25 sed
-rwxr-xr-x    1 root     root        312892 Jul 13 11:45 sup  :我们自己开发的命令也可以放在该目录下面 
     B,多个命令对应一个可执行程序,然后该可执行程序再对不同的命令进行解析,例如:
rwxrwxrwx    1 root     root            14 Jul 13 11:46 reboot -> ../bin/busybox 
lrwxrwxrwx    1 root     root            14 Jul 13 11:46 rfkill -> ../bin/busybox
lrwxrwxrwx    1 root     root            14 Jul 13 11:46 rmmod -> ../bin/busybox
lrwxrwxrwx    1 root     root            14 Jul 13 11:46 route -> ../bin/busybox
     BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令。
     busybox的流程分析参见 附六。

reboot是系统调用:

2,系统处理接口的调用入口:
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
        void __user *, arg)
{
         case LINUX_REBOOT_CMD_RESTART:  //0x01234567
             kernel_restart(NULL);
         break;
}
3,具体实现接口流程
kernel_restart(/kernel/sys.c)
{
     kernel_restart_prepare(cmd);
     {
          device_shutdown();
          sysdev_shutdown();
     }
     machine_restart(cmd);
     {
              if (_machine_restart)  //相关的调用流程参照附四说明
             _machine_restart(command); --->octeon_restart(arch/mips/cavium-octeon/setup.c )
                    cvmx_write_csr(CVMX_CIU_SOFT_RST, 1);//主要就是写了一个CPU的重启寄存器
     }
}

4,预重启的准备接口操作
kernel/sys.c文件:
void kernel_restart_prepare(char *cmd)
{
//调用所有的设备的reboot的通知器的接口,一般的设备驱动接口初始化都会赋值有此通知接口,在mtd_info结构体有这个元素。比如附二。
    blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
//这是一个menu,在文件init/main.c里面EXPORT_SYMBOL(system_state);  
//在include/linux/kernel.h中定义 ,如附一
    system_state = SYSTEM_RESTART;

//调用所有的设备驱动的dev->driver->shutdown(dev)接口dev->bus->shutdown(dev); ,device--》device_driver--》shutdown 
//主要用于在内核注册驱动结构的设备 ,  主链表:struct kset *devices_kset;
//从打印来看只有dev->bus->shutdown(dev);有设备,dev下面没有 
  device_shutdown();printk(KERN_EMERG "*** Shutdown device_shutdown .\n");
//关闭一些cpu相关的资源,包括clocksource,timekeeping,cpu 
    sysdev_shutdown();printk(KERN_EMERG "*** Shutdown sysdev_shutdown .\n");
}

5,实际重启的实现:
     主要就是写了一个CPU的reset寄存器操作,CVMX_CIU_SOFT_RST手动写该寄存器也会导致CPU重启
machine_restart(cmd);
     {
              if (_machine_restart)  //相关的调用流程参照附四说明
             _machine_restart(command); --->octeon_restart(arch/mips/cavium-octeon/setup.c )
                    cvmx_write_csr(CVMX_CIU_SOFT_RST, 1);//主要就是写了一个CPU的重启寄存器
     }

附一:
/* Values used for system_state */
extern enum system_states {
    SYSTEM_BOOTING,
    SYSTEM_RUNNING,
    SYSTEM_HALT,
    SYSTEM_POWER_OFF,
    SYSTEM_RESTART,
    SYSTEM_SUSPEND_DISK,
} system_state;

附二:
      文件cfi_cmdset_0001.c中注册一些nor的mtd接口时:   mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
     
附三:
内核device的初始化和注册以及添加的一些接口:
int device_add(struct device *dev)
int device_register(struct device *dev)
void device_initialize(struct device *dev)
void device_del(struct device *dev)

附四:
一些CPU相关的接口的调用流程:
start_kernel(init/main.c)
     ----》setup_arch(arch/mips/kernel/setup.c)
           ---->prom_init(arch/mips/cavium-octeon/setup.c)----
               在这个接口里面初始化了一批的接口: 
 重启  : _machine_restart = octeon_restart;
                                  挂起:  _machine_halt = octeon_halt;


附五:
     命令的调用流程
     大量的系统命令都放置在了/sbin/目录下面,例如:
CPC                depmod             getty              loadfont           ntpd               svlogd
acpid              devmem             halt               loadkmap           oct_linux_csr      swapoff
add-shell          dhcprelay          hdparm             logcheck           pivot_root         swapon
addgroup           dnsd               hotplug-call       logread            popmaildir         switch_root
adduser            dtweak             hotplug2           losetup            poweroff           sysctl
adjtimex           e2fsck             httpd              lpd                powertop           syslogd
appdaemon          ether-wake         hwclock            lsmod              raidautorun        sysupgrade
appmain            fakeidentd         ifconfig           makedevs           rdate              telnetd
arp                fbset              ifdown             mdev               rdev               tftpd
arping             fbsplash           ifenslave          mkdosfs            readprofile        tunctl
bds_main           fdformat           ifplugd            mke2fs              reboot             ubiattach
blkid              fdisk              ifup               mkfs.ext2          remove-shell       ubidetach
blockdev           firstboot          inetd              mkfs.ext3          rfkill             ubimkvol
bootchartd         flash_eraseall     info-collect       mkfs.minix         rmmod              ubirmvol
brctl              flash_lock         init               mkfs.vfat          route              ubirsvol
bup                flash_unlock       insmod             mkswap             rtcwake            ubiupdatevol
chat               flashcp            ip                 modinfo            runlevel           uci
chpasswd           freeramdisk        ipaddr             modprobe           sed                udevtrigger
chroot             fsck               iplink             mount_root         sendmail           udhcpc
cli                fsck.ext2          iproute            mtd                setconsole         udhcpd
config_set         fsck.ext3          iprule             myfsck             setfont            upgrade
core_zip.sh        fsck.minix         iptunnel           nameif             setlogcons         vconfig
crond              fstrim             killall5           nanddump           slattach           watchdog
datasize           fsuptime           klogd              nandwrite          start-stop-daemon  who_am_i
delgroup           ftpd               ldconfig           nbd-client         sulogin            wifi
deluser            getppid            led.sh             net-proxy          sup                zcip
     而且大半部分都是软链接,链接到了文件系统:例如:
lrwxrwxrwx    1 root     root            14 Jul 13 11:46 reboot -> ../bin/busybox 
lrwxrwxrwx    1 root     root            14 Jul 13 11:46 rfkill -> ../bin/busybox
lrwxrwxrwx    1 root     root            14 Jul 13 11:46 rmmod -> ../bin/busybox
lrwxrwxrwx    1 root     root            14 Jul 13 11:46 route -> ../bin/busybox
或者说直接就是单个的运行程序,例如:
-rwxr-xr-x    1 root     root        174391 May 24 12:25 sed
-rwxr-xr-x    1 root     root        312892 Jul 13 11:45 sup  :我们自己开发的命令也可以放在该目录下面 

附六:
     busybox的流程简单分析。基于源码1.22.1
     命令注册接口:
注册命令:include/applets.src.h文件
# define APPLET(name,l,s)                              int name##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
# define APPLET_ODDNAME(name,main,l,s,name2)      int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
# define APPLET_NOEXEC(name,main,l,s,name2)       int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
# define APPLET_NOFORK(name,main,l,s,name2)       int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;

IF_ACPID(APPLET(acpid, BB_DIR_SBIN, BB_SUID_DROP))
IF_ADDGROUP(APPLET(addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_IPROUTE(APPLET(iproute, BB_DIR_SBIN, BB_SUID_DROP))
IF_IPRULE(APPLET(iprule, BB_DIR_SBIN, BB_SUID_DROP))
IF_MOUNT(APPLET(mount, BB_DIR_BIN, IF_DESKTOP(BB_SUID_MAYBE) IF_NOT_DESKTOP(BB_SUID_DROP)))
IF_PKILL(APPLET_ODDNAME(pkill, pgrep, BB_DIR_USR_BIN, BB_SUID_DROP, pkill))
IF_PRINTF(APPLET_NOFORK(printf, printf, BB_DIR_USR_BIN, BB_SUID_DROP, printf))
IF_PWD(APPLET_NOFORK(pwd, pwd, BB_DIR_BIN, BB_SUID_DROP, pwd))

从上述两个宏可知,每个命令都有对应的处理函数,比如acpid_main ,mount_main 等等。
busybox与内核的交互通过init 进程来进行。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值