Linux系统编程 day03 Makefile、gdb、文件IO

news2024/9/22 5:33:35

Linux系统编程 day03 Makefile、gdb、文件IO

  • 1. Makefile
  • 2. gdb
  • 3. 文件IO

1. Makefile

Makefile文件中定义了一系列规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至更加复杂的功能操作。Makefile就像一个shell脚本一样,也可以执行操作系统的命令,Makefile带来的好处就是可以实现自动化编译,一旦写好只需要一个make命令就可以让整个工程完全自动编译,极大地提升了软件开发的效率。

make是一个命令工具,是专门解释Makefile文件中的指令的命令工具。大多数IDE中都有这个命令。Makefile文件中会使用gcc编译器对源代码进行编译,最重生成可执行文件或者是库文件。Makefile文件的命名为Makefile或者makefile。

Makefile文件由一些列规则组成,规则如下:

目标: 依赖
(tab)命令

这里必须是tab键,输入空格无效。Makefile的三要素分别是目标、规则以及命令。目标为要生成的目标文件,依赖为目标文件由哪些文件生成,命令是由依赖文件生成目标文件的一系列命令。

如在当前目录下有main.c、add.c、sub.c、mul.c、dive.c、head.h这几个文件,head.h文件中存放的是add.c、sub.c、mul.c、dive.c中函数实现的声明,main.c中调用其它C语言文件中的函数。由基本的规则编写一个Makefile文件生成可执行文件main,于是有第一个版本。

main: main.c add.c sub.c mul.c dive.c
	gcc -o main add.c sub.c mul.c dive.c -I./

这个版本的Makefile文件效率低,修改一个文件,所有的文件都会全部重新编译。想要写好一个效率更高的Makefile文件,就需要知道Makefile的工作原理。

Makefile想要生成目标,需要检查规则中所有的依赖文件是否都存在。若有的依赖文件不存在,则向下搜索规则,看看是否有生成该依赖文件的规则,如果有规则生成该依赖文件,则执行规则中的命令生成依赖文件;若没有规则生成该依赖文件,则程序报错。

在这里插入图片描述

如果依赖文件都存在,则检查规则中的目标是否需要更新,如果目标的所有依赖中有一个被更新,则目标需要更新。这一点是根据哪个时间大进行决定的。如果目标时间大于依赖时间就不更新,目标时间小于依赖时间就更新。因为是先有依赖才有的目标,所以不需要更新的时候目标的时间一定是比依赖的时间大的。

在这里插入图片描述
根据上面,于是我们有了第二个版本的Makefile文件。

main: main.o add.o sub.o mul.o dive.o
	gcc -o main.o add.o sub.o mul.o dive.o
main.o: main.c
	gcc -o main.o -c main.c -I./
add.o: add.c
	gcc -o add.o -c add.c -I./
sub.o: sub.c
	gcc -o sub.o -c sub.c -I./
mul.o: mul.c
	gcc -o mul.o -c mul.c -I./
dive.o: dive.c
	gcc -o dive.o -c dive.c -I./

可以发现这个版本里面虽然比上一个版本要稍微好点,但是里面有很多冗余,若C语言文件很多,编写起来会很麻烦。因此我们还需要继续寻找第三个更便捷的版本。既然上面有很多重复的部分,那么在Makefile中是否有相应的变量之类的东西去进行取代呢?

Makefile中也有变量的概念。Makefile中使用的变量类似于C语言中的宏定义,使用该变量相当于内容的替换,使用变量可以使Makefile易于维护,修改起来变得简单。Makefile中有三种类型的变量,分别是普通变量、自带变量、自动变量。

变量的定义是用=,使用的时候是$(变量名)。如下面语句定义了变量var1并将值赋值给了var2。

var1=main.c
var2=$(var1)

在编译器中也提供了一些变量供用户名使用,我们可以直接对其进行赋值。

自带变量名作用
CC编译器 gcc
CPPFLAGSC预处理选项 -I
CFLAGSC编译器选项 -Wall -g -c
LDFLAGS链接器选项 -L -l

除此之外还有一些自动变量,自动变量只能用于规则的命令之中,而不允许在目标和依赖中使用,下面是一些自动变量。

