基础开发工具

什么是软件包管理器?

  • 在linux 下安装软件,一个通用的办法就是下载源代码。然后编译,形成可执行程序,但是这样太麻烦了
  • 所以就有软件包管理器出现。别人吧软件写好打包放在服务器上,我们要安装,通过软件包管理器从服务器上下载到本地。
  • 软件就是app,软件包管理器就像应用商店。
  • linux下软件包管理器yum/apt就像一个客户端,从服务器上下载软件。
  • yum(Yellow dog Updater, Modified)是Linux下⾮常常⽤的⼀种包管理器. 主要应⽤在Fedora, RedHat, Centos等发⾏版上.
  • Ubuntu:主要使⽤apt(Advanced Package Tool)作为其包管理器。apt同样提供了⾃动解决依 赖关系、下载和安装软件包的功能。

linux软件的生态

一个操作系统为什么要有完整的生态

怎么样评估一个操作系统好?

首先,光有一个强大的操作系统不够,还必须要完整的生态,因为这样才会有更多人使用。一个操作系统是否完整,要看它的生态是否完善。

操作系统生态必须有社区论坛,强大的官网文档,丰富的软件体系。维护更新速度快。对客户要有针对性。

当一个开源的操作系统,别人为了使用它,不让他黄,肯定会有程序员去写丰富的软件,还有unbantu,等系统。这样社区论坛也热闹,官网文档也强。

所以我们下载软件,就可以通过软件包管理器,yum/apt,去查找软件,下载,再直接安装。yum/apt是怎么直接在几亿台服务器找到软件的了,因为软件服务器的路径会写在软件包管理器下文件里面。

但是有防火墙不能直接访问外网,或者下载速度慢。所以,有很多公司搞了镜像软件包服务器。

他们把软件下载国内的服务器。yum/apt文件下的路径也会被修改成国内的服务器。

.conf是文件的后缀,存放配置文件的。

软件依赖是什么?

就是我们下载安装一个软件,还会依赖其他软件来运行。比如vs2022,来需要在vs环境下安装c++等的编译环境。但是yum/apt在服务器下载,安装软件,解决这个问题。

yum/apt的具体操作

yum/apt是软件包管理器。它的作用是在服务器下载软件并安装。

他们怎么获取软件的服务器的。在配置文件下存放许多软件的镜像地址。叫做软件源。

软件源又分为稳定软件源和扩展软件源。

稳定软件源是放软件测试稳定,可靠的软件放在服务器上,存放的是服务器的地址。

扩展软件源是还没有成熟,或者稳定的软件。当软件完善之后也会放在稳定软件的服务器上。

像linux系统配置的软件源的服务器地址一般都是指向国外的。所以我们要更新配置软件源,将一个新的文件替换原来的软件源。

首先我们先备份原来的标准源

复制代码
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup//把.repo备份一份,原文件也在

再拷贝一个新的一份文件做备份。

wget:获取网址。

cpp 复制代码
# 使用 wget 下载阿里云的 CentOS-7.repo 文件,
# 并用 -O 把它直接保存并覆盖到 /etc/yum.repos.d/CentOS-Base.repo
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

但是清除旧缓存,不然yum,找不到国内服务器地址,还有旧的缓存。

cpp 复制代码
yum clean all

最后更新缓存

cpp 复制代码
yum makecache

上面就是更新软件源的方法。就是用新文件替换了旧的文件存放软件包服务器的地址。

apt的查看软件包的指令

cpp 复制代码
root@iZwz9c6v6ajdocnv9xkh8rZ:~# apt search lrzsz
Sorting... Done
Full Text Search... Done
cutecom/jammy 0.30.3-1build1 amd64
  Graphical serial terminal, like minicom

lrzsz/jammy,now 0.12.21-10 amd64 [installed]
  Tools for zmodem/xmodem/ymodem file transfer

更详细的看软件包(show)

