文章目录
- 一、Linux简介
- 二、Linux子系统
- 三、Linux命令行 (shell命令)
- (一) 目录命令:文件与目录管理 (File & Directory Ops)
- (二) 文件命令:文本处理与搜索 (Text Processing & Search)
- 1.创建文件:echo、touch、vim
- 2.搜索文件内容:grep
- 3.awk:按行号提取内容
- 4.查找文件:find
- 5.查找文件:which
- 6.查看文件内容/拼接文件:cat
- 7.查看文件的前几行:head
- 8.查看文件的后几行:tail
- 9.分页浏览:more、less
- 10.文件的行数、单词统计:wc (word count)
- 11.命令的组合:3种
- 12.修改文件权限:chmod (change mode)
- 13.文件创建掩码:umask
- 14.链接:硬链接和符号链接
- 15.打包、压缩、解压命令:unzip、tar
- 16.同时显示命令输出,并保存到文件:tee
- 17.对比两文件的内容是否相同,求文件的md5码值
- (三) 系统命令:系统管理与监控 (System Admin & Monitoring)
- 1.修改主机名、IP、源
- 2.查找特定进程:ps aux | grep
- 3.关机与重启
- 4.查系统内存:lshw -short -C memory、dmidecode -t memory | grep "Manufacturer:"
- 5.设置GRUB: /etc/default/grub:限制Linux内核的内存使用
- 6.Linux用户
- 7.时间
- 8.设置别名:alias
- 9.查看历史命令:history
- 10.查看当前服务器有多少用户在登录:who
- 11.查询系统中的逻辑处理器数量
- 12.查看自己的Ubuntu版本
- 13.修改时区
- 14.lsmod:列出当前已加载的内核模块
- 15.&&与;的区别
- 16.文件类型
- 17.管理 Linux 内核模块
- 18.Ubuntu本机支持中文
- 18.Ubuntu PC机器开新窗口
- 20.Ubuntu翻页
- 21.查主机名
- (四) 网络命令:传输命令、网络管理 (Networking)
- (五) 硬件外设管理:磁盘与存储 (Disk & Storage)
- (六) Shell 环境与脚本 (Shell & Scripting)
- (七) C++构建工具链(Build Toolchain)、构建命令
- (八) 信号与返回值
- 四、vim
- 五、编译工具链
- 五、其他
一、Linux简介
1.配置环境
0.安装unbuntu
1.静态IP地址:手动设置ip地址
instal net-tools
2.设置远程连接
网络协议SSH
sudo apt install ssh
2.安装vimplus
(1)ssh协议
git clone git@github.com:chxuan/vimplus.git
git clone https://github.com/chxuan/vimplus.git ~/.vimplus
(2)执行安装脚本
cd vimplus
./install.sh
(3)安装ycm
sudo apt install vim-youcompleteme
4.关闭主机前,先关闭虚拟机。否则会虚拟机损坏。
5.设置快照
6.daemon 守护进程 / 也是虚拟光驱软件
守护进程与非守护进程的区别:
①守护进程没有界面
②守护进程默默启动,7*24h
7.Linux哲学:
①一切皆文件
②没有消息就是最好的消息 (一般显示的消息是报错)
3.Linux历史
Unix → M → Linux
4.Linux模型
1.内核(Kernel):
①管理硬件资源:CPU(进程调度)、内存(内存管理)、外部设备(文件管理、网络通信、设备驱动)
②对上层应用程序提供接口(API),即系统调用
2.系统调用(System calls):内核给上层应用程序提供的接口
3.库函数(library function):对系统调用的包装,①方便使用 ②可移植性(不同操作系统的底层系统调用是不同的)
4.shell:命令行解释器
shell 是一个命令行解释器,它读取用户输入,然后执行命令,然后等待用户的下一
次输入
for(;;) {
read(cmd);
execute(cmd);
}
命令:一般来说,就是一些简单的可执行程序。
脚本:命令的集合

二、Linux子系统
(一) 用户子系统
1.man命令:查看帮助手册
3.man手册的数值的含义
①man 1:shell命令
②man 2:系统调用
③man 3:库函数

man 3 rmdir
2.man手册看哪些部分? (一手资料):

3.man手册的快捷键:
(1)翻页
↑、↓、f、b、d、u
↓:往下一行
d(down):往下翻半页
f(forward):往下翻一页
↑:往上一行
u(up):往上翻半页
b(backward):往上翻一页
(2)查找:/内容
查找下一个:n
查找上一个:N
(3)退出:q
4.man手册 (manual)
短选项:命令行
长选项:shell脚本
(二) 文件子系统
1.目录结构
根目录 /
/home:家目录,下面是普通用户
/root:超级用户
/lib:库文件
/bin:binary,可执行程序或脚本文件
/sys:system,系统相关文件
/dev:device,设备文件
/proc:process,进程相关的数据
/var:variable,经常发生变化的文件,比如日志文件
/etc:杂项,存放配置文件和启动脚本
/opt:Optional,表示这是一个用于存放可选软件的地方,存放第三方软件包
①passwd:man 5 passwd
②shadow:man 5 shadow
/etc/passwd:存放账号
/etc/shadow:存放密码
/etc/ssh:存放ssh协议相关的密钥等
/etc/hostname:存放主机名
/etc/hosts:存放主机通讯录
/etc 目录的名字来源于“et cetera”,意思是“等等”。这一目录最初用来存放一些系统的“杂项”配置文件,随着时间的推移,成为了存放所有系统配置文件的标准位置。虽然现在 /etc 中存放的文件种类繁多,但名称“etc”一直保留了下来。


1.通配符、正则表达式、重定向
(1)通配符:匹配文件名字
①*:匹配任意多个字符 (0-n个)
②?:匹配任意一个字符
③集合/类:[cha]匹配集合内任意一个字符,[!cha]匹配集合外任意一个字符
例如:[abc]、[0-9]、[0-9a-zA-z_]、[!0-9a-zA-z_]
④!:非
#要一次性删除3_CppBase以外的所有文件和目录
rm -rf !(3_CppBase)
(2)正则表达式:匹配文件内容
(1)基本单位:
①普通字符
②转义字符
③.:匹配任意一个字符
④集合:[abc]
⑤group:(abc)

(2)基本操作:
①连接:

②重复:前一个基本单位重复的次数


(3)指定基本单位出现的位置
①^:行首,“^abc”
②$:行尾,“xyz$”
③\<:词首
④\>:词尾
[^abc]:匹配除了 “a”、“b”、和 “c” 之外的任何单个字符
.*:任意字符,重复任意次
(3)重定向
1.输入重定向:<
入重定向是将程序的标准输入(通常是键盘)重定向到文件或其他输入源
举例:
输入源从键盘改为文件, cin会从文件中读取数据
./a.out < input.txt
2.输出重定向:
输出重定向是将程序的标准输出(通常是屏幕)重定向到文件。
①>:文件不存在则创建,文件存在则覆盖
②>>:追加写入文件末尾
3.标准错误重定向
错误重定向是将程序的标准错误输出(通常是屏幕)重定向到文件。
①2>:错误重定向,文件不存在则创建,文件存在则覆盖
②2>>:错误重定向,追加写入文件末尾
举例:
报错太多,可以使用错误重定向,然后搜索error
g++ set.cpp 2> error.txt

