Linux系统编程深度解析:C语言实战指南

文章一览

  • 前言
  • 一、gcc编译系统
    • 1.1 文件名后缀
    • 1.2 C语言编译过程
    • 1.3 gcc命令行选项
  • 二、gdb程序调试工具
    • 2.1 启动gdb和查看内部命令
    • 2.2 显示源程序和数据
      • 2.2.1 显示和搜索源程序
      • 2.2.2 查看运行时数据
    • 2.3 改变和显示目录或路径
    • 2.4 控制程序的执行
      • 2.4.1 设置断点
      • 2.4.2 显示断点
      • 2.4.3 删除断点
      • 2.4.4 运行程序
      • 2.4.5 程序的单步跟踪和连续执行
      • 2.4.6 函数调用
    • 2.5 其他常用命令

前言

在数字世界的浩瀚星海中,Linux操作系统如同一颗璀璨的恒星,以其开源、稳定和强大的特性,照亮了无数开发者的编程之路。而C语言,作为最接近硬件层面的高级编程语言,以其无与伦比的性能和灵活性,成为了构建Linux系统的基石。在这个充满挑战与机遇的时代,掌握Linux环境下的C程序设计,不仅是技术追求,更是一种对极致性能和系统控制的渴望。
现在,让我们一起启程,深入Linux与C语言的神秘世界。

一、gcc编译系统

1.1 文件名后缀

目前Linux平台上最常用的C语言编译系统是gcc(GNU Compiler Collection)

常用文件名后缀及其表示的文件类型:

文件名后缀文件类型
.cC源文件
.i预处理后的C源文件
.ii预处理后的C++源文件
.hC或C++头文件
.C .cc .cp .cpp .c++ .cxxC++源文件
.s汇编程序文件
.S必须预处理的汇编程序文件
.o目标文件
.a静态链接库
.so动态链接库

1.2 C语言编译过程

  1. 预处理阶段预处理程序(Preprocessor)读取C语言源文件,对其中以“#”开头的指令(伪指令)和特殊符号进行处理。 伪指令主要包括文件包含、宏定义和条件编译指令

  2. 编译阶段编译程序(Compiler)对预处理之后的输出文件进行词法分析和语法分析,试图找出所有不符合语法规则的部分。在确定各成分都符合语法规则后,将其“翻译”为功能等价的中间代码表示或者汇编代码。

  3. 汇编过程汇编程序(Assembler)把汇编语言代码翻译成目标机器代码的过程。

  4. 连接阶段将一个文件中引用的符号(如变量或函数调用)与该符号在另外一个文件中的定义连接起来,从而使有关的目标文件连成一个整体,最终成为可被操作系统执行的可执行文件。连接模式分为静态连接和动态连接

1.3 gcc命令行选项

$ gcc f1.c f2.c (针对C语言源程序) 执行完成后,生成默认的可执行文件a.out。

按照选项作用所对应的编译阶段,可将gcc的选项分为四组:预处理选项编译选项优化选项连接选项

  1. 预处理选项
选项格式功能
-C在预处理后的输出中保留源文件中的注释
-D name预定义一个宏name,而且其值为1
-D name=definition预定义一个宏name,并指定其值为definition所指定的值。其作用等价于在源文件中使用宏定义指令:#define name definition。但-D选项比宏定义指令的优先级高,它可以覆盖源文件中的定义
-U name取消先前对name的任何定义,不管是内置的,还是由-D选项提供的
-I dir指定搜索头文件的路径dir。先在指定的路径中搜索要包含的头文件,若找不到,则在标准路径(/usr/include, /usr/lib及当前工作目录)上搜索
-E只对指定的源文件进行预处理,不做编译,生成的结果送到标准输出

例:

 # 添加“-I /root”参数编译,/root为my.h文件位置
 gcc 1-3.c -o 1-3 -I /root 
  1. 编译程序选项
选项格式功能
-c只生成目标文件,不进行连接。用于对源文件的分别编译
-S只进行编译,不做汇编,生成汇编代码文件格式,其名与源文件相同,但扩展名为.s
-o file将输出放在文件file中。如果未使用该选项,则可执行文件放在a.out中
-g指示编译程序在目标代码中加入供调试程序gdb使用的附加信息
-v在标准出错输出上显示编译阶段所执行的命令,即编译驱动程序及预处理程序的版本号
  1. 优化程序选项