自动变量名含义
$@表示规则中的目标
$<表示规则中的第一个条件
$^表示规则中的所有条件,组成一个列表,以空格隔开,如果有重复项会自动去重。

除了上述的变量之外还需要提及的是一个模式规则。模式规则用%,表示一个或者多个,依赖条件中同样可以使用%,依赖条件中的%的取值取决于其目标。

有了上述这些,我们可以写我们的第三个版本的Makefile。

target=main
objects=main.o add.o sub.o mul.o sum.o
CC=gcc
CPPFLAGS=-I./

main:$(objects)
	$(CC) -o $@ $^
%.o:%.c
	$(CC) -o $@ -c $< $(CPPFLAGS)

可以发现这个版本冗余的部分比上一个版本好了很多,但是在objects变量的地方我们需要写很多.o,所以还是麻烦,在Makefile中也提供了函数。

Makefile中的函数有很多,此处就说两个最常用的。

函数名作用示例示例说明
wildcard查找指定目录下指定类型的文件src=$(wildcard *.c)在当前路径寻找后缀为.c的文件,赋值给src
patsubst匹配替换objects=$(patsubst %.c, %.o, $(src))将src变量中所有后缀为.c的文件换.o

于是我们有了第四个版本的Makefile。

target=main
src=$(wildcard *.c)
objects=$(patsubst %.c, %.o, $(src))
CC=gcc
CPPFLAGS=-I./

$(target):$(objects)
	$(CC) -o $@ $^
%.o:%.c
	$(CC) -o $@ -c $(CPPFLAGS) $<

不过这个版本还有一个缺点,就是每次重新编译的时候都需要我们手动去清理掉中间的.o文件以及最终目标文件。但是我们使用make命令的时候只会去执行最终目标,如果有多个目标不会去执行。我们可以通过make 目标名去执行指定的目标。如果一个目标没有任何依赖,则永远是最新的,也就不会被执行,所以此时需要声明为伪目标,声明为伪目标之后,Makefile将不会再检查目标是否存在或者该目标是否需要更新。申明伪目标使用.PHONY 目标名进行声明。在命令中,我们在前面加入-表示此条命令出错,make也会继续执行后续命令。如果在命令的前面加入了@符号,则表示不显示命令本身,只显示结果。如果当前路径有多个makefile文件,则可以通过make -f 文件名执行对应的Makefile文件。

于是有了Makefile的第五个版本,也就是最终版本。

target=main
src=$(wildcard *.c)
objects=$(patsubst %.c, %.o, $(src))
CC=gcc
CPPFLAGS=-I./

$(target):$(objects)
	$(CC) -o $@ $^
%.o:%.c
	$(CC) -o $@ -c $< $(CPPFLAGS)
	
.PHONY:clean
clean:
	-rm -rf *.o
	rm -rf main

2. gdb

GDB是gcc的调试工具。GDB主要是帮忙完成以下四个方面的功能。

  • 启动程序,可以按照你的自定义的要求随心所欲的运行程序。
  • 可以让被调试的程序在你所指定的断点处停住(断点可以是表达式条件)。
  • 当程序被停住时,可以检查此时你的程序中所发生的事。
  • 动态地改变你程序的执行环境。

一般来说GDB调试的主要是C/C++程序。要调试C/C++程序,首先要在编译的时候将调试信息加到可执行文件中,这一点可以通过gcc的-g参数做到。如果编译的时候没有加-g,则在调试的时候看不到程序的函数名,变量名等,所替代的全是运行时的内存地址。

启动GDB在shell中执行gdb program,其中program为可执行程序的名字或者路径。下面给出一些关于启动时GDB的一些命令。

命令作用
set args指定运行时参数,如set args 10 20 30
show args查看运行时参数
run程序开始执行,若有断点则停在第一个断点处
start程序向下执行一行,停在第一条语句处
next单步跟踪,函数调用当做一条简单语句执行
step单步跟踪,函数调用进入被调用函数体内
finish退出进入的函数,如果出不去,看一下函数体内的循环是否有断点,如果有需要删掉或者设置无效
until在循环体内单步跟踪的时候执行可以退出循环体
continue继续执行程序,如果有断点则跳到下一个断点处