将标准错误,重定向到 标准输出
2>&1
文件描述符 1 是标准输出 ( stdout)。
文件描述符 2 是标准错误 ( stderr)。
乍一看,2>1这似乎是重定向stderr到 的一个好方法stdout。然而,它实际上会被解释为“重定向stderr到名为 的文件1”。
&表示前后的是文件描述符,而不是文件名。因此,我们使用2>&1。将其视为>&重定向合并运算符。
三、Linux命令行 (shell命令)
(一) 目录命令:文件与目录管理 (File & Directory Ops)
1.创建文件:mkdir
mkdir - p 创建文件 (-p是级联创建)

2.删除目录:rmdir
rmdir -p 删除空目录 (-p是级联删除)
3.打印当前工作目录:pwd
print working directory,打印当前工作目录:显示当前用户在终端中的 绝对路径,即从根目录/开始的完整路径
4.切换当前工作目录:cd
cd 是 change directory
①. 当前目录
②.. 上级目录
③- 上次目录,环境变量 OLDPWD
④/ 根目录
⑤/home 所有用户的家目录
⑥~ 当前用户的主目录:cd ~ 等价于 cd $HOME,普通用户切到/home/用户名,root用户切到/root
5.复制:cp
(1)常用格式
cp src des #复制文件
cp -r src des #递归复制目录
cp src1 src2 .. des #拷贝多个文件到目标目录
(2)常用选项
-r:递归
-n:不覆盖 (des不存在,则创建。若存在,则不复制)
-i :交互询问