优化分为对中间代码的优化和针对目标代码生成的优化。

  1. 连接程序选项
选项格式功能
object -file -name不以专用后缀结尾的文件名就认为是目标文件名或库名。连接程序可以根据文件内容来区分目标文件和库
-c -S -E如果使用其中任何一个选项,那么都不运行连接程序,而且目标文件名不应该用做参数
-llibrary连接时搜索由library命名的库。连接程序按照在命令行上给定的顺序搜索和处理库及目标文件。实际的库名是liblibrary.a
-static在支持动态连接的系统中,它强制使用静态链接库,而阻止连接动态库;而在其他系统中不起作用
-Ldir把指定的目录dir加到连接程序搜索库文件的路径表中,即在搜索-l后面列举的库文件时,首先到dir下搜索,找不到再到标准位置下搜索
-Bprefix该选项规定在什么地方查找可执行文件、库文件、包含文件和编译程序本身数据文件
-o file指定连接程序最后生成的可执行文件名称为file,不是默认的a.out
  • Linux下库文件的命名有一个约定,所有的库名都以lib开头。因此,在-l选项所指定的文件名前自动地插入lib。并且约定,以.a(归档,archive)结尾的库是静态库,以**.so(共享目标,shared object)结尾的库是动态库**。

  • 生成静态库的方法实际上可分为两步:

① 将各函数的源文件编译成目标文件。例如:

\$ gcc -c f1.c f2.c f3.c -o game.o

由此可得到各源文件的目标文件game.o

② 使用ar工具将目标文件收集起来,放到一个归档文件中。例如:

\$ ar -rcs \$HOME/lib/libgame.a game.o

  • 生成静态库以后,就可在编译C语言源文件时指明对它进行搜索、连接,例如:

\$ gcc f1.c f2.c f3.c -o mygame -static -L$HOME/lib -lgame

例:

gcc编译静态库

#gcc 编译静态库并调用,演示如何将 add.c 打包成一个静态库来供 main.c 调用.
#1.首先将add.c编译成目标文件。
gcc  -c  add.c  -o  add.o
# 2.ar 打包静态库,将 add.o 打包成 libadd.a,
#参数 [-crv] :–c表示建立备存文件,- r表示将文件插入备存文件中,-v表示程序执行时显示详细的信息
ar  -crv  libadd.a  add.o
#3.使用静态库 libadd.a编译main.c, [-L./] 表示将当前目录加到静态库的搜索路径
gcc  main.c  -L./  libadd.a  -o  main2
#4.执行
./main2

gcc 编译动态库

#1.编译位置无关的目标文件 add.o,因为动态库动态加载到内存中的位置不确定,所以需要编译位置无关
gcc -fPIC -c add.c -o add.o
打包成动态库,
#2.如果不加 sudo 会提示没有权限,如果不指定/usr/lib/文件夹,会在执行时提示
#error while loading shared libraries:libadd.so: cannot open shared object file: No such file or directory
sudo gcc -shared add.o -o /usr/lib/libadd.so
#3.编译
sudo gcc -0 main3 main.c -L /usr/lib/ -ladd
#4.执行
./main3

二、gdb程序调试工具

程序中的错误按其性质可分为三种:

(1)编译错误,即语法错误。主要是程序代码中有不符合所用编程语言语法规则的错误。

(2)运行错误。如对负数开平方,除数为0,循环终止条件永远不能达到等 。

(3)逻辑错误。这类错误往往是编程前对求解的问题理解不正确或算法不正确引起的,它们很难查找。查找程序中的错误,诊断其准确位置,并予以改正,这就是程序调试。程序调试分为人工查错机器调试

gdb主要帮助用户在调试程序时完成四方面的工作

(1)启动程序,可以按用户要求影响程序的运行行为。

(2)使运行程序在指定条件处停止。

(3)当程序停止时,检查它出现了什么问题。

(4)动态改变程序的执行环境,这样就可以纠正一个错误的影响,然后再纠正其他错误。

2.1 启动gdb和查看内部命令

为了发挥gdb的全部功能,需要在编译源程序时使用-g选项:

