主页 > imtoken创建多个钱包 > [Linux系统] Linux启动过程

[Linux系统] Linux启动过程

imtoken创建多个钱包 2023-02-11 07:36:05

码农

今天,我们就一起来探讨一下操作系统的启动过程。

银行办理etc流程_etc系统的工作流程_建行etc注销流程

这部分比较有趣。 因为在BIOS阶段,计算机的行为基本上是硬编码的,程序员能做的事情不多; 然而,一旦进入操作系统,程序员几乎可以自定义所有方面。 因此,这部分与程序员的关系更为密切。

我主要关注的是Linux操作系统,它是目前服务器端的主流操作系统。 以下是针对 Debian 发行版的,因为我对其他发行版还不够熟悉。

加载内核

操作系统接管硬件后,首先读取/boot目录下的内核文件。

etc系统的工作流程_建行etc注销流程_银行办理etc流程

以我的电脑为例,/boot目录下大概有一些文件:

  $ ls /boot
  
  config-3.2.0-3-amd64
  config-3.2.0-4-amd64
  grub
  initrd.img-3.2.0-3-amd64
  initrd.img-3.2.0-4-amd64
  System.map-3.2.0-3-amd64
  System.map-3.2.0-4-amd64
  vmlinuz-3.2.0-3-amd64
  vmlinuz-3.2.0-4-amd64  

开始初始化过程

内核文件加载后,第一个程序/sbin/init开始运行,其作用是初始化系统环境。

etc系统的工作流程_银行办理etc流程_建行etc注销流程

由于 init 是第一个运行的程序,因此它的进程号 (pid) 为 1。所有其他进程都派生自它并且是它的子进程。

确定运行级别

许多程序需要引导才能启动。 它们在 Windows 中称为“服务”,在 Linux 中称为“守护进程”。

init进程的一个主要任务就是运行这些启动程序。 但是,在不同的场合需要启动不同的程序。 例如,Apache作为服务器需要启动,作为桌面则不需要。 Linux允许为不同的场合分配不同的引导程序,这称为“运行级别”。 也就是说,根据启动时的“运行级别”,决定运行哪些程序。

etc系统的工作流程_银行办理etc流程_建行etc注销流程

Linux 预设了七个操作级别(0-6)。 一般来说,0为关机etc系统的工作流程,1为单用户模式(即维护模式),6为重启。 每个发行版的运行级别 2-5 都不同。 对于Debian来说,都是一样的多用户模式(也就是普通模式)。

init进程首先读取文件/etc/inittab,这是运行级别的设置文件。 如果你打开它,你可以看到第一行是这样的:

  id:2:initdefault:  

initdefault的值为2,表示系统启动时运行级别为2。 如果需要指定其他级别,可以手动修改该值。

那么,runlevel 2 中有哪些程序,系统如何知道每个级别应该加载哪些程序呢? ......答案是每个运行级别在/etc目录下都有对应的子目录,指定要加载的程序。

  /etc/rc0.d
  /etc/rc1.d
  /etc/rc2.d
  /etc/rc3.d
  /etc/rc4.d
  /etc/rc5.d
  /etc/rc6.d  

上面目录名中的“rc”表示run command(运行程序),最后一个d表示directory(目录)。 让我们看看/etc/rc2.d 目录中指定了哪些程序。

  $ ls  /etc/rc2.d
  
  README
  S01motd
  S13rpcbind
  S14nfs-common
  S16binfmt-support
  S16rsyslog
  S16sudo
  S17apache2
  S18acpid
  ...  

可以看出,除了第一个文件README外,其他文件名都是“字母S+两位数字+程序名”的形式。 字母S表示Start,表示start(启动脚本的运行参数为start),如果这个位置是字母K,则表示Kill(关闭),即切换过来需要关闭的程序其他运行级别(启动脚本运行参数为stop)。

后面两位数字表示处理顺序,数字越小越早处理,所以最先启动的程序是motd,然后是rpcbing,nfs……当数字相同时,按照程序的字母顺序启动程序名称,所以 rsyslog 将在 sudo 之前启动。

该目录下的所有文件(README除外)都是启动时加载的程序。 如果要增加或删除一些程序,不建议手动修改/etc/rcN.d目录,最好使用一些特殊的命令来管理(参考这里和这里)。

加载引导程序

前面说过,预设的7个“运行级别”,每一个都有一个目录,里面存放着开机需要启动的程序。 不难想象,如果多个“运行级别”需要启动同一个程序,那么这个程序的启动脚本在每个目录下都会有一份。 这样会造成管理上的麻烦:如果要修改启动脚本,不是每个目录都要改吗?

Linux的解决办法是将/etc/rcN.d这7个目录下列出的程序都设置为链接文件,指向另一个目录/etc/init.d,真正的启动脚本都放在这个目录下。 init进程一个一个加载启动程序,其实就是运行这个目录下的启动脚本。

etc系统的工作流程_银行办理etc流程_建行etc注销流程