6.重命名/移动文件:mv
(1)常用格式
①重命名
mv会默认覆盖同名文件,
mv 文件名1 文件名2
inode不变
虚拟文件系统
②移动文件
mv 文件名 目录名
(2)常用选项
-n:不覆盖
-i:交互式
7.删除文件和目录:rm
rm(remove)命令可以删除文件和目录。
rm -rf dir
删除当前目录下所有文件
rm -rf ./*
①rm -r 递归删除 (-r 是recursively,递归地)
②-i:交互式
③-f:force,强制执行,不给提示。-f 强制,不给消息。有些用户不想看消息,不想交互,就用-f,默默地强制执行。
8.查看文件的目录项:ls
ls -l:查看目录项
(1)常用选项
①-l:长格式,详细信息
②-a:显示所有内容,包括 .和…、隐藏文件(以.开头的文件)
③-h:人类可读的
④-t:按照时间由新到旧排序。(不加,默认是按照文件名字典序排序的)
⑤-r:反过来排序
⑥-i:物理inode编号
ls -larthi
(2)读写权限
①可执行程序:775 rwx rwx r-x (八进制,r w x 分别值为4 2 1 )
②普通文件:664 rw- rw- r–
③7列:九个字符(三组)表示权限、硬链接数、拥有者、拥有组、文件大小、最近修改时间、文件名

ls 目录名 #显示指定目录的内容
ls后发现当前目录下都是白色,如何显示颜色?
1.本次命令临时显示颜色:
ls --color=auto
2.长久保存显示颜色:
vim ~/.bashrc
alias ls='ls --color=auto'
source ~/.bashrc
9.du、df
(1)查看目录或文件的大小 (占用的磁盘空间):du -sh
1.看当前目录的总大小:du -sh
2.看当前目录下的每个文件或子目录的大小:du -sh *
3.按大小排序:du -sh * | sort -rh
du是 disk usage 的缩写。
当使用ls -lih时,目录大小永远只显示4K,而无法递归地显示目录的真实大小,这时候就要使用du命令。
(2)显示磁盘空间使用情况、查看挂载点:df -h
df:disk filesystem,其主要功能是报告文件系统的磁盘空间使用信息
-h:human,人类可读
执行 df -h 命令后,你会看到每个已挂载文件系统的容量、已用空间、可用空间、使用百分比以及挂载点等信息。
虽然 df -h 主要用于查看磁盘空间使用情况,但它确实也能间接显示出系统上所有已挂载的文件系统(包括物理硬盘、分区、网络存储、USB 设备等)。这是因为只有已经挂载的文件系统才会出现在 df 的输出中。如果你想专门检查某个特定文件系统或设备是否已经挂载,除了可以使用 df -h 外,还可以考虑使用 mount 或 findmnt 命令来获取更详细的信息。
10.列出文件目录项结构:tree
1.递归显示目录
tree
2.只显示两层目录
tree -L 2
(二) 文件命令:文本处理与搜索 (Text Processing & Search)
1.创建文件:echo、touch、vim
①echo:输入简短内容,不存在则创建,已存在则覆盖。echo "hello Linus" > a.txt"
②touch:文件存在,修改时间戳;文件不存在,创建空文件
③vim:编辑文件

2.搜索文件内容:grep
1.功能
grep (global regular expression print,全局正则表达式打印) 命令可以用于搜索文件内容
grep负责"查找"(搜索过滤)
sed负责"编辑"(流式修改)
awk负责"分析"(格式化处理)
2.用法:
grep [选项] "搜索的内容" 文件名
grep -nE "要查找的字符串内容" 文件名
grep -rwn 102425070001
在当前目录及其子目录下,递归查找包含完整单词 102425070001 的所有行,并显示这些行的内容和行号。
3.选项:
①-n:显示匹配行的行号
②-E:扩展功能(建议都加)
③-w:只匹配整个单词
④-c:显示匹配了多少行的数量
⑤-i:忽略大小写
⑥-r:递归地在目录下搜索文件内容
⑦-l:只显示包含匹配字符串的文件名
⑧-v:显示不匹配的行

例题:
搜索 Linux 内核源码中,包含调用 exit 函数的所有行。
grep -nE "\<exit\(.*\)" linux-6.9 -r #问题: *会多匹配内容,遇到)不结束
grep -nE "\<exit\([^)]*\)" linux-6.9 -r #问题:[^)]在遇到第一个)就结束。但是 exit() 的()中可能还有()
3.awk:按行号提取内容
要求返回第一行和第三行的neritic
modinfo enrigin | awk 'NR==1 || NR==3'
4.查找文件:find
find:查找文件 (在目录中递归地查找)
1.按文件名进行查找
find 目录 -name "文件名"
举例:在当前目录cppBase下查找figure.cpp文件
find . -name "figure.cpp"
如果存在,将得到路径
./Cpp23/bind/figure.cpp
2.按文件类型进行查找
例:查找当前目录下,名字含有pytest的目录
find . -name "*pytest*" -type d
3.按时间查找
-mtime 1 #1到2天内
-mtime +1 #2天前
-mtime -1 #0到1天内

4.按其他方式进行查找



5.常用方式举例:

5.查找文件:which
which:查找文件 (查找可执行程序,即查找命令)
which 可执行程序名
which 可执行程序名 -a (遍历完PATH)
which是通过PATH环境变量,查找目录路径
6.查看文件内容/拼接文件:cat
4.cat
①看文件内容
cat -n 带行号
②拼接文件: cat text1 text2 > text3
7.查看文件的前几行:head
head -n 5 #只查看前5行
head -n -5 #除了后5行,都显示
8.查看文件的后几行:tail
tail -f /var/log/app.log #实时显示文件追加的内容(如日志文件)
tail -n 5
tail -n +5

9.分页浏览:more、less
1.more:分页浏览
b、f或空格翻页
2.less:分页浏览 (more的升级版)
可以上下滚轮
10.文件的行数、单词统计:wc (word count)
wc 文件名
得到:
行数 单词数 字节数 文件名
①wc -l :统计行数
效果等价于:
cat Makefile | grep -c '^'
11.命令的组合:3种
(1)管道(pipe) |
1.管道:将前一个命令的输出,直接作为后一个命令的输入
例如:cmd1的输出 作为 cmd2的输入
cmd1 | cmd2
2.原理:将cmd1的stdout 重定向 到 管道的写端,将cmd2的stdin 重定向 到 管道的读端

3.示例
history | wc -l #得到1000
du -sh * | sort -rh
(2)多命令 ;
cmd1 ; cmd2
先执行cmd1,再执行cmd2。如:mkdir dir ; cd dir
(3)xargs:将cmd1输出的每一行,作为cmd2的命令行参数
0.介绍
xargs 是一个非常强大的命令行工具,通常用于将输入的数据(如文件名、字符串等)转换为命令行参数,传递给其他命令执行。它常与 find、ls、grep 等命令一起使用,用于批量处理文件或文本数据。
1.格式
cmd1 | xargs cmd2

2.示例
(1)删除当前目录下,除了名为"example.sh"以外的所有文件
①grep + xargs
ls | grep -v "example.sh" | xargs rm -f
②find + exec
find . -not -name 'example.sh' -type f -exec rm -f {} \;

3.原理
(1)将cmd1的stdout 重定向 到 管道的写端,将cmd2的stdin 重定向 到 管道的读端
(2)xargs将stdin里的每一行 作为 命令行参数

12.修改文件权限:chmod (change mode)
1.三个群组
①所有者(Owner)
②用户组(Group)
③其他人(Others)
2.三种权限
①4 读 (r,read)
②2 写 (w,write)
③1 执行 (x,execute)
7 = 4(读) + 2(写) + 1(执行) = rwx
5 = 4(读) + 0(写) + 1(执行) = r-x
3.两种文件类型
①文件:-
②目录:d
4.目录:
r:查看目录项 (ls、tree)
w:添加和删除目录项
x:目录最基本的权限。若没有x权限,则不能r和w。不能cd到该目录。

5.举例:
(1)例子1
drwxrwxrwx
d表示是目录,且 所有者(Owner)、用户组(Group)和 其他人(Others)都有读、写、执行权限
(2)例子2
-rwxr-xr-x
-表示是文件
-rwx r-x r-x
│ │ └── others: 读+执行
│ └── group: 读+执行
└── owner: 读+写+执行
6.命令
①文字设定法: chmod [ugoa][±-][rwx] filename
②数字设定法: chmod mode filename
chmod 755 client //数字设定法
chmod 664 a.txt //数字设定法
chmod a+x hello.py //文字设定法

7.模型
(1)目录文件的模型:
目录项以链表互相连接

13.文件创建掩码:umask
想去掉的权限

14.链接:硬链接和符号链接
(1)硬链接 (hard link):ln 源文件 链接名
1.原理:
(1)共享inode结点
(2)引用计数。每增加一个硬链接,引用计数+1,引用计数为0才会真正删除文件。修改任意一个文件的内容,所有共享引用计数的文件内容都会改变。
2.命令:ln (link)
3.格式也是 - ,普通文件
ln a.txt link_a

(2)软连接 (symbolic link):ln -s 源文件/目录 链接名
1.命令:ln -s
2.可以指向一个不存在的文件,大小为指向的路径名
3.格式是 l
4.类似C语言的指针、Windows的快捷方式。除了rm命令,符号链接可以解引用,修改软连接的内容,原内容也会修改。
ln -s b.txt link_b


15.打包、压缩、解压命令:unzip、tar
tar 是 text archive 的缩写
(1)zip
若是.zip,需要使用unzip 包裹名命令
打包
zip [选项] 压缩包名称.zip 文件或目录
解压
unzip [选项] 压缩包名称.zip
-r:递归压缩目录中的所有文件和子目录
-e:加密压缩包,设置密码
-d:指定解压目录

(2)tar
1.打包、压缩为tar
tar -cvf 压缩包名称.tar 要压缩的目录/
举例:
tar -cf test.tar kernel_interface/
2.解压
tar -xvf 压缩包名.tar
举例:
tar -xf test.tar
(3)tar.gz
1.打包、压缩为tar.gz
tar -czvf 压缩包名称.tar.gz 要压缩的目录/
2.解压命令
tar -xzvf 包裹名.tar.gz
3.选项介绍
①-c:create,创建归档文件,即创建压缩包
②-f:file,指定归档文件的名称。-f 选项必须紧跟文件名,放在所有选项的最后
③-v:verbose,显示详细的处理过程信息
④-x:extract,从归档文件中提取文件,即解压压缩包
⑤-z:gzip,即使用gzip算法对归档文件进行压缩或解压缩,默认文件结尾 .tar.gz。-z选项是专门针对gzip算法的,即tar.gz
⑥-t:查看压缩包内容
⑦-r:追加


16.同时显示命令输出,并保存到文件:tee
tee [OPTION]... [FILE]...
使用场景:
①调试程序:
当你运行一个长时间运行的程序并希望在查看输出的同时将输出保存到文件中以便后续分析时,可以使用 tee。
②监控日志文件:
如果你正在监控一个程序的日志输出,想要查看实时日志输出,并且还想保存日志到文件中进行记录,tee 非常适合。
③自动化脚本:
在自动化脚本中,你可以使用 tee 来同时保存执行过程中的输出日志并显示在屏幕上,便于实时查看和后续记录。
1.将输出同时显示在屏幕上并保存到文件
command | tee output.txt
这个命令将 command 的输出既显示在屏幕上,又保存到 output.txt 文件中。如果 output.txt 文件已存在,tee 会覆盖文件中的内容。
2.将输出追加到文件中
command | tee -a output.txt
使用 -a 选项,输出将被追加到文件 output.txt 的末尾,而不会覆盖原有内容。
举例:
ninja -j 56 | tee -a ../ninja_information_log.txt
3.同时将输出保存到多个文件
command | tee file1.txt file2.txt
这会将命令 command 的输出同时写入到 file1.txt 和 file2.txt 文件中,并显示在屏幕上。
4.忽略中断信号
command | tee -i output.txt
使用 -i 选项后,tee 会忽略中断信号,即使在命令执行时按 Ctrl+C,它也不会终止命令的执行
17.对比两文件的内容是否相同,求文件的md5码值
md5哈希值是根据文件的实际内容(二进制数据)计算的,与文件名(文件系统元数据,不影响文件内容本身)无关
md5sum <filename>
(三) 系统命令:系统管理与监控 (System Admin & Monitoring)
1.修改主机名、IP、源
(1)修改主机IP
1.vim /etc/netplan/00-installer-config.yaml
修改主机IP、DNS服务器IP、网关IP
# This is the network config written by 'subiquity'
network:
bridges:
br0:
addresses:
- 10.42.128.44/24 #这里修改主机IP
dhcp4: false
dhcp6: false
interfaces:
- eno1
nameservers:
addresses:
- 10.254.1.1 #DNS服务器地址IP
parameters:
stp: false
routes:
- metric: 100
to: 0.0.0.0/0
via: 10.42.128.254 #网关IP
ethernets:
eno1:
dhcp4: false
version: 2
应用:netplan apply -f
查看IP:ip a
刷新IP:source /etc/profile.d/ipenv.sh
网络架构示意图:
您的主机 (10.42.128.44)
↓
桥接接口 br0
↓
物理接口 eno1
↓
网关 (10.42.128.254) ← 负责转发到外网
↓
DNS服务器 (10.254.1.1) ← 负责域名解析
(2)修改DNS服务器IP
1./etc/netplan/00-installer-config.yaml
举例,见上文
2./etc/resolv.conf
举例:
# Generated by NetworkManager
#nameserver 10.254.1.1
nameserver 10.1.4.210
(3)修改主机名
1.主机名
vim /etc/hostname
2.主机通讯录里,127.0.0.1改为主机名
vim /etc/hosts
举例:
127.0.0.1 localhost
127.0.1.1 ubuntu
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 sha-peg-blt-16
112.15.7.51 mirrors.aliyun.com
3.修改源
vim /etc/apt/sources.list
举例:
deb https://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
# deb https://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
# deb-src https://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
2.查找特定进程:ps aux | grep
ps aux | grep "进程名"
3.关机与重启
(1)关机命令
1.立即关机:poweroff
poweroff
2.定时关机:shutdown
shutdown -h now # 立刻关机
shutdown -h 5 # 5分钟后关机
shutdown -h 20:30 # 20:30关机
取消定时关机:
shutdown -c
(2)重启命令
reboot
shutdown -r now
4.查系统内存:lshw -short -C memory、dmidecode -t memory | grep “Manufacturer:”
(1)查内存总量和插的情况
sudo lshw -short -C memory
(1)2根32GB内存条,系统总内存64GB

(2)8根32GB内存条,系统总内存256GB

(3)16根64GB内存条,系统总内存1024GB=1TB

(2)查看内存条厂家(制造商)信息
sudo dmidecode -t memory | grep "Manufacturer:"
这台机器,16个槽位,空着14个,有2个插了2根三星内存条

这台机器4个槽位,有2个是海盗船(Corsair),有2个槽位空着

5.设置GRUB: /etc/default/grub:限制Linux内核的内存使用
(1)概念
GRUB:GNU Grand Unified Bootloader,GNU 多引导加载程序。GRUB是BIOS和OS之间的启动向导、引导加载程序
GRUB是指引导程序给Linux内核传递参数,设置Linux内核最多识别到多大的内存

如果像这样没设置GRUB,引导程序就不会给Linux内核传递参数,那么Linux内核就默认使用全部的内存。即用户态的memory为0。那么需要使用host memory的程序就无法运行,比如efvs
例如:

(2)操作
vim /etc/default/grub
update-grub
reboot

6.Linux用户
(1)用户分类
(1)root:根用户,超级用户
(2)sudoers:管理员用户。安装ubuntu时,创建的用户默认为sudoers。sudoers可以使用sudo命令临时提升权限为root
(3)普通用户
家目录~的区别
| 用户类型 | 用户名示例 | 执行cd ~后的位置 |
|---|---|---|
| root用户 | root | /root |
| 普通用户 | edward | /home/edward |
(2)用户命令
1.创建用户 useradd
2.删除用户 userdel
sudo userdel 用户名 -r #加-r,不仅删除用户,还将用户主目录中的文件和用户邮箱一起删除
3.设置密码、修改用户密码 passwd
sudo passwd 用户名
4.切换用户 su
(1)临时切换为root用户
sudo -i
5.退出切换 exit
(1)退出 root 用户
exit
例题:
(填写执行的命令即可)
a. 创建 test1 用户,指定 test1 用户的 login shell 为 /bin/bash, 并给他创建家目录。
b. 将 test1 用户的密码修改为 123456 (或其它任意密码)
c. 切换到 test1 用户
d. 退出切换
e. 将 test1 用户删除,家目录也一起删除
a.sudo useradd test1 -m -s /bin/bash
b.sudo passwd test1123123
c.sudo su test1
d.exit
e.sudo userdel test1 -r
7.时间
(1)查看时间:date
1.查看时间
date
2.按照 年月日、星期、时间的格式来查看
date "+%Y-%m-%d %H:%M:%S %A"
(2)设置时间
1.手动校准(临时调整)
该方式调整后立即生效,但系统重启后可能会丢失。
sudo date -s "2025-05-29 10:20:00"
2.硬件时钟同步系统时间(长期生效)
调整系统时间后同步到硬件时钟,以防重启后时间丢失
sudo hwclock --systohc
8.设置别名:alias
1.查看别名
alias
2.临时设置别名 (有效期为当前终端会话)
alias ll="ls -la"
alias h='history'
3.永久设置别名:写入.bashrc
①打开 .bashrc
cd ~
vim .bashrc
②将别名写入
将你要设置的别名 ,如alias h='history',写入.bashrc。保存并退出。
alias ls='ls --color=auto'
alias ll="ls -la"
③保存退出,重新运行一下.bashrc
source .bashrc
9.查看历史命令:history
查看输入的所有历史命令,包括输入的错误的命令也会被记录
history
查看最近20条历史命令
history 20
10.查看当前服务器有多少用户在登录:who
1.示所有当前登录的用户
who
2.显示当前终端的登录信息
who am i
相关命令:
①w:除了显示当前登录的用户外,还显示他们正在做什么(例如,运行的命令)。
②users:仅列出当前登录的用户名,没有其他详细信息。
③last:显示最近登录的用户列表,包括登录和注销时间。
11.查询系统中的逻辑处理器数量
nproc
12.查看自己的Ubuntu版本
lsb_release -a
这会显示关于您Ubuntu版本的详细信息,包括:
- Distributor ID: 发行版名称(Ubuntu)
- Description: 发行版描述(如:Ubuntu 20.04 LTS)
- Release: 发行版版本号
- Codename: 发行版代号(如:focal)


13.修改时区
1.确保系统正在使用 systemd
ps -p 1 -o comm=
2.时区文件通常存放在 /usr/share/zoneinfo/ 目录下。你可以列出目录内容来查找目标时区。例如,要查找 Asia/Shanghai,可以执行:
ls /usr/share/zoneinfo/Asia
3.更新时区
sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
4.手动设置时间
sudo date --set="2025-03-03 18:14:55"
14.lsmod:列出当前已加载的内核模块
显示当前系统中已加载的所有内核模块:提供每个模块的名称、大小以及被使用的次数等信息
lsmod
lsmod | grep xxx
15.&&与;的区别
mkdir build && cd build
与
mkdir build ; cd build
&&:确保前一个命令成功执行后才执行后一个命令。
;:不管前一个命令是否成功,都会执行后一个命令
16.文件类型
| 缩写 | 英文全称 | 中文 |
|---|---|---|
| d | directory | 目录 |
| f | file | 普通文件 |
| l | symbolic link | 符号链接 |
| c | character device file | 字符设备文件 |
| b | block | 块设备文件 |
| s | socket | 套接字 |
| p | named pipe | 有名管道 |

17.管理 Linux 内核模块
1.rmmod:
用于卸载内核模块。它只能卸载指定的模块,而不会自动处理模块的依赖关系。
2.modprobe:
modprobe 不仅可以加载模块,还可以卸载模块(使用 -r 参数)。
18.Ubuntu本机支持中文
sudo apt install fbterm
fbterm
~/.bash_profile
# Load .bashrc if it exists
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
fbterm -- bash -c '
cd ~/BLT_BurnIn/blt_i30-1.0.8-x86_64-linux-dbg-3ce6d18d58 &&
./scan_write_sn_pn.sh &&
bash
'
18.Ubuntu PC机器开新窗口
alt+F1,alt+F2,alt+F3,可以pc本机开新窗口
这样就可以在断网的情况下(不能远程连接),一边跑BERT_large,一边用efsmi -dmon监控
alt F1 是第一个窗口
alt F2 是第二个窗口
alt F3 是第三个窗口
20.Ubuntu翻页
远程连接 (Xshell、MobaXterm) 或者 fbterm中都i可以
shift + pageup 能向上翻页滚动
shift + pagedown 向下翻页
21.查主机名
cat /sys/class/dmi/id/product_name
(四) 网络命令:传输命令、网络管理 (Networking)
1.远程复制、跨网段传输文件:scp
scp,Secure Copy Protocol,安全拷贝协议
远程路径:用户名@IP:绝对路径
0.有jumpserver之后的scp命令变化:
scp -P 2222 文件名 域账户@root@IP@jump-ssh.riverbegin.com:绝对路径
例如:
scp -P 2222 blt_burnin_dorstar-1.1.5-x86_64-linux-dbg-20251209-2a235a355.tar.gz edward@root@10.42.128.44@jump-ssh.riverbegin.com:/root/BLT_BurnIn
或者cp到自己的mount目录。cp两遍,代替一次scp
①从本地复制文件到远程服务器
1.将file传到edward主机下的某路径:
scp 文件名 用户名@IP:绝对路径
scp ./file edward@192.168.248.136:~/MyCode/cpp58/Linux/Linux04
scp
scp efvs-1.0.8-x86_64-linux-dbg.deb root@10.42.128.20:/root/ 【然后需要输入密码:root123456】
sshpass + scp
sshpass -p root123456 scp efvs-1.0.8-x86_64-linux-dbg.deb root@10.42.128.9:/root 【不需要输密码了,sshpass命令携带着密码一起传输过去】【若没有该命令,则安装一下:sudo apt install sshpass】
2.将dir目录传到edward主机下的某路径:
递归复制目录要加 -r
scp -r 目录名 用户名@IP:绝对路径
scp -r ./dir edward@192.168.248.136:~/MyCode/cpp58/Linux/Linux04
②从远程服务器复制文件到本地
scp username@remote_host:/path/to/remote/file /path/to/local/destination
③复制文件到另一台远程服务器
scp username@remote_host:/path/to/remote/file username@another_remote_host:/path/to/another_remote/destination

非常实用,以后互相传文件不需要通过微信了。
Windows给Ubuntu传文件也不需要通过WinSCP了。不过下面的sz、rz更简单好用。
2.同步命令:只复制新增的文件: rsync
将 source_dir 目录同步到 dest_dir 目录:
rsync -av --ignore-existing source_dir/ dest_dir/
1.本机器:
rsync -av --ignore-existing /root/tool_install_package/ /root/BLT_BurnIn/tool_install_package/
2.跨机器:
rsync -av --ignore-existing /root/tool_install_package/ root@10.255.0.6:/root/BLT_BurnIn/tool_install_package/
3.本机的Windows和Linux互传:sz、rz
sz/rz 适合小文件(几MB~ 几十MB),大文件(GB 级)建议用 scp/rsync/SFTP(更稳定、支持断点续传)
1.安装命令
sudo apt install lrzsz
2.服务器发文件到本地:把文件从Linux发到Windows,sz (Send ZModem)
sz filename
然后选择要下载到的winodws文件目录位置
3.服务器接收从本地上传的问题:从Windows获得文件到Linux,rz (Receive ZModem)
rz
然后选择要上传的windows文件夹目录文件
4.请求和传输数据:curl命令
curl [选项] [URL]
curl(Client URL)是一个非常强大的命令行工具,用于与服务器进行数据传输,支持多种协议,包括 HTTP、HTTPS、FTP 等。它通常用于从服务器获取数据或者将数据发送到服务器。
curl 是一个灵活且功能强大的工具,可以满足开发、测试、网络调试等多种需求。常见场景包括 API 调试、文件下载、网络测试、模拟浏览器行为等。通过组合不同的选项,curl 可以完成几乎所有网络请求相关的任务。
Linux命令学习链接:https://wangchujiang.com/linux-command/c/curl.html
5.SSH命令连接其他主机
用SSH命令连接测试机
ssh user@IP -p port
ssh 用户名@IP地址 -p 端口号
举例:
(1)以root连接192.168.100.26
ssh root@192.168.100.26 -p 22
(2)测试是否能连接到github
ssh -T git@github.com
(3)测试是否能连接到gitlab
ssh -T git@gitlab.riverbegin.com -p 10022
6.查看网络状态:netstat命令
netstat -apno | grep 8080 #查看端口8080的网络状态
netstat -ntlp #仅显示正在监听的 TCP 连接
-a:显示所有连接和监听端口
-p:显示与连接关联的程序和进程 ID。
-n:不进行主机、端口和用户的名称解析,直接数字形式显示 IP 地址和端口号。
-o:显示连接的计时器
-t:仅显示 TCP 连接。
-l:仅显示监听(listening)连接。
7.模拟客户端:nc
nc 127.0.0.1 8888 #作为客户端,连接目标IP和端口号的服务器
(五) 硬件外设管理:磁盘与存储 (Disk & Storage)
1.U盘:Linux下使用U盘,mount与umount
(1)挂载U盘
sudo mount /dev/sdb1 /mnt/usb
注意:
1.插上U盘后,需要重启,才有 /dev/sdb1
2.不一定有 /dev/sdb1 目录,需要用磁盘分区管理工具fdisk查询一下USB的分区
fdisk -l
(2)卸载U盘
sudo umount /mnt/usb
注意:umount的时候,不能有任何会话窗口在 /mnt/usb目录下,否则报错:
umount: /mnt/usb: target is busy.
还是无法umont,则暴力杀死这些进程:
(1)使用 lsof 命令查看哪些进程正在访问该挂载点:
sudo lsof +D /mnt/usb
(2)杀死这些进程!
sudo kill <PID>
2.列出所有 PCI 设备:lspci
lspci
例如:查找华为 / 阿里的板卡
lspci -d 19e5: #华为
lspci -d 1ded: #阿里
查询Vendor ID网址:https://pcisig.com/membership/member-companies?combine=enrigin
3.dmidecode:查硬件信息
DMI:Desktop Management Interface,桌面管理界面
dmidecode:DMI Table Decoder,DMI表解码器
1.主要作用:从主板BIOS/UEFI中读取系统的硬件组件的详细信息
2.数据来源:它不像lspci那样直接从硬件寄存器读取信息,而是从系统固件(BIOS/UEFI)中读取存储的 DMI表
3.dmidecode能查到什么?
主板、内存(RAM)、处理器(CPU)、BIOS、system
查看所有信息 (输出非常长):sudo dmidecode
查看特定类型的信息 (使用 -t 参数)
1.查看主板信息
sudo dmidecode -t baseboard
(1)只看主板制造商:
sudo dmidecode -t baseboard | grep Manufacturer
sudo dmidecode -t baseboard | grep -i 'Manufacturer' | awk -F: '{gsub(/ /,"",$2);print $2}'
2.查看内存详细信息:查内存条槽位插的情况
dmidecode -t memory
3.查看CPU信息
sudo dmidecode -t processor
4.查看系统概览(型号、序列号)
sudo dmidecode -t system
(六) Shell 环境与脚本 (Shell & Scripting)
1.常用命令与快捷键
(1)常用命令
| 命令 | 含义 |
|---|---|
| clear / crtl+L | 清屏 |
| touch | 创建文件 |
| ls -a | 全部显示,包括.开头的隐藏文件 |
| rm | 清除,rm * -rf |
| echo “I love xixi”> b.txt | 写入文件 |
| cat 文件名 (cat main.c) | 查看文件内容 |
| 编译、执行程序 | gcc main.c -o main ./main |
| shutdown命令 | 关机命令 |
| reboot | 重启 |
| man 命令名 | manual手册,解释该命令 (be a man!) |
| env | 查看环境变量 |
| history | 查看历史命令 |
gcc:gnu c compiler
(2)Linux快捷键
| 快捷键 | 功能 |
|---|---|
| Tab | 联想,命令补全 |
| ↑ | 上一条命令 |
| Ctrl + A | 将光标移动到最前面 |
| Ctrl + E | 将光标移动到最后面 |
| Crtl + U | 清除当前行 |
(七) C++构建工具链(Build Toolchain)、构建命令
1.查看camke的版本
cmake --version
2.构建命令:配置、生成构建文件、编译、链接、安装
(1)配置 + 生成构建文件(build.ninja)
核心作用:生成 Ninja 构建规则文件build.ninja
make -S ../validation_tool2 -B . -G Ninja
cmake 构建命令
#1.传统写法: CMake < 3.13 (2018年11月)
cmake ../validation_tool2 -G Ninja
#2.现代写法:Source 和 Build目录显式写出:CMake ≥3.13
cmake -S ../validation_tool2 -B . -G Ninja
(2)编译(Compile) + 链接(Link)
核心作用:生成可执行程序 / 库文件等构建产物
ninja -j 56
(3)安装(Install)
核心作用:将构建产物部署到指定安装目录
ninja install -j 56
基于第二步编译链接生成的最终构建产物(可执行程序、库文件、配置文件等),按照第一步 CMake 配置时定义的安装规则(CMakeLists.txt中install()指令),将产物复制到系统 / 项目指定的目录中(如默认的/usr/local/bin、/usr/local/lib,或 CMake 配置时通过-DCMAKE_INSTALL_PREFIX指定的自定义路径)。
2.cmake+ninja构建命令
答:cmake -S 源码路径 -B build -G Ninja
3.构建工具(Build Tools)
源代码
↓
CMake(元构建系统)读取 CMakeLists.txt
↓
生成 build.ninja(构建描述文件)
↓
Ninja(构建系统)解析 build.ninja
↓
调用 gcc/clang(编译器)实际编译
↓
生成可执行文件/库
(八) 信号与返回值
1.信号
信号是一种进程间通信(IPC)的机制,信号是异步的事件通知机制。
kill -l命令:列出所有信号及其编号
| 信号 | 含义 | 触发条件 |
|---|---|---|
| SIGSEGV | segment volation,段错误信号 | 访问非法的内存,如:①解引用空指针②越界访问数组③非法内存访问(内存已释放或未分配)④栈溢出(递归没有出口) |
| SIGILL | illegal | 执行非法的指令 |
| SIGFPE | float point exception,浮点异常 | 算数异常 (除0) |
| SIGPIPE | broken pipe | 写一个读端关闭的管道 |
| SIGABRT | 自己调用abort() | |
| SIGKILL | 强制终止信号,不可忽略,也不可捕获,立即终止进程 | |
| SIGSTOP | 不能被捕获,暂停进程 | |
| SIGCHLD | 子进程终止 | |
| SIGINT | 中断信号 | 通过 ctrl+c 触发,用来终止前台运行的程序 |
| SIGQUIT | 终止进程,并生成核心转储文件 (core dump) | crtl + \ |
| SIGTSTP | 暂停进程,将进程挂起到后台 | crtl + Z |
| kill -SIGINT 子进程pid | kill命令 | |
| SIGTERM | 请求进程正常终止,允许进程进行清理操作,是常用的终止进程信号 | |
| SIGHUP | 挂起信号,通常在用户终端断开连接时触发,可以用于重启进程 | |
| SIGALRM | 定时信号,常用于触发定时器事件 |
链接:https://blog.csdn.net/Edward1027/article/details/139141074
2.返回值
退出码 = 128 + 信号编号(Signal Number)
139 = 128 + 11,对应的是信号11 (SIGSEGV)
SIGSEGV 英文全称:Segmentation Violation(段错误)
中文含义:程序试图访问不被允许的内存地址(比如无权限、地址不存在、只读区写操作等)。
139 = 程序触发了段错误(内存访问违规)
四、vim
vim编辑器:https://blog.csdn.net/Edward1027/article/details/147295194
五、编译工具链
前面我们写程序的时候用的都是集成开发环境 (IDE: Integrated Development
Environment),集成开发环境可以极大地方便我们程序员编写程序,但是配置起来也
相对麻烦。在 Linux 环境下,我们用的是编译工具链,又叫软件开发工具包(SDK:
Software Development Kit)。Linux 环境下常见的编译工具链有:GCC 和 Clang,我
们使用的是 GCC。
1.编译
gcc、g++分别是 gnu 下的 c 和 c++ 编译器。
$ sudo apt install gcc gdb g++ #安装gcc和gdb
$ gcc -v #查看gcc的版本
(1)下生成可执行程序的整个过程

(2)对应的 gcc 命令如下
gcc -E hello.c -o hello.i #-E 预处理,生成 预处理后的文件
gcc -S hello.c -o hello.s #-S 预处理+编译,生成 汇编代码
gcc -c hello.c -o hello.o #-c 预处理+编译+汇编,生成 目标文件
gcc hello.c -o hello #什么都不加,生成 可执行程序
gcc hello.c -o hello -l库名 #-l 链接库
| 选项 | 含义 |
|---|---|
| -Wall | 生成所有警告信息 (warning all) |
| -g | 调试 |
| -Dmacro | 相当于在文件开头加上了 #define macro |
| -Dmacro=value | 相当于在文件开头加上了 #define macro value |
| Idir | 指定#include头文件的优先查找的目录,找不到再到当前目录、系统的include目录查找 |
| -O0,-O1,-O2,-O3 | -O0不优化(开发环境),-O1和-O2(生产环境),-O3是激进的优化策略(一般不使用),Optimize |
(3)条件编译
1.条件编译的3种预处理指令:

①#if
#if 常量表达式
...
#endif
(2)#if defined(macro)
#if defined(DEBUG)
...
#endif
②#ifdef (是上文的语法糖)
#ifdef DEBUG
...
#endif
③#ifndef
#ifndef 标识符
...
#endif
2.条件编译的作用/适用场景:
(1)编写可移植的代码:
#ifdef WIN32
...Windows的代码块
#elif MAC_OS
...
#elif LINUX
...
#endif

(2)为宏提供默认定义
我们可以检测一个宏是否被定义了,如果没有,则提供一个默认的定义:
#ifndef MAXSIZE
#define MAXSIZE 4096
...
#endif
(3)(避免)防止头文件重复包含
第一次碰到该宏,会定义该宏,并执行代码块。
第二次碰到该宏,因为已经定义过该宏,会跳过代码块。
宏的命名就是为了标识该头文件。
#ifndef __WD_FOO_H //若没有定义过该宏,则定义该宏
#define __WD_FOO_H //下次再碰到,就已经定义了该宏,会直接跳过
...
#endif
#ifndef _HELLO_H_
#define _HELLO_H_
...
#endif

(4)调试程序:临时屏蔽包含注释的代码

2.GDB调试
(1)调试程序 GDB的使用方法
GDB调试:https://blog.csdn.net/Edward1027/article/details/151355187
(2)coredump文件 (核心转储)
1.core文件:
(1)是什么:程序异常终止时的运行状态的快照 (程序及内存)
(2)为什么需要,作用:一定能实现错误复现,因为core文件保存了当时内存崩溃的场景,core文件可以恢复场景。
多线程的错误很难还原,在生产环境下的程序,可能每次运行结果都不同。不一定能复现,而core文件就可以用来复现错误
2.开启生成core文件
(1)查看系统是否允许生成Coredump文件
$ ulimit -a #查看
...
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
...
$ ulimit -c unlimited #将core文件的大小临时设置为不受限制
(2)设置Coredump文件的格式
$ sudo vim /etc/sysctl.conf
kernel.core_pattern = %e_core_%s_%t #%e:executable-name,%s:signal,%t:timestamp
$ sudo sysctl -p #让配置生效
(3)使用Coredump文件调试程序
①查看信号异常终止的数字对应的宏:kill -l (list)
②用GDB查看core文件,复现错误
$ gcc test.c -o test -g # 生成可执行程序test
$ ./test # 运行test
#报错了,并生成了core文件,可使用ls命令查看生产的core文件名
$ gdb test test_core_8_1679196427 # 使用Coredump文件调试程序:gdb 可执行程序名 core文件名
③查看栈:backtrace/bt

④查看栈帧:frame n
⑤查看传递的参数的值:info args
⑥查看局部变量的值:lnfo locals
⑦查看寄存器的 值:info registers
普通GDB也可以查看 info args、info locals,并不一定需要有core文件
3.Makefile
1.Makefile是什么 (what)
Makefile:脚本文件
make工具:解释并执行Makefile

2.Makefile的作用 (why)
(1)自动编译:写好 Makefile 之后,输入一个 make命令就可以构建整个项目了,自动进行编译。
(2)增量编译:Makefile只编译新增的和修改过的.c文件 (-c生成.o文件)
不需要全量编译,全量编译需要若干个小时。
编译很慢,链接很快。核心是.o目标文件

3.书写Makefile (how)
特点:Makefile的语法要求非常严格
main: main.o add.o sub.o mul.o div.o
gcc main.o add.o sub.o mul.o div.o -o main
main.o: main.c algs.h
gcc -c main.c -Wall -g
add.o: add.c algs.h
gcc -c add.c -Wall -g
sub.o: sub.c algs.h
gcc -c sub.c -Wall -g
mul.o: mul.c algs.h
gcc -c mul.c -Wall -g
div.o: div.c algs.h
gcc -c div.c -Wall -g
规则:目标,依赖,命令

4.Makefile的工作原理
Makefile默认只实现(或尝试构建)第一个目标。
#默认目标是 hello
hello: hello.o main.o #两个依赖不存在,先执行下面的指令,以生成依赖
g++ hello.o main.o -o hello #第三个执行
hello.o: hello.cpp
g++ -c hello.cpp -o hello.o #第一个执行
main.o: main.cpp
g++ -c main.cpp -o main.o #第二个执行
.PHONY:clean
clean:
rm -f *.o
rm -f hello a.out
(1)通过有向无环图(DAG)来管理依赖
make [目标],若不指定目标,则自动选择第一个target作为目标。
make 伪目标,才会走.PHONY里的

(2)拓扑排序
①保证了依赖关系
②使用DFS,对DAG进行拓扑排序

5.伪目标 .PHONY
(1)效果:伪目标,每次都能执行的命令,但不生成文件。
(2)提出目的:伪目标是为了避免与文件同名
(3)原理:伪目标没有时间戳,因此每次都会执行。
.PHONY: clean rebuild #一定执行
clean:
rm -f *.o main
rebuild: clean main

6.简易Makefile
make是根据文件的时间戳,判断文件是否已经过时。如果时间戳不变,则make不会执行对应的目标生成命令。
hello: hello.o
g++ hello.o -o hello
rm hello.o
hello.o: hello.cpp
g++ -c hello.cpp
.PHONY:clean
clean:
rm -f *.o
rm -f hello
7.完整的Makefile / makefile
main: main.o add.o sub.o mul.o div.o
gcc main.o add.o sub.o mul.o div.o -o main
main.o: main.c algs.h
gcc -c main.c -Wall -g
add.o: add.c algs.h
gcc -c add.c -Wall -g
sub.o: sub.c algs.h
gcc -c sub.c -Wall -g
mul.o: mul.c algs.h
gcc -c mul.c -Wall -g
div.o: div.c algs.h
gcc -c div.c -Wall -g
.PHONY: clean rebuild
clean:
rm -f main main.o add.o sub.o mul.o div.o
rebuild: clean main
其对应的源码:
// algs.h
#ifndef __WD_ALGS_H
#define __WD_ALGS_H
int add(int, int);
int sub(int, int);
int mul(int, int);
int div(int, int);
#endif
// add.c
#include "algs.h"
int add(int a, int b) {
return a + b;
}
// sub.c
#include "algs.h"
int sub(int a, int b) {
return a - b;
}
// mul.c
#include "algs.h"
int mul(int a, int b) {
return a * b;
}
// div.c
#include "algs.h"
int div(int a, int b) {
return a / b;
}
// main.c
#include "algs.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("add(7,3) = %d\n", add(7,3));
printf("sub(7,3) = %d\n", sub(7,3));
printf("mul(7,3) = %d\n", mul(7,3));
printf("div(7,3) = %d\n", div(7,3));
return 0;
}
使用Makefile编写shell脚本:
make、make clean、make build
test: test.o
gcc test.c -o test #编译链接
./test #执行程序
.PHONY: clean rebuild
clean:
rm test test.o
rebuild: clean test
8.非常通用的Makefile模板:含变量
Srcs := $(wildcard *.c)
Outs := $(patsubst %.c, %, $(Srcs))
CC := gcc
CFLAGS = -Wall -g -pthread
ALL: $(Outs)
%: %.c
$(CC) $< -o $@ $(CFLAGS)
.PHONY: clean rebuild ALL
clean:
$(RM) $(Outs)
rebuild: clean ALL
9.变量
(1)变量在声明时需要赋初始值;使用时,需要给在变量名前加上$符号,如果变量名包含
多个字符,我们应该用小括号 () 或大括号 {} 把变量括起来。
(2)使用变量,改写上文的Makefile
Objs := main.o add.o sub.o mul.o div.o
Out := main
$(Out): $(Objs)
gcc $(Objs) -o $(Out)
main.o: main.c algs.h
gcc -c main.c -Wall -g
add.o: add.c algs.h
gcc -c add.c -Wall -g
sub.o: sub.c algs.h
gcc -c sub.c -Wall -g
mul.o: mul.c algs.h
gcc -c mul.c -Wall -g
div.o: div.c algs.h
gcc -c div.c -Wall -g
.PHONY: clean rebuild
clean:
rm -f $(Out) $(Objs)
rebuild: clean $(Out)
(3)预定义变量

使用预定义变量,改写上文的Makefile
Objs := main.o add.o sub.o mul.o div.o
Out := main
CC := gcc
CFLAGS := -Wall -g
$(Out): $(Objs)
$(CC) $(Objs) -o $(Out)
main.o: main.c algs.h
$(CC) -c main.c $(CFLAGS)
add.o: add.c algs.h
$(CC) -c add.c $(CFLAGS)
sub.o: sub.c algs.h
$(CC) -c sub.c $(CFLAGS)
mul.o: mul.c algs.h
$(CC) -c mul.c $(CFLAGS)
div.o: div.c algs.h
$(CC) -c div.c $(CFLAGS)
.PHONY: clean rebuild
clean:
$(RM) $(Out) $(Objs)
rebuild: clean $(Out)
(4)规则中的特殊变量

引入自动变量后,我们可以将上面的 Makefile 改写成:
Objs := main.o add.o sub.o mul.o div.o
Out := main
CC := gcc
CFLAGS := -Wall -g
$(Out): $(Objs)
$(CC) $^ -o $@
main.o: main.c algs.h
$(CC) -c $< $(CFLAGS)
add.o: add.c algs.h
$(CC) -c $< $(CFLAGS)
sub.o: sub.c algs.h
$(CC) -c $< $(CFLAGS)
mul.o: mul.c algs.h
$(CC) -c $< $(CFLAGS)
div.o: div.c algs.h
$(CC) -c $< $(CFLAGS)
.PHONY: clean rebuild
clean:
$(RM) $(Out) $(Objs)
rebuild: clean $(Out)
10.模式规则
模式规则"%.o : %.c",表示的含义是:所有的.o文件依赖于对应的.c文件。
下面示例就是 Makefile 的一个模式规则,由所有的.c文件生成对应的.o文件:
%.o: %.c
$(CC) -c $< -o $@
有了模式规则后,我们可以这样写 Makefile:
Objs := main.o add.o sub.o mul.o div.o
Out := main
CC := gcc
CFLAGS := -Wall -g
$(Out): $(Objs) #Objs := main.o add.o sub.o mul.o
div.o
$(CC) $^ -o $@
%.o: %.c algs.h #这里应用了Makefile的隐式推导,%.o是与上一个规则的依赖进行匹配,即$(Objs)
$(CC) -c $< $(CFLAGS)
.PHONY: clean rebuild
clean:
$(RM) $(Out) $(Objs)
rebuild: clean $(Out)
11.内置函数
(1)通配符函数

(2)模式替换函数


4.库文件
库文件是目标文件(*.o)的集合
| 静态库 | 动态库 | |
|---|---|---|
| Windows | .lib | .dll |
| Linux | .a | .so |
(1)静态库
静态库:链接阶段,将库代码嵌入可执行程序,合为一体
优点:移植方便,程序运行时与静态库再无瓜葛。当链接好静态库后,即使静态库坏了、没了,依然不影响已生成的程序的执行。
缺点:①浪费空间,每个进程都有一份静态库的副本 ②对程序更新,部署,发布不友好,当静态库更新时,所有用户都需要重新下载安装的可执行程序。
(2)动态库
动态库:对函数的链接,是在运行时完成的
优点:①节省内存空间,动态库可以被多个进程共享 ,动态库(dynamic library)又称为共享库(shared library) ②对程序的更新,部署,发布友好,只需要更新动态库就好了
缺点:程序运行时,依赖动态库,移植不方便
(3)库的生成
1.生成静态库
ar crsv lib库名.a add.o sub.o mul.o div.o #静态库打包,用archive
sudo mv lib库名.a /usr/lib
gcc main.c -o main -l库名 #需要加-l选项,链接库
2.生成动态库
gcc -c *.c -fpic #生成动态库的目标文件,要加-fpic
gcc -shared *.o -o libalgs.so #打包生成共享库,用gcc
sudo mv libalgs.so /usr/lib #移动到系统的库目录下
gcc main.c -o main -l库名 #同名的静态库和动态库都存在时,默认加载动态库
3.修改版本
libalgs.so当作一个符号链接,其他的带版本号是真的动态库
sudo ln -s libalgs.so.001 libalgs.so #这样libalgs.so就仅仅只是一个符号链接
五、其他
1.修改代码模板:snippet.c
vim ~/.vim/plugged/prepare-code/snippet/snippet.c
#ifndef __SNIPPET_H__
#define __SNIPPET_H__
class snippet
{
public:
snippet();
~snippet();
private:
};
#endif
2.自定义头文件
/usr/include
3.小知识储备
1.字段与字段之间,以冒号:分隔
2.Windows回收站
其实是一个文件夹,Windows的删除其实是mv操作。Linux没有回收站。
3.脚本
Python脚本


1377

被折叠的 条评论
为什么被折叠?