gcc  -g  prog.c  -o  prog  #(针对C语言源程序prog.c)
gcc  -g  program.cpp  -o  program # (针对C++源程序program.cpp)

启动gdb的常用方法有:

(1)以一个可执行程序作为gdb的参数:

$ gdb prgm

(2)同时以可执行程序和core文件作为gdb的参数:

$ gdb prgm core

启动gdb后就显示其提示符:(gdb),并等待用户输入相应的内部命令。

用户可以利用命令quit终止其执行,退出gdb环境。

2.2 显示源程序和数据

2.2.1 显示和搜索源程序

(1)显示源文件

利用list命令可以显示源文件中指定的函数代码行

格式功能
list没有参数,显示当前行之后或周围的10多行
list –显示先前10行之前的10行
list [file:] num显示源文件file中给定行号num周围的10行。如果缺少file,则默认为当前文件。例如,list 100
list start , end显示从行号start至end之间的代码行。例如,list 20,38
list [file:]function显示源文件file中指定函数function的代码行。如果缺少file,则默认为当前文件。例如,list meng1.c:square

也可以利用set listsize命令重新设置一次显示源程序的行数:

set listsize linenum

(2)模式搜索

格式功能
forward-search regexp从列出的最后一行开始向前搜索给定的模式regexp(即正则表达式,一个字符串的匹配模式)。例如,forward-search i=*
search regexp同上
reverse-search regexp从列出的最后一行开始向后搜索给定的模式regexp(即正则表达式,一个字符串的匹配模式)。例如,reverse-search i=??

2.2.2 查看运行时数据

(1)print命令

  • 当被调试的程序停止时,可以用print命令(简写为p)或同义命令inspect来查看当前程序中运行的数据。
  • print命令的一般使用格式:print [/fmt] exp

print i (或p i) 显示当前变量i的值。

print i\*j (或p i\*j) 将根据程序当前运行的实际情况显示出i*j的值。

(2)gdb所支持的运算符

①用&运算符取出变量在内存中的地址,如:

print &i 显示变量i的存放地址。

print &array[i] 显示数组array第i个元素的地址。

{ type }adrexp 表示一个数据类型为type、存放地址为adrexp的数据。

@ 是一个与数组有关的双目运算符,使用形式如:

print array@10 打印从array(数组名,即数组的基地址)开始的10个值。

print array[3]@5 打印从array第三个元素开始的5个数组元素的数值。

file :: var (或者 function :: var ) 表示文件file(或者函数function)中变量var的值。例如:

print inner::i 打印函数inner中变量i的当前值。

(3)输出格式

由表示格式的字母(如o、x、d、u、t、f、a、i、c、s)和表示数据长度的字母(如b、w、h、g)组成。

2.3 改变和显示目录或路径

(1)directory命令

​ 将给定目录dir添加到源文件搜索路径的开头,并且忽略先前保存的有关源文件和代码行位置的信息。其一般格式是:

directory [dir] 或者 dir [dir]

(2)cd命令

​ cd命令将调试程序和被调试程序的工作目录置为指定的目录dir。其使用格式为:

cd dir

(3)path命令

​ 利用path命令可以将一个或多个目录添加到目标文件搜索路径的开头。其使用格式是:

path dirs

(4)pwd命令

​ 该命令用来显示工作目录。

(5)show directories命令

​ 该命令显示定义的源文件搜索路径。

(6)show paths命令

​ 该命令显示当前查找目标文件的搜索路径。

2.4 控制程序的执行

2.4.1 设置断点

编译源程序时需要使用-g选项

在gdb中用break命令(其缩写形式为b)设置断点:

break linenum (在当前文件指定行linenum处设置断点,停在该行开头)

break linenum if condition (在当前文件指定行linenum处设置断点,但仅在条件表达式condition成立时才停止程序执行)

break function (在当前文件函数function的入口处设置断点)

break file:linenum (在源文件file的linenum行上设置断点)

break file:function (在源文件file的函数function的入口处设置断点)

break *address (运行程序在指定的内存地址address处停止)

break (不带任何参数,则表示在下一条指令处停止)

断点应设置在可执行的行上,不应是变量定义之类的语句

2.4.2 显示断点

info  breakpoints  [num]
info  break  [num]

2.4.3 删除断点

