Linux软件编程学习笔记(一):Linux基础、Shell编程与C语言开发环境
一、前言
在学习 C 语言之后,如果希望进一步进行嵌入式开发、服务器开发或者 Linux 下的 C/C++ 开发,仅仅掌握 C 语言语法是不够的。
我们还需要了解:
-
Linux 操作系统的基本概念;
-
Linux 文件系统;
-
Linux 常用命令;
-
Shell;
-
GCC 编译器;
-
GDB 调试工具;
-
Valgrind 内存检测工具;
-
静态库和动态库;
-
Makefile;
-
多文件程序编译。
这些内容共同构成了 Linux 软件开发的基础。
本文主要根据学习资料中的 Linux软件编程部分进行整理,将这些知识串联起来,形成一套比较完整的 Linux 软件开发入门知识体系。
二、什么是操作系统?
操作系统本质上也是一种软件。
它的一个重要作用是:
屏蔽底层不同硬件平台的差异,为上层应用程序提供统一的接口。
例如我们编写一个 C 程序时,并不需要直接操作 CPU、内存控制器、硬盘控制器等硬件,而是通过操作系统提供的接口完成相关操作。
常见的 PC 操作系统主要包括:
操作系统
├── Windows
├── Linux
└── Unix
Linux 在服务器和嵌入式领域具有非常广泛的应用。资料中也将 Linux 的典型应用场景归纳为服务器和嵌入式系统。
三、Linux操作系统
Linux 最重要的部分就是:
Linux Kernel(Linux内核)
Linux 内核主要负责管理计算机的各种硬件资源,并向上层软件提供服务。
根据学习资料,Linux 内核主要涉及以下五个方面:
Linux内核
│
├── 内存管理
├── 多任务调度
├── 文件系统管理
├── 多任务间通信
└── 网络通信
其中 Linux 文件系统有一个非常经典的特点:
Linux系统中一切皆是文件。
也就是说,普通文件、设备以及某些通信资源等,都可以通过文件的形式进行统一管理。
四、Linux内核、系统调用、Shell和库函数
学习 Linux 软件编程时,一个非常重要的概念就是:
应用程序
↓
库函数
↓
系统调用
↓
Linux内核
↓
硬件
4.1 Linux内核
Linux 内核负责:
-
内存管理;
-
进程调度;
-
文件管理;
-
网络通信;
-
进程间通信等。
应用程序一般不能直接操作硬件,而是通过内核提供的功能完成操作。
4.2 系统调用
系统调用是 Linux 内核向用户程序提供的接口。
例如:
open()
read()
write()
close()
fork()
这些接口可以让应用程序请求操作系统完成相应任务。
资料中将系统调用概括为:
Linux 内核中的函数接口,功能强大,但比较简练。
4.3 库函数
库函数可以理解为对系统调用进行进一步封装。
例如 C 语言中的:
printf()
scanf()
malloc()
free()
这些函数使用起来比直接进行底层系统调用更加方便。
因此可以简单理解为:
系统调用:更底层
↑
库函数:更加方便
↑
应用程序:直接使用
库函数通常具有更好的通用性,而系统调用则与具体操作系统关系更加密切。
五、什么是Shell?
Shell 可以理解为:
用户与 Linux 操作系统之间的命令解释器。
用户在终端输入:
ls
Shell 接收到命令之后进行解释,再调用相应的系统功能。
因此可以理解为:
用户
↓
Shell
↓
系统调用
↓
Linux内核
↓
硬件
Shell 的主要作用包括:
-
保护内核
-
命令解释器
学习资料中也将 Shell 定义为通过一系列命令完成 Linux 内核功能的命令解释器。
六、Linux常用Shell命令
掌握 Linux 软件编程之前,首先需要熟悉一些基本命令。
6.1 ls:查看文件
ls
查看当前目录下的文件。
常用:
ls -l
查看详细文件信息。
ls -a
查看包括隐藏文件在内的所有文件。
6.2 touch:创建文件
touch test.txt
创建一个普通文件。
6.3 mkdir:创建目录
mkdir test
创建 test 目录。
6.4 rm:删除文件
rm test.txt
删除普通文件。
如果需要删除目录及其内部内容:
rm -rf test
⚠️ rm -rf 删除操作具有较高风险,使用时一定要确认路径。
6.5 cp:复制文件
复制普通文件:
cp a.txt /home/linux/
复制目录:
cp test /home/linux/ -rf
6.6 mv:移动和重命名
移动文件:
mv a.txt /home/linux/
重命名:
mv old.txt new.txt
因此 mv 既可以用于移动文件,也可以用于修改文件名。
6.7 cd:切换目录
cd 目录
例如:
cd /home/linux
返回上一级:
cd ..
进入当前用户家目录:
cd ~
进入根目录:
cd /
6.8 pwd:查看当前路径
pwd
可以查看当前所在目录的绝对路径。
七、Linux文件类型
Linux 中可以通过 ls -l 查看文件的详细信息。
例如:
ls -l
可能看到:
drwxr-xr-x
-rw-r--r--
第一个字符表示文件类型。
常见类型:
| 符号 | 含义 |
|---|---|
- |
普通文件 |
d |
目录 |
l |
链接文件 |
b |
块设备文件 |
c |
字符设备文件 |
s |
Socket文件 |
p |
管道文件 |
资料中也特别强调了 Linux 中的 socket 和 pipe 文件,它们与进程间通信密切相关。
八、Linux文件权限
Linux 文件权限主要有三类:
r —— read 读
w —— write 写
x —— execute 执行
例如:
rwxr-xr--
可以拆成:
rwx | r-x | r--
↓ ↓ ↓
用户 用户组 其他用户
含义:
用户: 读 + 写 + 执行
用户组: 读 + 执行
其他人: 读
8.1 chmod修改权限
例如:
chmod 0664 filename
也可以使用符号方式:
chmod +x filename
给文件增加执行权限。
九、Shell中的管道和重定向
Shell 中非常实用的两个功能:
-
管道
-
重定向
9.1 管道 |
管道的作用是:
将前一个命令的输出作为后一个命令的输入。
例如:
ps -ef | grep "bash"
执行过程:
ps -ef
↓
输出所有进程
↓
grep "bash"
↓
筛选包含 bash 的内容
这也是 Linux 命令组合非常重要的一种方式。
9.2 输出重定向 >
例如:
ps -ef > file.txt
表示:
ps -ef
↓
输出内容
↓
file.txt
如果文件已经存在,> 会覆盖原有内容。
9.3 追加重定向 >>
ps -ef >> file.txt
与 > 不同:
> 覆盖
>> 追加
9.4 管道 + 重定向
例如:
tail -n 200 /usr/include/stdio.h | grep "extern" > file.txt
这条命令可以拆成三个步骤:
stdio.h最后200行
↓
grep查找extern
↓
保存到file.txt
这就是 Linux Shell 非常典型的命令组合方式。
十、文件查看与查找命令
10.1 cat
cat filename
直接查看文件内容。
10.2 more / less
用于分页查看较大的文件。
more filename
或者:
less filename
10.3 head / tail
查看文件开头:
head filename
查看文件末尾:
tail filename
例如查看最后 20 行:
tail -n 20 filename
10.4 find
查找文件:
find . -name "test.txt"
表示在当前目录及其子目录中查找 test.txt。
10.5 grep
搜索文件中的指定字符串:
grep "hello" test.txt
可以查找 test.txt 中包含 hello 的行。
十一、通配符
Shell 中常用的通配符包括:
*
匹配任意长度的字符。
例如:
file_*.txt
可以匹配:
file_1.txt
file_abc.txt
file_test.txt
?
匹配一个字符。
file_??.txt
[]
匹配指定范围或者指定字符。
例如:
file_[1-5].txt
可以匹配:
file_1.txt
file_2.txt
...
file_5.txt
十二、文件压缩与解压
Linux 中常用 tar 进行文件打包和压缩。
压缩:
tar -zcvf filename.tar.gz dirname/*
解压:
tar -zxvf filename.tar.gz
另外也可以使用:
tar -jcvf filename.tar.bz2 dirname/*
解压:
tar -jxvf filename.tar.bz2
十三、其他常用Linux命令
查看日期
date
查看系统信息
uname -a
可以查看 Linux 内核版本、系统架构等信息。
查看网络信息
ifconfig
测试网络连通性
ping www.baidu.com
查看历史命令
history
查看磁盘空间
du -m filename
或者:
du -k filename
十四、Linux软件安装
Linux 下常见的软件安装方式包括 dpkg 和 apt-get。
14.1 dpkg安装
对于 .deb 软件包:
sudo dpkg -i 软件包名.deb
卸载:
sudo dpkg -P 软件名
查看是否安装:
dpkg -l 软件名
十五、apt-get软件管理
如果使用 Ubuntu,可以使用:
sudo apt-get install 软件名
安装软件。
例如:
sudo apt-get install valgrind
安装 Valgrind。
安装 Wireshark:
sudo apt-get install wireshark
更新软件源:
sudo apt-get update
修复软件依赖:
sudo apt-get install -f
资料中还整理了 autoclean、update、install -f 等常用软件管理操作。
十六、Shell脚本
前面介绍的:
ls
cd
mkdir
cp
mv
grep
都是 Shell 命令。
如果我们把很多命令按照一定的逻辑组织起来,就可以形成:
Shell脚本
资料中将 Shell 脚本定义为:
一系列 Shell 命令的集合。
Shell 与 C 语言有一个明显区别。
C 语言属于:
编译型语言
而 Shell 属于:
解释型语言
简单理解:
C语言:
源代码
↓
编译
↓
可执行程序
↓
运行
Shell:
Shell脚本
↓
解释执行
Shell 开发效率较高,但执行效率通常不如编译型语言。
十七、编写第一个Shell脚本
首先创建文件:
vim test.sh
编写 Shell 代码。
然后增加执行权限:
chmod +x test.sh
执行:
./test.sh
资料中给出的基本流程就是:
创建脚本
↓
vim filename.sh
↓
chmod +x filename.sh
↓
./filename.sh
十八、Shell变量
Shell 中可以定义变量:
name=linux
使用变量:
echo $name
需要注意:
等号两边不能随意添加空格。
错误:
name = linux
正确:
name=linux
十九、Shell环境变量
常见环境变量:
PWD
HOME
PATH
例如:
echo $HOME
查看当前用户的家目录。
echo $PATH
查看系统的环境变量 PATH。
二十、Shell位置变量
Shell 脚本可以接收命令行参数。
例如:
./test.sh hello 123
脚本中:
$0
$1
$2
分别表示:
$0 → 脚本文件名
$1 → 第一个参数
$2 → 第二个参数
此外:
$# → 参数个数
$$ → 当前Shell脚本进程ID
$? → 上一条命令的返回结果
这些变量在 Shell 脚本开发中非常常用。
二十一、Shell中的引号
Shell 中常见三种引号:
" " 双引号
' ' 单引号
` ` 反引号
21.1 双引号
双引号中的变量会被解析。
例如:
name=Linux
echo "hello $name"
输出:
hello Linux
21.2 单引号
单引号中的内容一般按照原样处理。
name=Linux
echo 'hello $name'
不会按照变量值进行替换。
21.3 反引号
反引号可以将其中内容作为命令执行。
例如:
date=`date`
echo $date
它的作用可以理解为:
执行 date 命令
↓
获得命令结果
↓
赋值给变量
资料中也对这三种引号的作用进行了区分。
二十二、Shell输入与输出
Shell 中最常用的输入输出命令:
echo → 输出
read → 输入
22.1 echo
echo "Hello Linux"
输出:
Hello Linux
22.2 read
read name
从终端接收用户输入。
完整示例:
echo "请输入你的名字:"
read name
echo "你好,$name"
二十三、Shell中的if语句
Shell 中可以使用 if 进行条件判断。
基本结构:
if [ 判断条件 ]
then
语句
else
语句
fi
例如:
if [ -f test.txt ]
then
echo "文件存在"
else
echo "文件不存在"
fi
这里:
-f
用于判断指定路径是否为普通文件。
二十四、Shell中的case语句
如果需要根据多个不同情况执行不同操作,可以使用 case。
基本结构:
case 变量 in
值1)
语句
;;
值2)
语句
;;
*)
语句
;;
esac
例如:
case $score in
90)
echo "优秀"
;;
80)
echo "良好"
;;
*)
echo "其他"
;;
esac
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)