前面结束了数据结构的相关内容,我们又得继续下一个内容的学习,也就是Linux软件编程,这一部分的内容也相对较多,需要循序渐进的学习,那就跟着博主一起来学吧:
1、操作系统基本概念

操作系统可以看成是一个软件,功能是用来屏蔽底层不同的硬件平台,为上层应用提供统一的接口和运行环境
操作系统类型:
|---------|--------------------------|
| Unix | 经典老牌,现代 OS 鼻祖 |
| Linux | 高效运行、开源免费,内核基于 Unix 思想开发 |
| Windows | 视窗界面友好 |
**Linux应用领域:**服务器、嵌入式领域、机器人、Android手机、平板、广告机、视频记录仪、路由器、交换器等
(1)Linux内核---功能:
- 内存的管理
- 文件系统的管理
- 任务的调度 //FreeRTOS实现的功能
- 多任务的通信
- 网络功能的管理
- 对硬件设备的管理
(2)Shell:
1、保护内核,用户不直接操作内核,所有请求都通过 Shell 中转,避免用户直接调用内核接口引发系统崩溃
2、命令行解释器 :是用户与内核之间的交互接口,读取解析用户命令并转化为对系统调用或可执行程序的调用请求 → 传递请求给内核→ 内核直接执行指令(直接执行其早已编译好的二进制代码(最初由C等语言编写))
(3)库函数:
1、库函数是**封装好的可复用代码集合,**便于用户函数调用
2、简化开发
系统调用是内核提供的底层接口,语法繁琐、平台差异大;库函数对其封装,提供简洁统一的调用接口,比如用printf打印,无需直接操作底层的系统调用
3、跨平台兼容性(便于移植)
同一套标准库函数可以在 Windows、Linux、macOS 编译运行,底层适配不同系统的系统调用,开发者无需关注平台差异。
2、Shell命令
2.1 命令格式
bash
command [options] [arguments]
options:选项,用于调整命令行为,短选项用-开头(如-n),长选项用--开头(如--help),多个短选项可合并(cat -n -v = cat -nv)
arguments:参数,命令操作的对象(如文件名、路径、字符串),是可选部分
格式中[]代表可选内容,不是命令的一部分,输入时无需书写
2.2 常用命令
2.2.1 文件查看命令
(1)cat
功能: 查看文件全部内容(查看小型文本文件更适合)
bash
cat filename # 查看文件全部内容
cat -n filename # 显示行号(包含空行)
cat -b filename # 显示行号(跳过空行)
(2)head/tail
功能:head 查看文件开头内容,tail查看文件末尾内容, 默认显示10行
bash
head -n 10 filename # 查看文件前10行(-n可省略,直接写 head -10 filename)
tail -n 10 filename # 查看文件后10行
tail -f filename # 实时追踪文件新增内容(查看日志必备,如服务运行日志)
2.2.2 管道符 |
功能:将前一个命令的标准输出,作为后一个命令的标准输入,实现命令组合
bash
# 筛选文件前10行中包含指定字符串的内容
head -n 10 filename | grep "字符串"
# 筛选头文件末尾10行中包含extern的内容
tail -n 10 /usr/include/stdio.h | grep "extern"
# 查看系统中与bash相关的进程信息
ps -ef | grep bash
注意:管道仅传递标准输出 (stdout),错误信息 不会通过管道传递
2.2.3 文件搜索命令---grep
功能:在文件 / 输入流中按规则搜索字符串 / 正则表达式,输出匹配行
bash
# 在指定文件中搜索字符串
grep "目标字符串" 文件名
grep -i "字符串" filename # 忽略大小写搜索
grep -v "字符串" filename # 反向匹配,输出不包含该字符串的行
grep -n "字符串" filename # 显示匹配行的行号
grep -c "字符串" filename # 仅统计匹配的行数
2.2.4 重定向
功能: Shell 默认将输出打印到终端(标准输出),重定向可将输出写入文件 / 其他设备,分为输出重定向和输入重定向 将原来输出在终端的内容写入到文件中
输出重定向
| 符号 | 作用 | 示例 |
|---|---|---|
> |
覆盖重定向 | 若文件不存在则创建,存在则清空原有内容后写入 |
>> |
追加重定向 | 若文件不存在则创建,存在则在文件末尾追加内容 |
bash
echo "hello" > test.txt # 覆盖写入test.txt
echo "world" >> test.txt # 追加内容到test.txt
输入重定向( < )
bash
# 正常方式:grep从文件读取
grep "error" log.txt
# 输入重定向方式:功能完全一样!
grep "error" < log.txt
2.2.5 通配符
功能: 用于匹配文件名 / 路径,配合 ls、rm、cp 等文件操作命令使用
| 通配符 | 含义 | 示例 |
|---|---|---|
* |
匹配任意长度、任意字符(包含空字符) | ls *.txt 匹配所有 txt 文件 |
? |
匹配单个任意字符 | ls file?.txt 匹配 file1.txt、filea.txt |
[] |
匹配括号内任意一个字符 | ls file[123].txt 仅匹配 file1/2/3.txt |
[^] |
匹配不在括号内的单个字符 | ls file[^0-9].txt 排除数字命名文件 |
注意 :通配符是 Shell 解析的,不是命令自身功能
2.2.6 文件权限管理
(1)权限基础规则
Linux 文件权限分三类用户:
- 属主 (u):文件的创建者 / 所有者
- 属组 (g):文件所属用户组的成员
- 其他用户 (o):系统内除 u、g 外的所有用户
权限对应符号与数字权重:
| 权限 | 符号 | 数字权重 | 含义 |
|---|---|---|---|
| 读 | r |
4 | 读取文件内容 / 查看目录结构 |
| 写 | w |
2 | 修改文件内容 / 在目录内增删文件 |
| 执行 | x |
1 | 执行脚本 / 进入目录 |
权限组合计算:rwx=4+2+1=7,rw-=6,r-x=5,---=0
(2)修改文件 / 目录权限:chmod
bash
chmod 0777 filename
# 三位数字依次对应:属主、属组、其他用户 权限
# 0为特殊权限位,日常使用可省略,直接写 chmod 755 filename
chmod u+x filename # 给属主添加执行权限
chmod g-w filename # 给属组移除写权限
chmod a=r filename # 所有用户(u/g/o)统一设置为只读权限
#加-R选项递归修改目录下所有子文件 / 子目录权限,包括目录自身
chmod -R 755 test_dir/
rwx:创建文件的用户对文件是否拥有读写执行的权限
rwx:创建文件的同组用户对文件是否拥有读写执行的权限
rwx:其余人是否拥有读写执行的权限
(3)修改文件所属的组:chgrp
bash
# 查看所有组
cat /etc/group
sudo chgrp 组名 filename # 修改文件所属组,组必须存在
chown:
(4)chown:修改文件所属的用户 ,同时可修改所属组
**功能:**同时支持修改属主和属组,比chgrp更通用
bash
chown 用户名 filename # 仅修改文件属主,也必须存在
chown 用户名:组名 filename # 同时修改属主和属组(常用)
2.2.7 压缩和解压缩
(1) 核心参数释义
| 参数 | 作用 |
|---|---|
-c |
create,创建归档 / 压缩包(压缩必备) |
-x |
extract,解压归档 / 压缩包(解压缩必备) |
-v |
verbose,显示压缩 / 解压的详细过程(可选,方便查看进度) |
-f |
file,指定压缩包文件名,必须放在所有参数最后一位 |
-z |
调用gzip算法,对应.tar.gz/.tgz格式 |
-j |
调用bzip2算法,对应.tar.bz2/.tbz格式 |
(2) 压缩命令
bash
# 压缩为 .tar.gz 格式(gzip,压缩速度快,使用率最高)
tar -zcvf filename.tar.gz dirname/
# 压缩为 .tar.bz2 格式(bzip2,压缩率更高,速度稍慢)
tar -jcvf filename.tar.bz2 dirname/
tar -zcvf /target/archive.tar.gz source/ 压缩到指定目录,直接指定输出文件路径
注意:
dirname/* 可简化为 dirname/,效果一致,会打包目录下所有文件;
-f 参数必须紧跟压缩包名称,不能穿插其他参数
(3)解压缩命令
bash
# 解压 .tar.gz 格式
tar -zxvf filename.tar.gz
# 解压 .tar.bz2 格式
tar -jxvf filename.tar.bz2
# 解压到指定目录(-C 参数,大写C)
tar -zxvf filename.tar.gz -C /home/test/
2.2.8 查找文件---find
bash
find [搜索起始目录] [匹配条件] "文件名"
# 精确查找文件(区分大小写)
find /home -name "test.txt"
# 忽略大小写查找(-iname,更常用)
find /home -iname "TEST.txt"
# 结合通配符模糊查找
find /etc -name "*.conf" # 查找所有.conf后缀配置文件
find /home -type f # 只查找普通文件,排除目录
find /home -type d # 只查找目录
find /home -size +100M # 查找大于100MB的文件 100k(小写)
find /home -mtime -7 # 查找7天内修改过的文件
2.2.9 其余命令
(1)echo:
功能:在终端输出字符串、变量值,配合重定向可快速写入文件;在终端显示对应内容
bash
echo "Hello Linux" # 输出固定字符串
echo $PATH # 输出系统环境变量PATH的值
echo -n "无换行输出" # -n:取消末尾自动换行
echo "追加内容" >> test.txt # 结合追加重定向写入文件
(2)du:
功能 :disk usage,统计文件 / 目录的磁盘占用大小
bash
du -h # 人性化显示单位(KB/MB/GB,最推荐使用)
du -m # 以MB为单位显示大小
du -k # 以KB为单位显示大小
du -sh dirname/ # 统计目录总大小,不展示子文件详情(高频用法)

(3)fdisk :
功能 :查看磁盘分区信息,仅 root / 授权用户可执行
bash
sudo fdisk -l # 列出系统所有磁盘及分区信息(含容量、格式、挂载点)
(4)sudo:
功能 :switch user and do,临时以超级用户(root)权限执行命令,避免长期使用 root 账户带来风险
使用超级用户的权限来执行某个操作
bash
sudo [需要提权的命令]
示例:sudo vim /etc/hosts(修改系统配置文件需要提权)
(5)date:
功能:查看 / 设置系统日期和时间
bash
date # 查看当前系统时间(默认格式)
date "+%Y-%m-%d %H:%M:%S" # 自定义格式:年-月-日 时:分:秒

(6)whoami :
功能 :快速查看当前登录终端的用户名
bash
whoami
(7)ps:
功能 :process status,查看当前系统进程信息(静态查看,执行一次输出一次结果)
bash
ps -ef # 查看系统所有进程完整信息(含PPID父进程ID、用户、命令等)
ps aux # BSD格式展示进程,是Linux下更通用的写法,展示内容更全面
(8)top:
功能 :实时动态监控系统进程与资源占用(CPU、内存、负载),默认按 CPU 使用率排序
bash
top # 直接执行进入监控界面
q:退出 top 界面
M:按内存占用率排序
P:恢复按 CPU 使用率排序

(9)ifconfig:
**功能:**查看网卡信息
bash
ifconfig # 查看所有激活网卡的信息
ip addr #推荐使用
(10)ping :
功能 :测试本机与目标主机的网络连通性和网络质量,基于 ICMP 协议
bash
ping www.baidu.com # 测试与百度服务器连通性
ping 192.168.1.1 # 测试局域网内设备连通性
ping -c 4 www.baidu.com # -c:指定发送数据包数量,发送4次后自动停止(避免无限ping)
2.2.10 dpkg工具集
dpkg是底层包管理工具 ,仅能管理本地已下载的 .deb 格式安装包,无法自动解决软件依赖问题,依赖缺失会导致安装失败。
bash
#安装软件
sudo dpkg -i filename.deb # -i=install
#查看软件是否安装成功(已安装的软件)
dpkg -l | grep 软件名
#彻底卸载软件(删除配置)
sudo dpkg -p 软件名 # -P=purge,彻底删除程序 + 配置文件
#仅卸载软件(保留配置)
dpkg -r 软件名 #-r=remove,删除程序,保留配置文件
注意:
执行dpkg -i安装失败(提示依赖缺失)时,可通过 sudo apt-get install -f 修复依赖。
2.2.11 apt-get工具集
apt-get 是高级包管理工具 ,基于dpkg封装,自动从软件源下载包、解析并安装所有依赖 ,是日常安装软件的首选;新版系统推荐使用简化版命令 apt,功能一致且更易用。
可以自己根据配置的源下载对应的软件
根据软件依赖关系安装软件所需要的所有依赖
1、网络检测,先查看是否可以上网:ping 8.8.8.8 # 检测外网连通性,正确
ping -c 4 8.8.8.8 # 推荐用法:发送4个包后自动停止,避免无限ping
若无法上网,则:
(1)让虚拟机使用NAT模式:
点击"虚拟机"
点击"设置"
点击"虚拟网络适配器"
选择"NAT模式"
点击"确认"
(2)修改Ubuntu配置文件
打开配置文件:
sudo vim /etc/network/interfaces
修改配置文件为如下格式:
auto lo
iface lo inet loopback
auto ens33
iface ens33 inet dhcp
保存退出
:wq
(3)重启Ubuntu
sudo reboot / sudo shutdown -r now
2、配置apt-get工具集的源
(1)点击"Ubuntu Software"
(2)右键选择"Software & Updates"
(3)「Download from」选择「Other」,筛选国内镜像源,源选择 aliyun
(4)点击"close"
(5)输入命令
sudo apt-get autoclean # 清理旧版本安装包缓存
sudo apt-get update # 刷新软件源缓存(必须执行,同步最新软件列表)
sudo apt-get install -f # 修复系统中缺失的依赖包
3、软件安装
#安装软件
sudo apt-get install 软件名 #自动处理依赖
#彻底卸载软件
sudo apt-get remove 软件名 --purge
sudo apt-get purge 软件名
#卸载软件(保留配置)
sudo apt-get remove 软件名
3、shell编程
3.1 解释型语言与编译型语言
**解释型语言:**边翻译边执行,不生成独立可执行文件
核心特点: 开发效率高、执行效率较低、适合做复杂数据运算、适合对系统自动化管理
**代表语言:**Shell、Python
**编译型语言:**源码先通过编译器编译为机器码文件,再直接执行(先编译再执行)
**核心特点:**开发效率低、执行效率高、运行速度快、适合做大规模数据运算,有丰富的数据类型和底层操作能力
**代表语言:**c/c++、c#
3.2 shell脚本开发流程
bash
#脚本首行规范:必须添加解释器声明
#!/bin/bash
# 这是注释,# 开头的行不会被执行
# 1. 编辑脚本(推荐指定bash解释器)
vim test.sh
# 2. 添加执行权限
chmod +x test.sh
# 3. 相对路径执行(运行)
./test.sh
shell脚本本质:
Shell 脚本是一系列 Shell 命令、语法结构、变量的有序集合,系统逐行解析执行,实现自动化操作。
3.3 shell脚本中的引号
bash
echo "当前路径:$(pwd)"
| 引号类型 | 语法规则 | 变量解析 | 命令执行 | 示例 |
|---|---|---|---|---|
双引号 " " |
弱引用 | 解析变量,替换为变量值 | 支持$()执行命令 |
echo "当前目录:$PWD" |
单引号 ' ' |
强引用 | 不解析变量,原样输出 | 不执行任何命令 | echo '输出纯文本 $PWD' |
反引号 |
命令替换 | 执行引号内命令,输出结果替换自身 | 执行系统命令 | ``echo 当前时间:```date` |
注意:
反引号可读性差,现代 Shell 推荐用 $() 替代反引号,功能一致且支持嵌套
3.4 shell中的变量
3.4.1 预定义环境变量
系统内置变量,存储系统配置信息,可直接调用(shell脚本中用来存放系统相关信息的变量)
PWD:当前工作目录的绝对路径HOME:当前用户的家目录PATH:系统查找可执行文件的路径集合(系统软件默认的路径)SHELL:当前使用的 Shell 解释器类型
3.4.2 位置参数变量
用于接收脚本执行时传入的外部参数,是脚本交互核心:
| 变量 | 含义 |
|---|---|
$0 |
当前脚本的文件名 / 路径 |
$1 |
第一个传入参数 |
$2 |
第二个传入参数 |
$# |
传入参数的总个数 |
$? |
上一条命令的退出状态码 :0= 执行成功,非0= 执行失败 |
$$ |
当前脚本运行的进程 ID号(PID) |
示例 :./test.sh a b c,则 $1=a,$2=b,$3=c,$#=3
3.4.3 自定义变量
定义规则
- 格式:
变量名=值,等号两侧绝对不能有空格(Shell 语法强制要求) - 变量名规范:由字母、数字、下划线组成,不能以数字开头
- 调用变量:
$变量名或${变量名}(推荐后者,避免变量名歧义)
示例:
bash
# 定义变量
i=0
str="hello world"
# 调用变量
echo $i
echo ${str}_shell # 拼接字符串,{}区分变量边界
3.5 流程控制语句
3.5.1 分支语句:if
基本格式:
bash
if [ 表达式 ]; then # 推荐简写格式,[] 两侧必须有空格
语句块
elif [ 表达式 ]; then
语句块
else
语句块
fi
if [ 条件 ]
then # 如果then换行,可以省略分号
语句
fi
test 与 []
[ 表达式 ] 等价于 test 表达式,用于条件检测,常用场景:
- 数值比较:
-eq(等于)、-ne(不等于)、-gt(大于)、-lt(小于) - 文件检测:
-f 判断是否为普通文件、-d 判断是否为目录 - 字符串比较:
=判断相等
示例:
bash
num=10
if [ $num -gt 5 ]; then
echo "数字大于5"
fi
# Bash支持两种语法,推荐第一种
if [[ $str == "test" ]]; then # [[ ]] 是Bash关键字,更强大
echo "匹配"
fi
# 使用(( ))进行算术比较
if (( a > b )); then
echo "a大于b"
fi
| 特性 | [[ ]] |
(( )) |
|---|---|---|
| 类型 | 条件表达式 | 算术表达式 |
| 用途 | 字符串、文件测试 | 数值计算和比较 |
| 返回值 | 逻辑真/假(0/1) | 算术结果(数值) |
| 是否需要$ | 需要变量前的$ | 不需要变量前的$ |
| 示例 | [[ $str == "test" ]] |
(( a > b )) |
3.5.2 多分支:case
bash
case 变量值 in
9)
语句块
;; # 每个分支必须以双分号结尾
8)
语句块
;;
*) # 通配符,匹配所有未命中的情况(默认分支)
语句块
;;
esac # case的结束标记,是case的反写
支持通配符匹配 ,可匹配多个值:9|8|7) 语句块 ;;
4、循环语句
4. 1 for循环
格式 1:遍历列表
bash
# 遍历字符串/文件列表
for var in 1 2 3 4 5
do
echo "数值:$var"
done
格式 2:类 C 语言风格
bash
for ((i=0; i<5; i++))
do
echo $i
done
4.2 while循环
条件为真时循环执行,适用于未知循环次数场景:
bash
i=1
while [ $i -le 5 ]
do
echo $i
i=$((i+1)) # 数值自增运算
done
4.3 until循环
条件为假时循环执行,与 while 逻辑相反:
bash
i=1
until [ $i -gt 5 ]
do
echo $i
i=$((i+1))
done
4.4 循环控制关键字
break:跳出整个循环continue:跳过当前次循环,执行下一次
5、数组
Shell 仅支持一维数组,不支持多维数组,核心用法:
bash
# 方式1:直接赋值
arr=("apple" "banana" "orange")
# 方式2:指定下标赋值
arr[0]="red"
arr[1]="blue"
echo ${arr[0]} # 获取单个元素
echo ${arr[*]} # 获取所有元素
echo ${#arr[*]} # 获取数组长度
6、函数
Shell 函数用于封装复用代码,无返回值类型限制,通过状态码 /echo 传递结果。
6.1 函数定义
bash
# 标准格式
function 函数名() {
语句块
# return 数字:设置函数退出状态码(0-255)
}
# 简化写法(省略function关键字,更常用)
函数名() {
echo "执行函数:$1" # 函数内 $1 接收第一个参数
}
6.2 函数调用与参数
bash
# 调用函数,直接写函数名,后接参数
print_info "hello" "shell"
# 函数内获取参数:$1 $2 $# 规则与脚本位置参数一致
6.3 获取函数结果
bash
# 方式1:通过echo输出结果,外部用$()接收
add() {
echo $(( $1 + $2 ))
}
res=$(add 1 2)
echo "计算结果:$res"
7、expr:表达式计算器
基本功能:
expr 主要用于整数运算、字符串操作和逻辑比较。
bash
# 整数运算(注意:运算符两侧必须有空格)
expr 10 + 5 # 输出: 15
expr 20 - 3 # 输出: 17
expr 6 \* 3 # 输出: 18(*需要转义)
expr 15 / 4 # 输出: 3(整数除法)
expr 15 % 4 # 输出: 3(取模)
# 字符串长度
expr length "hello" # 输出: 5
# 子串查找
expr index "hello" "l" # 输出: 3(第一个'l'的位置)
# 子串提取
expr substr "hello" 2 3 # 输出: ell(从第2位开始取3个字符)
bash
# expr的现代替代
# 算术运算 → $(( ))
echo $((10 + 5)) # 15
echo $((20 * 3)) # 60(不需要转义)
# 字符串长度 → ${#var}
str="hello"
echo ${#str} # 5
# 子串提取 → ${str:start:length}
echo ${str:1:3} # ell
8、seq:序列生成器
基本用法:生成数字序列
bash
# 生成1到5
seq 5
# 输出:
# 1
# 2
# 3
# 4
# 5
# 指定范围
seq 3 7
# 输出:
# 3
# 4
# 5
# 6
# 7
# 指定步长
seq 1 2 10
# 输出:
# 1
# 3
# 5
# 7
# 9
# 反向序列
seq 10 -2 1
# 输出:
# 10
# 8
# 6
# 4
# 2
实际应用:
bash
# 批量创建目录
for i in $(seq 1 10); do
mkdir "day$i"
done
现代替代方案:
bash
# Bash的brace expansion(简单序列)
echo {1..5} # 1 2 3 4 5
echo {1..10..2} # 1 3 5 7 9
echo {10..1..-2} # 10 8 6 4 2
# for循环替代
for i in {1..5}; do
echo $i
done
# 使用C语言风格的for循环
for ((i=1; i<=5; i++)); do
echo $i
done