这是链接文件实际指向的位置。

  $ ls -l /etc/rc2.d
  
  README
  S01motd -> ../init.d/motd
  S13rpcbind -> ../init.d/rpcbind
  S14nfs-common -> ../init.d/nfs-common
  S16binfmt-support -> ../init.d/binfmt-support
  S16rsyslog -> ../init.d/rsyslog
  S16sudo -> ../init.d/sudo
  S17apache2 -> ../init.d/apache2
  S18acpid -> ../init.d/acpid
  ...  

这样做的另一个好处是,如果你想手动关闭或重启一个进程,只需要到目录/etc/init.d中找到启动脚本即可。 例如,如果我想重启 Apache 服务器,我运行以下命令:

  $ sudo /etc/init.d/apache2 restart  

/etc/init.d 这个目录名的最后一个字母d是directory的意思,表示这是一个目录,用来区别于/etc/init.d这个程序。

用户登录

加载启动程序后,用户必须登录。

建行etc注销流程_银行办理etc流程_etc系统的工作流程

一般来说,用户登录有以下三种方式:

(1)命令行登录

(2)ssh登录

(3) 界面登录

在这三种情况下,每种情况都有自己的方式来验证用户。

(1)命令行登录:init进程调用getty程序(意思是get teletype),让用户输入用户名和密码。 输入完成后,调用登录程序检查密码(Debian会运行另一个身份检查程序/etc/pam.d/login)。 如果密码正确,则从文件/etc/passwd 中读取用户指定的shell,并启动shell。

(2)ssh登录:此时系统调用sshd程序(Debian会再次运行/etc/pam.d/ssh),替换getty和login,然后启动shell。

(3)图形界面登录:init进程调用显示管理器,Gnome图形界面对应的显示管理器为gdm(GNOME Display Manager),然后用户输入用户名和密码。 如果密码正确,读取 /etc/gdm3/Xsession 并启动用户会话。

进入登录shell

所谓shell,简单来说就是一个命令行界面,可以让用户直接与操作系统对话。 用户登录时打开的shell称为登录shell。

银行办理etc流程_etc系统的工作流程_建行etc注销流程

Debian 的默认 shell 是 Bash,它读取一系列配置文件。 本步骤中对上一步中的三种情况的处理也有所不同。

(1)命令行登录:首先读取/etc/profile,这是对所有用户有效的配置; 然后依次查找以下三个文件,这是当前用户的配置。

  ~/.bash_profile
  ~/.bash_login
  ~/.profile  

需要注意的是,只要这三个文件有一个存在,后面的文件就不会被读入。比如~/.bash_profile存在,后面两个文件就不会被读入。

(2)ssh登录:与第一种情况完全一样。

(3)图形界面登录:只加载/etc/profile和~/.profile。 也就是说,无论 ~/.bash_profile 是否存在,它都不会运行。

打开非登录shell

老实说,上一步完成后etc系统的工作流程,Linux的启动过程就结束了,用户已经可以看到命令行提示符或者图形界面了。 但是,为了完整起见,这一步必须再次介绍。

用户进入操作系统后,往往会手动启动一个shell。 这种shell称为非登录shell,意思是它不同于登录时出现的shell,不读取/etc/profile和.profile等配置文件。

银行办理etc流程_建行etc注销流程_etc系统的工作流程

非登录shell的重要性不仅在于它是用户最常接触到的shell,还在于它会读取用户自己的bash配置文件~/.bashrc。 大多数时候,我们对bash的定制都是写在这个文件中的。

你可能会问,如果不进入非登录shell,.bashrc 不运行,bash 就不能完成定制了吗? 其实Debian已经考虑到了这个问题,请打开文件~/.profile,可以看到如下代码:

  if [ -n "$BASH_VERSION" ]; then    
      if [ -f "$HOME/.bashrc" ]; then      
          . "$HOME/.bashrc"    
      fi  
  fi  

上面的代码首先判断变量$BASH_VERSION是否有值,然后判断主目录下是否有.bashrc文件,如果存在则运行该文件。 第三行开头的点是source命令的缩写形式,意思是运行某个文件,也可以写成“source ~/.bashrc”。

因此,只要运行~/.profile文件,~/.bashrc文件就会一起运行。 但是在上一节第一种情况中提到,如果有~/.bash_profile文件,那么~/.profile文件可能运行不了。 解决这个问题很简单,只需将下面的代码写入.bash_profile 即可。

  if [ -f ~/.profile ]; then    
      . ~/.profile   fi  

这样无论在什么情况下,.bashrc都会被执行,用户的设置就可以安全的写入这个文件中了。

Bash的设置之所以如此繁琐,是有历史原因的。 早期电脑运行很慢,加载配置文件需要很长时间。 Bash 的作者不得不将配置文件分成几个部分,分阶段加载。 系统的通用设置放在/etc/profile中,需要被所有子进程继承的用户个人设置放在.profile中,不需要继承的设置放在.bashrc中。

顺便说一句,除了Linux,Mac OS X使用的shell也是Bash。 但是,它只加载 .bash_profile,然后在 .bash_profile 中调用 .bashrc。 而且,无论是ssh登录还是图形界面启动shell窗口都是如此。