嵌入式:Linux系统应用程序(APP)启动流程概述
Linux加载应用程序,有SysVinit和Systemd两个初始化系统。
一. 传统 SysVinit 系统启动脚本
SysVinit 是早期 Linux 系统广泛使用的初始化系统,其启动过程基于运行级别,每个运行级别对应不同的系统状态。
1. /etc/rc.sysinit
- 作用:这是系统启动时最早执行的脚本之一,负责进行系统的基本初始化工作,如设置系统时钟、挂载根文件系统、激活交换分区、加载内核模块等。
- 查看 app 启动流程相关:如果应用程序依赖某些内核模块,可能会在这个脚本中看到模块加载的信息。例如,若应用需要特定的网络驱动模块,可能会有类似 modprobe <module_name>的命令。
2. /etc/init.d/ 目录
- 作用:该目录下存放着大量的服务启动脚本,每个脚本对应一个系统服务,如 httpd(Apache HTTP 服务器)、sshd(SSH 服务)等。这些脚本遵循特定的格式,包含 start、stop、restart等操作。
- 查看 app 启动流程相关:如果你的应用程序是以服务的形式存在,那么可以查看该目录下对应的脚本。例如,若应用名为 myapp,则可能有 /etc/init.d/myapp脚本。打开该脚本,你可以看到启动应用的具体命令,通常在 `start` 部分,可能类似于:
start() {
echo -n "Starting myapp: "
/usr/bin/myapp &
echo "OK"
}
3. /etc/rc.d/rcN.d/目录(N 代表运行级别,0 - 6)
- 作用:系统启动时,会根据当前的运行级别进入对应的 rcN.d目录执行脚本。以 `S` 开头的脚本会在系统启动时按顺序执行,用于启动服务;以 `K` 开头的脚本会在系统关闭或切换运行级别时执行,用于停止服务。
- 查看 app 启动流程相关:例如,在运行级别 3(多用户文本模式)下,系统会进 /etc/rc.d/rc3.d/ 目录。如果应用程序需要在该运行级别启动,可能会有一个以 `S` 开头的软链接指向 /etc/init.d/ 目录下的对应脚本,这意味着系统会在启动时执行该脚本的 start操作。
二. 现代 Systemd 系统启动脚本
Systemd 是现代大多数 Linux 发行版采用的初始化系统,它使用单元(Unit)来管理系统资源,包括服务、挂载点、套接字等。
1. /usr/lib/systemd/system/ 目录
- 作用:该目录存放着系统自带的服务单元文件,是系统预定义的服务配置。当安装新软件包时,如果软件提供了 systemd 服务,其配置文件也可能被安装到该目录。
- 查看 app 启动流程相关:假设应用程序名为 myapp,可能会有/usr/lib/systemd/system/myapp.service 文件。
打开该文件,你可以看到服务的详细配置,例如:
[Unit]
Description=My Application
After=network.target
[Service]
ExecStart=/usr/bin/myapp
Restart=always
[Install]
WantedBy=multi-user.target
```
[Unit]部分:描述服务的基本信息和依赖关系,`After=network.target` 表示该服务在网络服务启动后再启动。
[Service]部分:`ExecStart` 指定启动应用的命令,`Restart=always` 表示服务意外停止时会自动重启。
[Install]部分:`WantedBy=multi-user.target` 表示该服务在多用户模式下启动。
2. /etc/systemd/system/ 目录
- 作用:该目录用于存放用户自定义的服务单元文件,或者对系统默认服务的覆盖配置。如果需要修改某个服务的配置,可以在该目录下创建同名的服务单元文件,并进行相应修改。
- 查看 app 启动流程相关:如果你对 `myapp` 的启动配置进行了自定义修改,可能会在 `/etc/systemd/system/myapp.service` 中看到修改后的内容。
3. `/etc/systemd/system/multi-user.target.wants/` 目录
作用:“multi-user.target” 是系统进入多用户模式时的目标。该目录下存放的软链接指向 /etc/systemd/system/或 /usr/lib/systemd/system/目录下的服务单元文件。当系统启动进入多用户模式时,systemd 会自动启动这些软链接对应的服务。
查看 app 启动流程相关:如果 myapp需要在多用户模式下启动,可能会有一个软链接 `/etc/systemd/system/multi-user.target.wants/myapp.service` 指向实际的服务单元文件。
三. Systemd系统启动详解
在基于 systemd 的 Linux 系统中,`/usr/lib/systemd/system/`目录下的服务主要通过 systemd 管理器启动,systemd 会依据服务单元文件的配置,在系统启动、运行过程中对服务进行相应的启动操作。
系统启动时自动启动
如果服务单元文件(如`example.service` )的`[Install]`部分包含`WantedBy=multi-user.target`(`multi-user.target`代表多用户运行级别,系统启动到该级别时会启动一系列服务 )或其他目标(如`graphical.target`用于图形化界面启动 ),那么在系统启动进入对应目标时,systemd 会自动启动该服务。
systemd 会读取`/etc/systemd/system/`目录下的软链接(这些软链接指向`/usr/lib/systemd/system/`目录下的服务单元文件 ),进而启动对应的服务。
例如,若`/etc/systemd/system/multi-user.target.wants/example.service`是一个软链接,指向`/usr/lib/systemd/system/example.service`,系统进入多用户模式时就会启动`example`服务。
使用 systemctl 命令手动启动
在系统运行过程中,可使用`systemctl`命令手动启动服务。以启动`httpd`服务为例,在终端运行`sudo systemctl start httpd.service`,即可启动`/usr/lib/systemd/system/httpd.service`对应的服务 。
还能使用`systemctl`命令进行其他操作,如`sudo systemctl stop httpd.service`用于停止服务,`sudo systemctl restart httpd.service`用于重启服务,`sudo systemctl status httpd.service`用于查看服务状态 。
通过依赖关系触发启动
若一个服务(`serviceA` )的`[Unit]`部分设置了`After`或`Requires`等依赖关系,例如`After=network.target`表示`serviceA`在网络服务启动后启动,`Requires=mysql.service`表示`serviceA`依赖`mysql.service`,当被依赖的服务(如网络服务、`mysql.service` )启动或满足特定条件时,systemd 会依据依赖关系启动`serviceA`。
依赖关系与顺序关键字
`After` 和 `Before`:`After` 表示当前服务应在指定服务之后启动,`Before` 则相反,指定当前服务在哪些服务之前启动。例如,若服务 A 的配置中有 `After=serviceB.service`,那么服务 A 会在服务 B 启动之后才启动。
`Requires` 和 `Wants`:`Requires` 定义了强依赖关系,若所依赖的服务启动失败,当前服务也不会启动;`Wants` 是弱依赖关系,即使所依赖的服务启动失败,也不影响当前服务的启动。这两个关键字也会间接影响启动顺序,因为依赖的服务需要先启动。
默认依赖
systemd 规定了许多默认依赖,一般的服务需要等待默认依赖的服务启动完毕后才可以启动。这些默认依赖确保了服务在内核启动完毕、硬件设备驱动启动完毕、内存管理等启动完成之后才启动。
启动过程
系统启动时,systemd 首先启动那些没有依赖关系或者依赖关系已满足的服务。然后,按照依赖关系和顺序关键字,逐步启动其他服务。由于 systemd 采用并行启动的方式,在满足依赖条件的情况下,多个服务可以同时启动,以加快系统的启动速度。
依赖关系查看
通过 `systemctl list-dependencies` 命令查看某个服务的依赖关系,从而了解其启动顺序。例如,`systemctl list-dependencies AAA.service` 会列出 `AAA` 服务所依赖的其他服务以及它们的启动顺序。
下一篇详解Service参数。