cpp 复制代码
root@iZwz9c6v6ajdocnv9xkh8rZ:~# apt show lrzsz
Package: lrzsz
Version: 0.12.21-10
Priority: optional
Section: universe/comm
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Martin A. Godisch <godisch@debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 531 kB
Depends: libc6 (>= 2.15)
Suggests: minicom
Homepage: https://ohse.de/uwe/software/lrzsz.html
Download-Size: 74.8 kB
APT-Manual-Installed: yes
APT-Sources: http://mirrors.cloud.aliyuncs.com/ubuntu jammy/universe amd64 Packages
Description: Tools for zmodem/xmodem/ymodem file transfer
 Lrzsz is a cosmetically modified zmodem/ymodem/xmodem package built
 from the public-domain version of Chuck Forsberg's rzsz package.
 .
 These programs use error correcting protocols ({z,x,y}modem) to send
 (sz, sx, sb) and receive (rz, rx, rb) files over a dial-in serial port
 from a variety of programs running under various operating systems.

yum查看软件包的指令

cpp 复制代码
yum list | grep lrzsz
lrzsz.x86_64 0.12.20-36.el7 @base 

也可以search

cpp 复制代码
yum search lrzsz

yum和apt安装软件的指令

cpp 复制代码
sudo yum install 软件
sudo apt install 软件
cpp 复制代码
sudo yum install -y 软件
sudo apt install -y 软件


yum/apt 会⾃动找到都有哪些软件包需要下载, 这时候敲 "y" 确认安装.

出现 "complete" 字样或者中间未出现报错, 说明安装完成.
注意事项:

安装软件时由于需要向系统⽬录中写⼊内容, ⼀般需要 sudo 或者切到 root 账⼾下才能完成.

yum/apt安装软件只能⼀个装完了再装另⼀个. 正在yum/apt安装⼀个软件的过程中, 如果再尝试⽤
yum/apt安装另外⼀个软件, yum/apt会报错.

如果 yum / apt报错, 请⾃⾏百度

卸载软件

cpp 复制代码
sudo  yum remove -y 软件
sudo apt remove -y 软件 

y跟上面一样

vim编辑器

三种模式

1.命令模式

输入许多命令,可以编写文件。进入默认是命令模式。

【yy】复制这一行.

p粘贴,前面可以加数字多少行复制。

【gg】回到文本开头。

【G】回到文本末尾

\^回到行开头

【$】回到行尾

【h】向左 【j】向下 【k】向上 【l】向右

dd删除行

x删除单个字符 【u】撤销

【crtl+r】对撤销取消

【行号+shift+g】跑到对应的行上

【w】单词为单位,向前查找

【b】单词为单位,向后查找。

批量化注释,批量化去注释crtl+v进入视图。然后j下移选择多少行。再shift+i进入插入模式。再在开头输入//最后esc退出,就批量注释了。删除注释就是crtl+v,选择要取消注释的,然后按d就可以了。

shift+~大小写转换

r替换光标那的字符。

shift+r光标后面的都可以替换。

u撤销

ctrl+r:对撤销动作取消。

shift+zz:保存并退出。

底行模式

set nu:对每行都写上行号。

w:保存,wq:保存并退出。q!:强制退出。wq!保存强制退出

cpp 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc t.c
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l
total 24
-rwxrwxr-x 1 jcm jcm 15960 Mar 11 19:54 a.out
drwxrwxr-x 2 jcm jcm  4096 Mar  8 21:07 dir
-rw-rw-r-- 1 jcm jcm   283 Mar 11 19:54 t.c
-rw-rw-r-- 1 jcm jcm     0 Mar  8 20:53 tess.c
-rw-rw-r-- 1 jcm jcm     0 Mar 10 20:34 test.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt10.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt1.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt2.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt3.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt4.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt5.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt6.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt7.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt8.c
-rw------- 1 jcm jcm     0 Mar  8 20:59 txt9.c

编译之后,生成了a.out文件。在执行文件的时候,就算文件在当前路径下。我们也并不能只给文件名,linux找不到。

cpp 复制代码
a.out//找不到
./a.out//应该这样给。
或者给绝对路径,从根目录开始
bash 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ./a.out
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world

一般都要退出文件编译,再运行gcc t.c 然后执行./a.out文件,这样太慢了。

我们可以在底行模式加个!加gcc t.c 然后!./a.out就可以同样执行代码,还不会退出。