在调试的过程中,可以使用以下操作命令。

命令作用
list linenum显示第linenum行的上下文内容
list function显示函数名为function的源程序
list显示当前行后面的源程序
list -显示当前文件开始处的源程序
list file:linenum显示file文件中的第linenum行
list file:function显示file文件中函数名为function的源程序
set listsize count设置一次显示源代码的行数为count
show listsize显示当前listsize的设置
break linenum设置断点在第linenum行
break function设置断点在函数名为function的入口处
break filename:linenum设置断点在filename文件中的第linenum行
break filename:function设置断点在filename文件中函数名为function的入口处
break where if condition当condition满足时候在where处设置断点,如break test.c:8 if i == 8
info break查看所有断点
delete num删除断点号为num的断点
delete num1 num2 …删除多个断点,断点号为num1,num2…
delete num1-num2删除多个连续断点,断点号为num1到num2
delete删除所有断点
disable num使断点号为num的断点无效
disable num1 num2 …使断点号为num1,num2…的断点无效
disable num1-num2使在num1-num2中的连续断点无效
disable使所有的断点无效
enable num使断点号为num的无效断点有效
enable num1 num2 …使断点号为num1,num2…的无效断点有效
enable num1-num2使在num1-num2中的连续无效断点有效
enable使所有的无效断点有效
display varname设置自动显示变量名为varname的值
info display显示display中设置的自动显示信息
undisplay num删除自动显示编号num的自动显示
delete display num删除自动显示编号为num的自动显示
delete display num1 num2 …删除自动显示编号为num1,num2…的自动显示
delete display num1-num2删除自动显示编号在num1-num2中连续的自动显示
disable display num使自动显示编号为num的自动显示无效
disable display num1 num2 …使自动显示编号为num1,num2…的自动显示无效
disable display num1-num2使自动显示编号在num1-num2中的连续自动显示无效
enable display num使自动显示编号为num的无效自动显示有效
enable display num1 num2 …使自动显示编号为num1,num2…无效的自动显示有效
enable display num1-num2使自动显示编号在num1-num2中的无效自动显示有效
ptype varname打印变量名为varname的变量的类型
print varname打印变量名为varname的值
set var varname=value设置变量名为varname的变量值为value

上述的很多命令都可以简写,简写列表如下。

命令全称命令简写
listl
breakb
infoi
deleted
disabledis
enableena
runr
nextn
steps
untilu
continuec
printp

这些简写都可以配合上面的命令混合使用。

3. 文件IO

首先学习文件IO就需要会C语言库中IO函数的工作流程,流程如下:

在这里插入图片描述

在这里插入图片描述

C语言中会使用fopen函数打开一个文件,会返回一个FILE *fp

跟踪以下内核代码,我们可以发现是struct _IO_FILE定义为类型FILE

在这里插入图片描述

接下来我们看一下关于struct _IO_FILE的内容。

在这里插入图片描述在这个指针中,有三个部分是非常重要的。

  • 文件描述符:通过文件描述符可以找到文件的inode,通过inode可以找到对应的数据块。代码中的int _fileno存储的就是文件描述符。
  • 文件指针:读和写共享一个文件指针,读或者写都会引起文件指针的变化。
  • 文件缓冲区:读或者写会先通过文件缓冲区,主要是减少对磁盘的读写次数,提高读写磁盘效率。

在我们调用printf函数的时候,操作系统会先调用write函数,将文件描述符传递过去,然后操作系统会从用户态切换到内核态,通过调用系统调用sys_write()函数使设备驱动工作调用设备驱动函数显示printf函数中的内容。系统调用是由操作系统实现并提供给外部应用程序的编程接口。

在这里插入图片描述

32位的Linux会为每一个运行的程序(进程)分配一个0~4G的地址空间。这个地址空间叫虚拟地址空间。进程的虚拟地址空间分为用户区和内核区。内核区是首保护的,用户不能对其进行读写操作。内核区中非常重要的是进程管理,进程管理中有一个区域是PCB(进程控制块)。在PCB中有文件描述符表,文件描述符表中存放着打开的文件描述符,涉及文件的IO操作都会用到这些文件描述符。用户区主要是存放环境变量、命令行参数、栈区、共享库加载区、堆区、.bss、.data、.text、受保护的地址区。其中受保护的区域用户也是不能操作的。

