基础开发工具

什么是软件包管理器?

  • 在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。因为这样都要编译一次,编译也需要时间。

相关推荐
用户9718356334665 分钟前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪1 小时前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠17 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush418 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行52018 小时前
Linux 11 动态监控指令top
linux
不会C语言的男孩19 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
古城小栈19 小时前
Unix 与 Linux 异同小叙
linux·服务器·unix
凡人叶枫21 小时前
Effective C++ 条款42:了解 typename 的双重意义
java·linux·服务器·c++
2601_9618752421 小时前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant
java_cj21 小时前
深入kube-apiserver认证机制:从Bearer Token到mTLS的完整认证链解析
linux·运维·服务器·云原生·容器·kubernetes