当我们需要几个文件的时候.h .c我们编译完.c,再退出编译.h。太慢了。我们底行输入vs 文件就可以进行分屏操作

不仅可以分两屏,还可以分三屏更多。

底行模式还有常用的就是/,在文本查找内容进行高亮。

%s/被替换/新文件/g,可以替换文本中的内容。

补充的指令

vim配置

为了使vim更好用,我们可以在.vimrc文件里面配置一些命令,然后当我们vim的时候,就会打开.vimrc,生效我们的配置命令。推荐每个用户配置在自己的家目录下,不配置在root下

gcc/g++编译器

gcc:编译c语言的

g++:编译c++的

编译器:就是把源文件编译成可执行的二进制文件。

1 预处理

gcc -E code.c -o code.i。进行预处理。

预处理又分为:头文件展开。宏替换。去掉注释。条件编译。(头文件展开就是把头文件里面的内容拷贝到源文件。去掉注释,就是把注释的内容去掉。)使语言变成干净的语言。

复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -E jcm.c -o jcm.i
条件编译

为什么要条件编译?

条件编译的主要用途

  1. 根据不同平台或环境编译代码:可以针对不同的操作系统或硬件架构编写特定的代码。
  2. 调试和发布版本的区分:在调试版本中可以包含调试信息,而在发布版本中则可以排除这些信息。
  3. 多版本控制:根据不同的需求或功能选择性地编译某些模块或功能。

多版本控制,就是有些商业化软件会有基础版和专业版。基础版和专业版的公共代码一样。

利用条件编译就可以只实现一套代码。条件编译控制输出哪部分的代码。这样代码维护起来方便

2 翻译

将c语言翻译成汇编语言

bash 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -S jcm.i -o jcm.s
3 汇编

将汇编-》obj目标文件(可重定位的二进制文件)

bash 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -c jcm.s -o jcm.o
4链接

将目标文件与c语言的标准库里面的内容链接

bash 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc jcm.o -o jcm.exe
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ./jcm.exe
hellojcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l
解释的命令

-o就是把文件变成其他名称。-E就是预处理 -S就是翻译 -c就是汇编

最后建议
bash 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ touch hello{1..20}.c
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -c hello{1..20}.c
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l
total 164
-rw-rw-r-- 1 jcm jcm 17956 Mar 13 17:04 code.i
-rw-rw-r-- 1 jcm jcm  1560 Mar 13 17:05 code.o
-rw-rw-r-- 1 jcm jcm   738 Mar 13 17:04 code.s
drwxrwxr-x 2 jcm jcm  4096 Mar  8 21:07 dir
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello10.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello10.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello11.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello11.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello12.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello12.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello13.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello13.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello14.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello14.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello15.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello15.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello16.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello16.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello17.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello17.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello18.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello18.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello19.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello19.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello1.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello1.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello20.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello20.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello2.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello2.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello3.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello3.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello4.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello4.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello5.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello5.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello6.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello6.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello7.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello7.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello8.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello8.o
-rw-rw-r-- 1 jcm jcm     0 Mar 13 17:33 hello9.c
-rw-rw-r-- 1 jcm jcm   936 Mar 13 17:33 hello9.o

gcc -c会把.c文件形成同名的.o文件。最后我们再把.o文件链接。这样提高了编译效率

链接为什么要有库?库是什么?

在链接的时候为什么要用库?因为这样提高了效率,不然每个程序员要用的时候都要自己去实现,浪费。

库是什么?库是别人写好的代码集合。

库在哪里了?linux下centos和unbantu的路径不同。


编译出来的文件,默认是动态库。我们可以把它修改成静态库

bash 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc yu.c -o yu -statically
bash 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ file yu
yu: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=758cbf26757fe7b843d260ddb19e9cb26157182a, for GNU/Linux 3.2.0, not stripped

这样就是一个静态链接了。

动态库和静态库的优缺点