在这里插入图片描述
在PCB中存放的文件描述表可以存放1024个文件描述符。每个进程都默认打开三个文件描述符,分别如下。

  • 标准输入,宏名为STDIN_FILENO,值为0。
  • 标准输出,宏名为STDOUT_FILENO, 值为1。
  • 标准错误。宏名为STDERR_FILENO,宏名为2。

此后该进程每打开一个文件都会将该文件的文件描述符放在文件描述符表中最小的空位处。

在这里插入图片描述

PCB是通过struct task_struct进行定义的。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1229261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详解“协方差”与“相关系数”

引言 PCA的目标对象是矩阵&#xff0c;例如&#xff0c;有m个样本&#xff0c;每个样本有n个特征&#xff0c;那么就可以构造成一个样本矩阵&#xff0c;并转换成矩阵的形式。 PCA的最终目的是减少特征的个数&#xff0c;去掉那些不重要的特征&#xff0c;也就是减小矩阵列向量…

【LeetCode:689. 三个无重叠子数组的最大和 | 序列dp+前缀和】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

在回调之间共享数据

可以在 App 中为 UI 组件编写回调函数&#xff0c;以指定用户与其交互时的行为方式。 在具有多个相互依赖的 UI 组件的 App 中&#xff0c;回调函数通常必须访问主 App 函数中定义的数据&#xff0c;或与其他回调函数共享数据。例如&#xff0c;如果创建一个具有列表框的 App&a…

vue 如何实现粘贴复制功能

实现粘贴复制功能 vue 实现粘贴复制功能&#xff0c;也可用于app中h5插件&#xff0c;共四种方法&#xff0c;特别推荐第四种方法&#xff0c;具体还需了解根据需求使用 1. 安装第三方插件方法&#xff08;不推荐&#xff09; 这种方法兼容性很好&#xff0c;如果项目只使用了…

如何自己生成fip.bin在Milkv-duo上跑freertos

前言 &#xff08;1&#xff09;PLCT实验室实习生长期招聘&#xff1a;招聘信息链接 &#xff08;2&#xff09;本来是要跑RT-Thread的&#xff0c;搞了很久&#xff0c;一直没成功。哭死&#xff0c;后面mentor通电话&#xff0c;让我先跑一下freertos试试。有可能是因为RT-Th…

这5款好用的app,能让你生活质量和效率飙升

随着科技的进步和智能手机的普及&#xff0c;不少好用的手机APP出现让我们的生活更加便捷&#xff0c;也提升了我们的生活质量&#xff0c;带给我们不少惊喜。接下来&#xff0c;让我们一起探索这5款实用APP&#xff0c;看看有没有适合你的&#xff01; 1、粉笔 一款专门备考…

全屋智能:鱼很大,但水更深

1990年&#xff0c;作为世界首富的比尔盖茨&#xff0c;已经对智能家居生活有了明确畅想。他花了7年时间&#xff0c;耗资1亿多美元&#xff0c;在美国西雅图的华盛顿湖东岸&#xff0c;建了一座占地6600平方米的湖滨别墅。在这座被命名为“未来之屋”的豪宅里&#xff0c;到处…

暖阳脚本_ 将Agent技术的灵活性引入RPA,清华等发布自动化智能体ProAgent

RPA暖阳脚本 近日&#xff0c;来自清华大学的研究人员联合面壁智能、中国人民大学、MIT、CMU 等机构共同发布了新一代流程自动化范式 “智能体流程自动化” Agentic Process Automation&#xff08;APA&#xff09;&#xff0c;结合大模型智能体帮助人类进行工作流构建&#x…

OTP语音芯片 NV080D在智能空气检测仪的应用

随着人们对健康和环保的关注度不断提高&#xff0c;人们对看不见的家居环境也越来越重视。智能空气检测仪的市场需求也在不断增长中&#xff0c;呈现稳中向好的趋势。智能空气检测仪能够检测室内空气中的PM2.5、甲醛、TVOC等有害物质&#xff0c;同时还可以检测温湿度、空气质量…