delete [bkptnums]

2.4.4 运行程序

run [args] (run简写是r)

2.4.5 程序的单步跟踪和连续执行

(1)单步跟踪

step [N] 参数N表示每步执行的语句行数。 进入被调用函数内部执行。

next [N] 参数N表示每步执行的语句行数。 被调用函数被当做一条指令执行。

stepi(缩写为si)或nexti(缩写为ni)命令一条一条地执行机器指令。

(2)连续执行

利用continue,c或fg命令连续执行到下一个断点

2.4.6 函数调用

call expr

​ 其中,expr是所用编程语言的函数调用表达式,包括函数名实参

  • 在调试过程中,可以使用return命令强行从正在执行的函数中退出:

return [expr]

  • 还可以使用finish命令退出函数,但它并不立即退出,而是继续运行,直至当前函数返回

2.5 其他常用命令

1.执行shell命令

shell command-string

例如:

(gdb) shell date

2009年 03月 31日 星期二 16:47:56 CST

(gdb)

2.修改变量值

(gdb) print x=10

(gdb) set variable x=10

3.跳转执行

jump linenum (参数linenum表示下一条语句的行号。)

jump *addr (参数 addr表示下一条代码行的内存地址。)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用QML实现播放器进度条效果

使用QML实现播放进度效果 QML Slider介绍 直接上DEMO如下: Slider {width: 300;height: 20;orientation: Qt.Vertical; //决定slider是横还是竖 默认是HorizontalstepSize: 0.1;value: 0.2;tickmarksEnabled: true; //显示刻度}效果图如下 那么我先改变滑块跟滚轮…

云数智融合体系建设实践——以工行软件开发中心为例

随着“云计算第三次浪潮”的涌动,业界正见证着一场围绕“算力”的结构性变革。云计算、大数据、人工智能三大核心技术的深度融合,正推动着算力基础设施的快速发展,实现算力的高效调度与利用,也标志着业界对云计算体系布局的全新理…

评估大语言模型在药物基因组学问答任务中的表现:PGxQA

​这篇文献主要介绍了一个名为PGxQA的资源,用于评估大语言模型(LLM)在药物基因组学问答任务中的表现。 研究背景 药物基因组学(Pharmacogenomics, PGx)是精准医学中最有前景的领域之一,通过基因指导的治疗…

com.google.common.collect.ImmutableList$SerializedForm

今天AndroidStudio安装了个2021版本的,gradle用了7.3.3,创建项目后控制台总是有这样一个错误: Unable to load class com.google.common.collect.ImmutableList$SerializedForm. This is an unexpected error. Please file a bug containing…

[机器学习]sklearn入门指南(2)

上一篇文章中,我们介绍了如何用sklearn训练和预测模型,以及缺失值处理,详见[机器学习]sklearn入门指南(1) 分类变量 分类变量(Categorical Variable),也称为定性变量(Q…

CentOS下,离线安装vscode的步骤;

前置条件: 1.CentOS7; 步骤: 1.下载vscode指定版本,例如; 例如 code-1.83.1-1696982959.el7.x86_64.rpm 2.使用下面命令: sudo rpm -ivh code-1.83.1-1696982959.el7.x86_64.rpm 其他: 卸载vscode的命…

AI一键制作圣诞帽头像丨附详细教程

我用AI换上圣诞帽头像啦~🎅 不管是搞笑表情、宠物头像还是你的自拍!!都能一键添加圣诞帽元素,毫无违和感!🎉 详细教程在P3、P4,手残党也能轻松搞定! 宝子们需要打“need”&#xff0…

基于java博网即时通讯软件的设计与实现【源码+文档+部署讲解】

目 录 1. 绪 论 1.1. 开发背景 1.2. 开发意义 2. 系统设计相关技术 2.1 Java语言 2.2 MySQL数据库 2.3 Socket 3. 系统需求分析 3.1 可行性分析 3.2 需求分析 3.3 系统流程图 3.4 非功能性需求 4. 系统设计 4.1 系统功能结构 4.2 数据库设计 5. 系统实现 5.…

智能公文写作一体机,开箱即用快速部署超便捷

在繁忙的政企事业单位中,时间就是生产力。公文撰写作为各类组织日常工作的核心环节,却常常因为传统的公文处理流程繁琐耗时而成为效率的瓶颈。如何打破这一瓶颈,实现高效的公文撰写,成为了众多单位关注的焦点。 一款即开即用的公文…

idea2024创建JavaWeb项目以及配置Tomcat详解

今天呢,博主的学习进度也是步入了JavaWeb,目前正在逐步杨帆旗航,迎接全新的狂潮海浪。 那么接下来就给大家出一期有关JavaWeb的配置教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正…

从零开始使用MaxKB打造本地大语言模型智能问答系统与远程交互

文章目录 前言1. 下载运行Ollama2. 安装大语言模型3. 安装Cpolar工具4. 配置公网地址5. 固定公网地址6. MaxKB 添加Olama7.创建问答应用 前言 目前大语言模型(LLM)已经成为了人工智能领域的一颗璀璨明星,从自然语言处理到智能问答系统&#…

二年级数学知识边界总结思考-下册

目录 一、背景二、过程1.数据收集和整理一、知识点二、由来三、作用和意义 2.图形的运动一、知识点二、由来三、作用和意义 3.小小设计师一、知识点二、由来三、作用和意义 4.克和千克一、知识点二、由来三、作用和意义 5.数学广角-推理一、知识点二、由来三、作用和意义 三、总…

企业数字化转型加速,现代 IT 如何用 Datadog 全面提升可观测性?

作为 Gartner 可观测平台魔力象限的领导者,Datadog 凭借全面的功能、直观的用户界面和强大的产品路线图赢得了全球企业的信任。 企业 IT 架构正变得日益复杂,从本地服务器到云端部署,从单体应用向微服务,还有容器、 Kubernetes 等…

绕组识别标签规范

有标签名称的要标记,没有的不用标记 需要标注的工具、器材 图像中文名称标签名称od脱模剂watering can2铁铲shovel1记号笔,白色着重标bluepen/whitepen6纸质标签label3钢尺scale5玻璃纤维带(卷)红色网格布red grid4白色网格布wh…

NPM老是无法install,timeout?npm install失败

NPM老是无法install,timeout? 尝试一下如下操作 一、 更换国内源 npm config set registry https://registry.npmmirror.com npm install或指定源install npm install pkg --registry https://registry.npmmirror.com --legacy-peer-deps如下图 二…

Unity开发哪里下载安卓Android-NDK-r21d,外加Android Studio打包实验

NDK下载方法(是r21d,不是r21e, 不是abc, 是d版本呢) google的东西,居然是完全开源的 真的不是很多公司能做到,和那种伪搜索引擎是不同的 到底什么时候google才会开始造车 不过风险很多,最好不要合资,风险更大 Andr…

六、模型显示位置与放缩

参考文档 # https://docs.live2d.com/zh-CHS/cubism-sdk-manual/layout/ 查看 LAppLive2DManager.cpp 中的 ChangeScene 方法, void LAppLive2DManager::ChangeScene(Csm::csmInt32 index) {_sceneIndex index;if (DebugLogEnable){LAppPal::PrintLog("[AP…

我的JAVA-Web基础(2)

1.JDBC 防止sql注入 2.JSP JSP的基本语法 基本语法是 <% %> Java代码 <% %> 输出变量 可以转换成${变量}的EL表达式 <%! %>定义变量 JSP的基本语法包括以下几个主要部分&#xff1a; 1. 表达式&#xff08;Expression&#xff09; 表达式用于将…

VR 动感单车身心调适系统的功能与作用

如今&#xff0c;人们面临着来自各方的压力&#xff0c;国家重视国民身心健康&#xff0c;但人们在实际生活中却缺乏有效的身心调节方式。无论是久坐的白领&#xff0c;还是学业繁重的学生&#xff0c;都存在身体亚健康和心理压力大的问题。传统健身方式枯燥、心理咨询成本高且…

数据中台到底是什么?

数据中台不是一套系统&#xff0c;也不是一套产品&#xff0c;而是一种机制。在传统IT架构中&#xff0c;不同部门&#xff0c;不同业务系统和不同的数据中心会产生大量数据。这些数据如同烟囱一样是垂直划分的&#xff0c;彼此之间无法连接&#xff0c;我们也把这种数据叫做数…