Linux系列-1 Linux启动流程——init与systemd进程

背景:

最近对所有项目完成了一个切换,服务管理方式由: init-> systemd。对相关知识进行总结一下。

1.启动流程

服务器的整体启动流程如下图所示:
在这里插入图片描述
POST:
计算机通电后进行POST( Power-On Self-Test )加电自检,检查 CPU、内存、硬盘、显卡、声卡、网卡等硬件是否正常工作; 检查完成后触发BIOS程序(来自主板)。

BIOS:
BIOS程序( Basic Input Output System )来自主板,被执行后会拥有整个裸机的执行权。BIOS会做以下几件事:
(1) 对硬件设置的检查和初始化 ;
(2) 加载MBR,并执行。BIOS加载启动盘的第一个扇区(0盘/0道/0扇区),将扇区的所有内容复制到内存中,并执行(将CPU的指令寄存器指向该内存)。
说明: (1) CPU被设计只能从内存中取数据和指令,启动过程中涉及的程序(保存在硬件中),都需要在执行前预先被加载到内存。(2) 在机器启动时,按F2(dell服务器)可以进入BIOS。在BIOS的启动选项菜单中可以选择引导设备,使用CD或者U盘安装系统时,将其作为首选引导设备;安装完成后,会自动弹出CD,重启服务器即可。如果把CD推入,重启会再走安装流程(安装完最好把它取出来)。

MBR:
MBR(Master Boot Record)表示硬盘的主引导记录,它位于第一个扇区(0盘/0道/0扇区)。MBR大小为512字节,包含446字节的引导加载程序(主boot-loader)、64字节的分区表信息、2字节的结束标志(0xAA55)。
主boot loader的唯一任务是加载次boot-loader(内核加载程序)。加载过程分为了主/次boot-loader两个加载器,因为512字节不足以完成将操作系统加载内核到内存的工作。

加载操作系统内核:
内核加载程序(grub/grub2)主要负责启动操作系统和加载内核。centos6(及以前)使用grub, 而centos7默认使用grub2。
说明:计算机上安装多个系统时,在grub/grub2阶段可以与用户交互,选择要加载的操作系统。
至此,计算机完全由操作系统接管。

init/systemd:
内核加载完成后,会启动第一个进程init/systemd. 在centos6及以前使用init进程管理服务,centos7及以后使用systemd守护进行管理服务。init/systemd会加载和运行其他的系统进程。
至此,开机启动完成。

2.init进程

2.1 Linux系统的运行级别

0-关机状态: 执行init 0会关闭计算机;
1-单用户模式:只支持root用户,不支持远程登录,一般用于系统维护;
2-多用户模式:支持多用户,不支持远程登录。
3-多用户-NFS:支持多用户,支持远程登录。
4-保留;
5-图形化(多用户、远程登录、支持图形化界面);
6-重启;

可以通过 init + 运行级别 实现系统运行级别的切换。

2.2 init进程的启动过程

(1) init进程从配置文件/etc/inittab中读取运行级别,根据运行级别来确定启动的程序。在CentOS 6中,默认的运行级别是运行级别3。
可以通过runlevel查看当前系统的运行级别:

>runlevel
N 5

(2) 启动子进程
对每个运行级别,在/etc/rc.d文件夹都有一个文件夹:rc0.d ~ rc6.d。比如:当运行级别是5时,rc3.d目录下的配置文件生效。包含如下文件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wH91aIfh-1700554024762)(C:\Users\0216001379\AppData\Roaming\Typora\typora-user-images\1700538088031.png)]
文件名格式为:K/S + 数字 + 服务名。K表示停止进程(Kill), S表示启动进程(Start); 数字表示运行级别,数字越小,执行越靠前。
此时,init进程会拉起network进程。

为防止在各个级别下(各个rcN.d目录下)都存放重复的文件,使用链接的形式引用。目录下的所有链接文件会指向/etc/init.d/目录下的脚本。当运行级别进行切换时,会给这些脚本进行传参,start或stop. 因此,需要安装模板规定开发服务脚本, 如下所示:

#! /bin/sh
# 准备操作SERVER_NAME='demo'start(){echo -e "\nStart ${SERVER_NAME}..."#todo: 启动逻辑echo -e "\nStart ${SERVER_NAME} success!"
}stop(){echo -e "\nShutdown ${SERVER_NAME}..."#todo: 停止逻辑echo -e "\nShutdown ${SERVER_NAME} finish!"
}case "$1" in"restart")stopstart;;"stop")stop;;"start")start;;*)echo "parameter error!! ";echo "three parameters are valid----restart, start, stop";;
esac

(3) init进程根据上述流程创建一系列子进程,当系统启动完成后,init进程将变成为守护进程,监视系统其他进程的运行状态,并在需要时重新启动它们。

2.3 常用API

添加服务
chkconfig --add ${servicename}删除服务
chkconfig --del ${servicename}查看所有的系统服务
chkconfig --list#查看指定服务信息
chkconfig --list ${servicename}设置服务的运行级别
chkconfig --level 运行级别 ${servicename} on/offeg:
设施mysql在运行级别为3和5下开机自启动
chkconfig --level 35 mysqld on

2.4 案例介绍

1.在/etc/init.d/目录下新建服务名,如ewen
脚本如下所示:

#! /bin/shecho "$@"SERVER_NAME='ewen'start(){echo -e "\nStart ${SERVER_NAME}..."echo -e "\nStart ${SERVER_NAME} success!"
}stop(){echo -e "\nShutdown ${SERVER_NAME}..."echo -e "\nShutdown ${SERVER_NAME} finish!"
}case "$1" in"restart")stopstart;;"stop")stop;;"start")start;;*)echo "parameter error!! ";echo "three parameters are valid----restart, start, stop";;
esac

此时,在环境上执行service命令时,可以将参数带入脚本:

>service ewen start a1 bc2 333 d4
#输出
start a1 bc2 333 d4
Start ewen...
Start ewen success

2.通过chkconfig将ewen服务注册到init:

chkconfig --add ewen

3.设置运行级别

chkconfig --level 3 ewen ewen on/off

3.systemd进程

init进程因串行化地启动程序,存在效率问题,且需要自定义脚本; systemd通过并行启动以及通过引入service配置文件,规避了上面两个问题。

ini使用service命令,systemd使用systemctl工具来管理,并且在操作上做了兼容处理(将service指令重定向到systemctl),如下所示:

>service ewen stop
Redirecting to /bin/systemctl ewen ota.service

在centos7之后(含centos7)使用systemd来管理程序, 通过ls -al /sbin/init 查看链接指向了systemd程序:
在这里插入图片描述
通过查看/etc/inittab也可以得到提示如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UXB1rjkn-1700565625746)(C:\Users\0216001379\AppData\Roaming\Typora\typora-user-images\1700548444781.png)]

通过ps 命令查看systemd的进程号(进程号为1):
在这里插入图片描述

3.1 启动流程

(1) 获取运行模式
当systemd进程启动后,会读取配置文件,确定运行模式。通过/etc/systemd/system/default.target文件链接到/usr/lib/systemd/system/multi-user.target还是/usr/lib/systemd/system/graphical.target确定运行模式。
在这里插入图片描述

(2) 获取需要开机启动的服务
multi-user模式为例,系统进入/etc/systemd/system/multi-user.target.wants获取所有配置的服务,并启动这些服务。
在这里插入图片描述

3.2 service配置文件介绍

3.2.1 文件路径

service配置文件用于自定义服务的启动顺序、运行方式、属组、启动方式等,可以将service文件放在
/usr/lib/systemd/[ system | user ]//etc/systemd/[ system | user ]/目录下。user表示用户服务,开机时不启动服务,用户登录后,才触发启动服务;system表示系统服务,开机时启动服务,而不需要用户登录。
/usr/lib/systemd/[ system | user ]/ 通常用于存放yum等软件安装的服务包。优先级/etc/systemd/system要高于/usr/lib/systemd/system
一般而言,自定义的服务建议放在/etc/systemd/system目录下。

3.2.2 service文件组成

如下所示是redis服务的service文件:

[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target[Service]
ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
ExecStop=/usr/libexec/redis-shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755[Install]
WantedBy=multi-user.target

由三个部分组成: [Unit]、[Service]、[Install],以下通过分章节分别进行介绍。

3.2.2.1 service文件的unit部分

unit部分可以定义服务描述、启动顺序和依赖关系。
描述
(1) Description:systemd使用Description描述服务信息(给读者看的,一般用一个简单的名称短语即可)。
(2) Documentation: 指定服务的详细说明文档(地址),多个使用空格进行分隔.

依赖关系
(1) Requires/Requisite:所依赖的单元必须已经启动,多个用都改分隔。
(2) RequiresAny: 指定列表中任意一个已经启动即可。
(3) PartOf:关联停止和重启,多个用逗号分隔。当被关联的服务停止或启动时,该服务也将随着停止和启动。
(4) BindsTo: 设置绑定服务列表,多个用逗号分隔。绑定列表中的所有服务被启动后,该服务才能被启动;绑定列表中的任一服务停止后,该服务被迫停止。绑定配置只有单向关系,即该服务停止后,不会影响列表中服务的状态。
(5) Conflicts: 指定相互冲突的服务,多个使用空格分开。该单元启动时,Conflicts指定的列表中所有单元都将被停止;列表中的某个单元启动时,该单元被停止。

启动顺序
systemd不够友好,依赖关系并不能保证启动顺序,需要用户通过Before和After手动指定。
redis.service文件中通过After指定了在network.target(网络服务)和yslog.target(系统日志服务)之后启动。即系统启动时,redis服务要等待network.target和yslog.target启动后才可启动。
可以通过空格进行分隔,也可以通过多个After项进行配置(如redis.service):

[Unit]
After=network.target
After=syslog.target

等价于:

[Unit]
After=network.target syslog.target

Before与After完全相反。

案例介绍
基于上述说明,对于不同场景,可以有一下组合:
case1:服务B在服务A之后重启,且依赖于服务A

B.service[Unit]
After=A.service

case2:服务A重启后,服务B必须重启

B.service[Unit]
After=A.service
PartOf=A.service

case3:服务C依赖于服务A或B

C.service[Unit]
RequiresAny=A.service B.service
After=A.service B.service

case4:服务D依赖于服务A和B,但是与C处于冲突状态

D.service[Unit]
Requires=A.service B.service
After=A.service B.service
Conflicts=C.service

3.2.2.2 service文件的service部分

用于定义服务的类型和属组,启停命令和重启机制、环境变量等。
服务类型:

鉴于章节篇幅,关于simple和forking的详细介绍在章节3.3中进行

Type定义服务类型:
simple:默认类型,使用当前线程作为主进程;
forking:服务会使用fork创建新进程,新进程作为主进程;
oneshot:一般用于执行一次性任务,与simple相似,区别在于systemd执行完oneshot类型才会认为该服务执行成功,而simple开始执行即认为执行成功。
除此之外,还有dbus, notify, idle等类型,因在开发过程中很少见,这里不进行说明。

服务的属组:
User和Group定义服务运行时归属的用户和群组。

启停命令:
(1) ExecStart和ExecStop和ExecReload指定启动和停止时执行的命令(含参数);
(2) ExecStartPre和ExecStartPost设置ExecStart启动前和启动后执行的命令;
(3) ExecStopPost设置停止后执行的命令;
(4) ExecReload表示重启服务时执行的命令。

环境变量:
Environment用于添加环境变量.

重启策略:
Restart和RestartSec用于配置服务重启策略。
(1) RestartSec定义重新启动服务的间隔时间, 单位:秒;
(2) Restart:服务重启策略:
no(默认值):不重启;
always:总是重新启动;
on-success/on-failure分别表示当服务正常退出(exit 0)/异常(exit 1)退出时重启.
(3) KillMode设置systemd停止服务的策略
control-group(默认值):kill主进程和所有子进程
none:不直接kill主进程或子进程,仅执行服务的stop命令
process:仅kill主进程
mixed:向主进程发送SIGTERM(kill)信号,向所有子进程发送SIGKILL(kill -9)信号。

说明: systemd提供了丰富的配置能力,可参考 https://www.jinbuguo.com/systemd/systemd.special.html

案例介绍:

[Service]
Type=forkingUser=ewen
Group=ewenExecStart=/usr/local/buaa/bin/ewen start
ExecStop=/usr/local/buaa/bin/ewen stop
ExecReload=/bin/kill -s HUP $MAINPIDEnvironment="EWEN_HOME=/usr/local/buaa"
#设置该服务可以打开的最大文件数为65535。
LimitNOFILE=65535PrivateTmp=true
Restart=on-failure
RestartSec=10KillMode=control-group

3.2.2.3 service文件的Install部分

通过WantedBy指定开机自启动模式,可指定为multi-user.target(多用户模式) 或 graphical.target(界面模式)等。上述的redis.service文件中: WantedBy=multi-user.target. 当执行systemctl enable redis[.service]时,创建一个链接文件:

> systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /etc/systemd/system/redis.service.

当执行systemctl disable redis[.service]时,删除该链接文件.

systemd启动时,如果是multi-user模式,则从/etc/systemd/system/multi-user.target.wants目录中读取service文件并启动,从而实现开机自启动;graphical模式,则从/etc/systemd/system/graphical.target.wants目录下读取。

也可为服务设置多种模式,通过空格分开,如:

[Install]
WantedBy=multi-user.target graphical.target

3.3 simple和forking服务类型

systemd启动simple和forking类型的服务流程如下图所示:
在这里插入图片描述
systemd进程启动服务时会fork子进程,然后委托这些systemd子进程去启动服务,即执行ExecStart配置的指令。
simple和forking对于systemd进程的核心区别在于“谁是我该监管的进程”:当启动simple类型的服务时,systemd子进程自身作为主进程,接受systemd的监管;而启动forking类型的服务时,systemd子进程将作为中间父进程退出,新创建的进程(systemd通过推断确定)作为主进程接受systemd的监管。
案例说明:
case1: simple服务类型
上述案例中redis的service部分如下所示:

[Service]
ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
ExecStop=/usr/libexec/redis-shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

没有定义Type,即使用默认的Type=simple类型。
启动redis后,查询进程状态:
在这里插入图片描述
此时,systemd跟总的主进程就是调用ExecStart指令的进程。该进程启动后,systemd就任务该服务启动成功。

case2: forking服务类型
nginx的service配置文件如下所示:

[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true[Install]
WantedBy=multi-user.target

通过Type=forking指定了服务类型。
启动nginx后,查询进程状态:
在这里插入图片描述
可以看到systemd实际监控的进程为18412,而执行ExecStart指令的进程为18409(中间进程,由systemd创建,已正常退出),该进程通过forking创建出了18412. 当中间进程退出且新进程生成后,systemd任务该服务启动成功。
另外,执行ExecStarPre的进程也是systemd创建的子进程。

上述案例的核心在于systemd监控的主进程,如果可以梳理清楚以下两种场景,simple和forking区别才算真正理解。

场景分析:
场景1: 应当设置为simple的服务被设置为了forking,会发生什么现象?
场景2: 应当设置为forking的服务被设置为了simple,会发生什么现象?

这里仅对第一种场景通过案例进行说明, 读者可通过相同方法对第二种进行梳理

# test.service文件
[Unit]
Description=test[Service]
Type=forking
ExecStart=/bin/bash -c "sleep 60"

给ExecStart设置的启动指令是sleep 60,即进程休眠1分钟。
执行systemctl start test后,systemd认为test服务是一个forking类型,因此等待这个进程退出(而该进程处于休眠状态,不会退出),所以通过systemctl status test查询test服务时,一直处于启动中状态:
在这里插入图片描述1分钟后,进程退出且没有新的进程被fork出来,systemd会认为该服务启动失败:
在这里插入图片描述
修改为simple类型后:

# test.service文件
[Unit]
Description=test[Service]
Type=simple
ExecStart=/bin/bash -c "sleep 60"

执行systemctl start test后,systemd认为simple服务是一个forking类型,执行完/bin/bash -c "sleep 60"指令后,systemd认为该服务启动成功:
在这里插入图片描述
1分钟后,进程退出,systemd会认为该服务退出运行:
在这里插入图片描述

3.4 systemctl

(1) 运行模式:

#设置graphical运行模式
systemctl set-default graphical.target#设置multi-user运行模式
systemctl set-default multi-user.target#获取运行模式
systemctl get-default

设置运行模式的本质,就是将/etc/systemd/system/default.target指向/usr/lib/systemd/system/multi-user.target/usr/lib/systemd/system/graphical.target.

(2) 注册服务:
将服务的service文件放到systemd管理的路径(比如/etc/systemd/system/目录)后,指向以下命令进行重新加载:

systemctl daemon-reload

(3) 启停服务(常用):

#启动服务
systemctl start 服务名[.service]#停止服务
systemctl stop 服务名[.service]#重启服务
systemctl restart 服务名[.service]#查看服务状态
systemctl status 服务名[.service]

(4) 开机自启动:

#开启开机自启动
systemctl enable 服务名[.service]#关闭开机自启动
systemctl disable 服务名[.service]

设置开机自启动本质是在/etc/systemd/system/multi-user.target.wants/目录下创建了一个链接文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/192765.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux之buildroot(3)配置软件包

Linux之buildroot(3)配置软件包 Author:Onceday Date:2023年11月30日 漫漫长路,才刚刚开始… 全系列文章请查看专栏: buildroot编译框架_Once_day的博客-CSDN博客。 参考文档: Buildroot - Making Embedded Linux Easymdev.t…

Hdoop学习笔记(HDP)-Part.17 安装Spark2

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

canvas 轮廓路径提取效果

前言 微信公众号:前端不只是切图 轮廓 对内容做border效果,可以先看下代码运行的效果 内容是黑线构成的五角星,其轮廓就是红线的部分,本文主要介绍如何在canvas中实现这种效果 Marching Square 这里运用到的是marching square算法…

鸿蒙是Android套壳么,当然不是,ArkTS还是很有意思的

前段时间看新闻,说是明年开始鸿蒙就要和andorid脱钩了。 大概就是这样的: 看到这个,我兴趣就来了。我有个华为P30,升级过鸿蒙系统,用起来也没啥变化,兼容andorid应用,然后就是开机去掉了Powere…

数据库表的管理

表的基本概念 表是包含数据库中所有数据的数据库对象。数据在表中的组织方式与在电子表格中相似,都是 按行和列的格式组织的。每行代表一条唯一的记录,每列代表记录中的一个字段。例如,在包含公 司员工信息的表中,每行代表一名员工…

19.字符串——查找三个字符串中的最大字符串(打擂台)

文章目录 前言一、题目描述 二、题目分析 三、解题 程序运行代码 四、举一反三总结 前言 本系列为字符串处理函数编程题&#xff0c;点滴成长&#xff0c;一起逆袭。 一、题目描述 查找三个字符串中的最大字符串 二、题目分析 打擂台 三、解题 程序运行代码 #include<…

从零开始:PHP实现阿里云直播的简单方法!

1. 配置阿里云直播的推流地址和播放地址 使用阿里云直播功能前&#xff0c;首先需要在阿里云控制台中创建直播应用&#xff0c;然后获取推流地址和播放地址。 推流地址一般格式为&#xff1a; rtmp://{Domain}/{AppName}/{StreamName}?auth_key{AuthKey}-{Timestamp}-{Rand…

如何使用手机制作证件照

1、打开vx搜索小&#x1f34a;x名称&#xff1a;标准证件照免冠照 2、选择你需要的证件照尺寸类型 3&#xff0e;选择手机照片生活照或者点击开始拍摄&#xff08;建议纯色的墙面好换底色&#xff09; 4&#xff0e;选择背景颜色&#xff0c;红底&#xff0c;蓝底奉背景颜色随你…

数据库管理-第121期 我为什么写文章(202301203)

数据库管理-第121期 我为什么写文章&#xff08;202301203&#xff09; 其实呢~大周末我不是太想写文章的&#xff0c;周五HaloDB起了个头还有一堆可以做的事情都计划到下周了&#xff0c;但是昨天发生了一件事情&#xff0c;让我很是不开心&#xff1a;强盗逻辑&#xff0c;白…

前端入门(五)Vue3组合式API特性

文章目录 Vue3简介创建Vue3工程使用vite创建vue-cli方式 常用 Composition API启动项 - setup()setup的执行时机与参数 响应式原理vue2中的响应式vue3中的响应式ref函数reactive函数reactive与ref对比 计算属性 - computed监视属性 - watchwatchEffect Vue3生命周期自定义hook函…

服务器数据恢复—V7000存储raid5崩溃导致上层卷无法使用的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌V7000存储中有一组由几十块硬盘组建的raid5阵列。上层操作系统为windows server&#xff0c;NTFS分区。 服务器故障&#xff1a; 有一块硬盘出现故障离线&#xff0c;热备盘自动上线替换离线硬盘。在热备盘上线同步数据的过程&#xff0c…

西南科技大学模拟电子技术实验五(集成运算放大器的应用设计)预习报告

一、计算/设计过程 设计一:用集成运放设计一个输入为0.05v,放大为-100的反相比例运算电路。 对于理想电路,反相比例运算电路的输出电压与输入电压之间的关系如下: =-100,所以 =100 若是假定R1为100k,则R2= =1k 为了减小输入级偏置电流引起的运算误差,在同相输入端…

解决:IDEA的debug模式只有第一次能拦截请求进行debug,后续所有请求全部失效

解决&#xff1a;IDEA的debug模式只有第一次能拦截请求进行debug&#xff0c;后续所有请求全部失效 一问题描述&#xff1a;IDEA的debug模式只有第一次能拦截请求进行debug&#xff0c;后续所有请求全部失效二问题原因&#xff1a;对IDEA的debug功能不熟悉或者理解有偏差三解决…

数学字体 Mathematical fonts

Mathematical fonts 数学字体&#xff1a; ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ \\ \mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ} \\ \mathfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ} \\ \mathbb{ABC…

HTML标签

1&#xff0c;HTML语法规范 1.1基本语法概述 1&#xff0c;HTML标签是由<>包围的关键词&#xff0c;例如<html> 2&#xff0c;HTML标签通常是成对出现的&#xff0c;例如<html>和</html>,称为双标签。标签对中的第一个标签是开始标签&#xff0c;第…

分治-归并算法——LCR 170. 交易逆序对的总数

文章目录 &#x1f33c;0. 归并排序&#x1f33b;1. 题目&#x1f33c;2. 算法原理&#x1f337;3. 代码实现 &#x1f33c;0. 归并排序 归并排序是典型的分治&#xff0c;将数组分成若干个子数组&#xff0c;数组两两比较&#xff0c;不是很清楚的&#xff0c;可以查看此篇文…

鸿蒙(HarmonyOS)应用开发——容器组件(Grid组件)

前言 前面一篇文章中&#xff0c;已经说了List组件。那么接下来就是容器组件中的Grid组件 #mermaid-svg-oz1b7w45ASmMlZFa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-oz1b7w45ASmMlZFa .error-icon{fill:#5522…

最大单词数算法分析

题目描述&#xff1a; 算法一&#xff1a; 代码实现&#xff1a; # include<stdio.h> # include<string.h>int main(){//char text[100]"leet code";//char brokenLetters[26]"lt";char text[100]"hello world";char brokenLetters…

HBASE命令行查看中文字符

问题记录 中文显示的是编码字符不方便查看value\xE5\xB8\xB8\xE5\xAE\x89\xE5\xAE\x891修改前中文显示&#xff1a; 解决方法 1、列族 : 列名 : toString ’2、列族 : 列名 : c(org.apache.hadoop.hbase.util.Bytes).toString ’ scan karry:student,{COLUMNS > [info:…

国际语音通知是什么?国际语音通知系统有哪些功能?

一、国际语音通知是什么&#xff1f; 如同国际短信通知&#xff0c;国际语音通知也在多种生活场景中扮演着重要的角色&#xff0c;如会议通知、商品发货通知、物流更新通知、快递取件通知、外卖取餐通知等。那么什么是语音通知呢&#xff1f; 国际语音通知可将通知的文本信息使…