自动化构建-make/makefile

  • 会不会写makefile,从⼀个侧⾯说明了⼀个⼈是否具备完成⼤型⼯程的能⼒
  • ⼀个⼯程中的源⽂件不计数,其按类型、功能、模块分别放在若⼲个⽬录中,makefile定义了⼀ 系列的规则来指定,哪些⽂件需要先编译,哪些⽂件需要后编译,哪些⽂件需要重新编译,甚⾄ 于进⾏更复杂的功能操作makefile带来的好处就是⸺"⾃动化编译",⼀旦写好,只需要⼀个make命令,整个⼯程完全 ⾃动编译,极⼤的提⾼了软件开发的效率。
  • make是⼀个命令⼯具,是⼀个解释makefile中指令的命令⼯具,⼀般来说,⼤多数的IDE都有这 个命令,⽐如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可⻅,makefile 都成为了⼀种在⼯程⽅⾯的编译⽅法
cpp 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
gcc -E code.c -o code.i
gcc -S code.i -o code.s
gcc -c code.s -o code.o
gcc code.o -o code
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l
total 1000
-rwxrwxr-x 1 jcm jcm  15960 Mar 15 21:05 code
-rw-rw-r-- 1 jcm jcm     68 Mar 15 21:05 code.c
-rw-rw-r-- 1 jcm jcm  17950 Mar 15 21:05 code.i
-rw-rw-r-- 1 jcm jcm   1496 Mar 15 21:05 code.o
-rw-rw-r-- 1 jcm jcm    659 Mar 15 21:05 code.s
drwxrwxr-x 2 jcm jcm   4096 Mar  8 21:07 dir
-rw-rw-r-- 1 jcm jcm     56 Mar 13 17:07 jcm.c
-rwxrwxr-x 1 jcm jcm  15960 Mar 13 17:09 jcm.exe
-rw-rw-r-- 1 jcm jcm  17934 Mar 13 17:08 jcm.i
-rw-rw-r-- 1 jcm jcm   1496 Mar 13 17:09 jcm.o
-rw-rw-r-- 1 jcm jcm    675 Mar 13 17:08 jcm.s
-rw-rw-r-- 1 jcm jcm    203 Mar 15 21:03 makefile
-rw-rw-r-- 1 jcm jcm     60 Mar 13 21:16 test.c
-rw-rw-r-- 1 jcm jcm   1504 Mar 13 21:16 test.o
-rw-rw-r-- 1 jcm jcm    102 Mar 11 21:04 t.h
-rwxrwxr-x 1 jcm jcm 900344 Mar 14 19:09 yu
-rw-rw-r-- 1 jcm jcm    165 Mar 14 17:52 yu.c
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ vim makefile
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make clean
rm -f code code.o code.s code.i
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l
total 956
-rw-rw-r-- 1 jcm jcm     68 Mar 15 21:05 code.c
drwxrwxr-x 2 jcm jcm   4096 Mar  8 21:07 dir
-rw-rw-r-- 1 jcm jcm     56 Mar 13 17:07 jcm.c
-rwxrwxr-x 1 jcm jcm  15960 Mar 13 17:09 jcm.exe
-rw-rw-r-- 1 jcm jcm  17934 Mar 13 17:08 jcm.i
-rw-rw-r-- 1 jcm jcm   1496 Mar 13 17:09 jcm.o
-rw-rw-r-- 1 jcm jcm    675 Mar 13 17:08 jcm.s
-rw-rw-r-- 1 jcm jcm    203 Mar 15 21:03 makefile
-rw-rw-r-- 1 jcm jcm     60 Mar 13 21:16 test.c
-rw-rw-r-- 1 jcm jcm   1504 Mar 13 21:16 test.o
-rw-rw-r-- 1 jcm jcm    102 Mar 11 21:04 t.h
-rwxrwxr-x 1 jcm jcm 900344 Mar 14 19:09 yu
-rw-rw-r-- 1 jcm jcm    165 Mar 14 17:52 yu.c

make自动执行,make clean执行下面删除方法。

看了上面的代码,肯定不知道.PHONY是干什么的,它是伪目标,修饰的目标文件和依赖方法总是被执行。什么是总是被执行,那我们先谈谈什么是不总是被执行。