亚马逊云科技帮助客户在云中构建具有高可靠性和韧性的应用程序

在一个理想的世界里&#xff0c;一切都非常完美&#xff0c;并且一直都在顺畅运作。早晨的通勤没有交通堵塞&#xff0c;最喜欢的停车位一直空着&#xff0c;一杯温度适宜的饮料&#xff0c;生活一帆风顺&#xff0c;没有任何中断。在需要时&#xff0c;您能得到所需的东西。但…

如何简单挖掘公益SRC?

目录 1、寻找漏洞 1)谷歌语法 2)fofa 2、挖掘漏洞 3、提交报告 第一步&#xff1a;“标题”和“厂商信息”和“所属域名” 第二步&#xff1a;其它内容 第三步&#xff1a;复现步骤 0、IP域名归属证明 1、漏洞页 2、该干啥 3、注入的结果 4、上榜吉时 时间&#x…

多视图聚类的论文阅读(一)

当聚类的方式使用的是某一类预定义好的相似性度量时&#xff0c; 会出现如下情况&#xff1a; 数据聚类方面取得了成功&#xff0c;但它们通常依赖于预定义的相似性度量&#xff0c;而这些度量受原始方法的影响:当输入维数相对较高时&#xff0c;往往是无效的。 1. Deep Mult…

asp.net校园二手交易平台系统VS开发sqlserver数据库web结构c#编程计算机网页

一、源码特点 asp.net校园二手交易平台系统 是一套完善的web设计管理系统&#xff0c;系统采用mvc模式&#xff08;BLLDALENTITY&#xff09;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 vs2010&#xff0c;数据库为sqlserver2008&a…

网络渗透测试(TCP/IP)理论篇

TCP/IP体系 垂直服务&#xff1a;底层为高层服务 TCP/IP体系结构是一个分层的协议体系&#xff0c;由多个层次组成&#xff0c;每个层次都负责不同的功能。以下是TCP/IP体系结构的主要层次&#xff1a; 物理层&#xff08;Physical Layer&#xff09;&#xff1a;该层负责传输…

15篇MyBatis-Plus系列集合篇「值得收藏学习」

历史文章&#xff08;文章累计490&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 M…

向量数据库——AI时代的基座

1.前言 向量数据库在构建基于大语言模型的行业智能应用中扮演着重要角色。大模型虽然能回答一般性问题&#xff0c;但在垂直领域服务中&#xff0c;其知识深度、准确度和时效性有限。为了解决这一问题&#xff0c;企业可以利用向量数据库结合大模型和自有知识资产&#xff0c;…

金属压块液压打包机比例阀放大器

液压打包机是机电一体化产品&#xff0c;主要由机械系统、液压控制系统、上料系统与动力系统等组成。整个打包过程由压包、回程、提箱、转箱、出包上行、出包下行、接包等辅助时间组成。市场上液压打包机主要分为卧式与立式两种&#xff0c;立式废纸打包机的体积比较小&#xf…

释放固态继电器的力量:主要优势和应用

固态继电器&#xff08;SolidStateRelay&#xff0c;缩写SSR&#xff09;&#xff0c;是由微电子电路&#xff0c;分立电子器件&#xff0c;电力电子功率器件组成的无触点开关。用隔离器件实现了控制端与负载端的隔离。固态继电器的输入端用微小的控制信号&#xff0c;达到直接…

wvp gb28181 pro 推流列表功能

界面截图 功能说明 功能演示 客户端推流 ​​​​​​​手机端&#xff0c;使用芯象软件进行推流&#xff0c;支持ios、android 推流地址使用如下格式&#xff1a; rtsp://192.168.4.116:554/live/123?secret035c73f7-bb6b-4889-a715-d9eb2d1925cc 详细操作教程参考 【腾讯文…

外贸自建站什么意思?自建独立网站的好处?

外贸自建站的含义是什么&#xff1f;如何区分自建站和独立站&#xff1f; 随着全球贸易的不断发展&#xff0c;越来越多的企业开始关注外贸自建站。那么&#xff0c;“外贸自建站”到底是什么意思呢&#xff1f;海洋建站将为您详细解析这个问题&#xff0c;带您深入了解这一新…