复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
gcc -E code.c -o code.i
gcc -S code.i -o code.s
gcc -c code.s -o code.o
gcc code.o -o code
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l
total 1000
-rwxrwxr-x 1 jcm jcm  15960 Mar 15 23:55 code
-rw-rw-r-- 1 jcm jcm     68 Mar 15 21:05 code.c
-rw-rw-r-- 1 jcm jcm  17950 Mar 15 23:55 code.i
-rw-rw-r-- 1 jcm jcm   1496 Mar 15 23:55 code.o
-rw-rw-r-- 1 jcm jcm    659 Mar 15 23:55 code.s
drwxrwxr-x 2 jcm jcm   4096 Mar  8 21:07 dir
-rw-rw-r-- 1 jcm jcm     56 Mar 13 17:07 jcm.c
-rwxrwxr-x 1 jcm jcm  15960 Mar 13 17:09 jcm.exe
-rw-rw-r-- 1 jcm jcm  17934 Mar 13 17:08 jcm.i
-rw-rw-r-- 1 jcm jcm   1496 Mar 13 17:09 jcm.o
-rw-rw-r-- 1 jcm jcm    675 Mar 13 17:08 jcm.s
-rw-rw-r-- 1 jcm jcm    203 Mar 15 21:03 makefile
-rw-rw-r-- 1 jcm jcm     60 Mar 13 21:16 test.c
-rw-rw-r-- 1 jcm jcm   1504 Mar 13 21:16 test.o
-rw-rw-r-- 1 jcm jcm    102 Mar 11 21:04 t.h
-rwxrwxr-x 1 jcm jcm 900344 Mar 14 19:09 yu
-rw-rw-r-- 1 jcm jcm    165 Mar 14 17:52 yu.c
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
make: 'code' is up to date.
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
make: 'code' is up to date.
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
make: 'code' is up to date.

先编译了code.c,然后继续make编译code.c,他不会执行,它提示code是新的。那他怎么知道code是最新的

它是通过看modify时间来看的,如果源文件的时间比可执行程序旧,就不会继续执行编译,因为编译也需要时间。

复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ stat code.c
  File: code.c
  Size: 68        	Blocks: 8          IO Block: 4096   regular file
Device: fc03h/64515d	Inode: 398067      Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1001/     jcm)   Gid: ( 1001/     jcm)
Access: 2026-03-15 21:05:22.544538587 +0800
Modify: 2026-03-15 21:05:18.828394051 +0800
Change: 2026-03-15 21:05:18.828394051 +0800
 Birth: 2026-03-15 21:05:18.828394051 +0800
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ stat code
  File: code
  Size: 15960     	Blocks: 32         IO Block: 4096   regular file
Device: fc03h/64515d	Inode: 398059      Links: 1
Access: (0775/-rwxrwxr-x)  Uid: ( 1001/     jcm)   Gid: ( 1001/     jcm)
Access: 2026-03-15 23:55:05.384575948 +0800
Modify: 2026-03-15 23:55:05.384575948 +0800
Change: 2026-03-15 23:55:05.384575948 +0800
 Birth: 2026-03-15 23:55:05.364575170 +0800

modify时间的改变是通过修改文件的内容。

access是通过访问文件。

change是修改文件的属性。

但是access虽然cat也是访问,但是修改access是有规律的,不可能你访问一次就修改时间,修改时间,要缓存在磁盘上,io操作。修改文件内容access会改变。如果每次读取(例如用 cat 查看)都立即将更新后的 atime 写回磁盘,会导致大量的磁盘 I/O,极大地降低系统性能。因为 atime 的修改和文件内容修改不同,它非常频繁且通常不那么关键。

当我们工程目标文件也用PHONY修饰,总是可以执行。

cpp 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
gcc -E code.c -o code.i
gcc -S code.i -o code.s
gcc -c code.s -o code.o
gcc code.o -o code
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
gcc code.o -o code
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
gcc code.o -o code
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make
gcc code.o -o code

那么code就会一直被链接,如果写出gcc code.c -o code。那么会一直编译,编译时间长,效率降低。

.PHONY:让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐

小结:最佳实践:clean可以被PHONY修饰,但是形成工程可执行文件不能被修饰。

gcc是通过比较源文件和可执行目标文件modify来对比,通过这个来查看是否执行,提升编译效率。

更适用的makefile

假如我们有许多文件.c都要编译成可执行程序,如果按上面一个一个编译太麻烦了。

我们使用变量替换,我们就可以编译很多文件,

cpp 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ make
 code10.c -> code10.o
 code1.c -> code1.o
 code2.c -> code2.o
 code3.c -> code3.o
 code4.c -> code4.o
 code5.c -> code5.o
 code6.c -> code6.o
 code7.c -> code7.o
 code8.c -> code8.o
 code9.c -> code9.o
 code.c -> code.o
 code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o code.o-> code

上面中的是变量引用,在定义变量的时候,后面不是字符串,都要加,比如makefile的函数或者变量。\^代表所有的依赖文件,@代表目标文件。$<代表每一个依赖文件。所以在编译形成.o的时候是每一个文件编译一个.o。

cpp 复制代码
BIN=proc.exe # 定义变量
CC=gcc
#SRC=$(shell ls *.c) # 采⽤shell命令⾏⽅式,获取当前所有.c⽂件名
SRC=$(wildcard *.c) # 或者使⽤ wildcard 函数,获取当前所有.c⽂件名
OBJ=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表
LFLAGS=-o # 链接选项
FLAGS=-c # 编译选项
RM=rm -f # 引⼊命令
$(BIN):$(OBJ)
@$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名。 $^: 代表依赖⽂件列表
@echo "linking ... $^ to $@"
%.o:%.c # %.c 展开当前⽬录下所有的.c。 %.o: 同时展开同
名.o
@$(CC) $(FLAGS) $< # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。
@echo "compling ... $< to $@" # @:不回显命令
.PHONY:clean
clean:
$(RM) $(OBJ) $(BIN) # $(RM): 替换,⽤变量内容替换它
.PHONY:test
test:
@echo $(SRC)
@echo $(OBJ)


我们在修改其中一个文件了

cpp 复制代码
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ make
 code10.c -> code10.o
 code1.c -> code1.o
 code2.c -> code2.o
 code3.c -> code3.o
 code4.c -> code4.o
 code5.c -> code5.o
 code6.c -> code6.o
 code7.c -> code7.o
 code8.c -> code8.o
 code9.c -> code9.o
 code.c -> code.o
 code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o code.o-> code
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ vim code.c
jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ make
 code.c -> code.o
 code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o code.o-> code

当我们再次编译的时候。只有code.c编译成code.o。因为其他的code1..2.c都已经编译过一次了。

这就是为什么在设计自动化工程的时候要先编译在链接,而不是直接ggc code.c -o code。因为这样都要编译一次,编译也需要时间。

相关推荐
无人生还别怕1 小时前
如何制作一个linux标准iso镜像
linux·iso·opencloudos·openanolisos
Yana.nice9 小时前
Linux 只保留 30 天内日志(find命令删除日志文件)
linux·运维·chrome
DFT计算杂谈12 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
Zhang~Ling13 小时前
从 fopen 到 struct file:从零开始拆解 Linux 文件 I/O
linux·运维·服务器
DeeplyMind13 小时前
Linux 深入 per-VMA lock:Linux 缺页路径如何摆脱 mmap_lock
linux·per-vma lock
爱写代码的森14 小时前
蒙三方库 | harmony-utils之FileUtil文件重命名与属性查询详解
linux·运维·服务器·华为·harmonyos·鸿蒙·huawei
XMAIPC_Robot15 小时前
软硬协同实时控制|RK3588业务调度+FPGA硬件时序,ethercat实现半导体设备微秒级响应(125us)
linux·arm开发·人工智能·fpga开发
重生的黑客15 小时前
Linux 进程优先级、切换与调度:从孤儿进程到 O(1) 调度模型
linux·运维·服务器·进程优先级·nice
骑上单车去旅行16 小时前
MD5校验对比脚本
linux·服务器·windows
平生幻17 小时前
Linux 常用命令
linux