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表示下一条代码行的内存地址。)

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

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

相关文章

安卓蓝牙扫描流程

目录 系统广播 流程图 源码跟踪 系统广播 扫描开启广播:BluetoothAdapter.ACTION_DISCOVERY_STARTED "android.bluetooth.adapter.action.DISCOVERY_STARTED";扫描关闭广播:BluetoothAdapter.ACTION_DISCOVERY_FINISHED "android.b…

八股(One Day one)

最近老是看到一些面试的视频,对于视频内部面试所提到的八股文,感觉是知道是什么,但是要说的话,却又不知道该怎么说(要不咋称之为八股文呢),所以就想到写一篇八股文总结的博客,以便进…

Rust 在前端基建中的使用

摘要 随着前端技术的不断发展,前端基础设施(前端基建)的建设已成为提升开发效率、保障产品质量的关键环节。然而,在应对复杂业务场景与高性能需求时,传统的前端技术栈逐渐暴露出诸多不足。近年来,Rust语言…

豆包MarsCode:a替换函数

问题描述 思路分析 在这个问题中,我们的目标是将字符串中的所有小写字母 a 替换为 "%100"。为了实现这一点,我们需要分析问题的核心需求和合理的解决方案。以下是分析和思路的详细步骤: 1. 理解问题 给定一个字符串 s&#xff0…

人脸生成3d模型 Era3D

从单视图图像进行3D重建是计算机视觉和图形学中的一项基本任务,因为它在游戏设计、虚拟现实和机器人技术中具有潜在的应用价值。早期的研究主要依赖于直接在体素上进行3D回归,这往往会导致过于平滑的结果,并且由于3D训练数据的限制&#xff0…

信贷域——互联网金融理论基础

摘要 互联网金融这种新兴的金融业态近几年飞速发展,规模不断扩大,互联网金融在对我国金融体系和经济发展影响中所占的分量越来越重,一定程度上也推动了互联网金融理论的发展。 互联网金融与传统金融都是金融,有着相近的理论基础。…

LightGBM分类算法在医疗数据挖掘中的深度探索与应用创新(上)

一、引言 1.1 医疗数据挖掘的重要性与挑战 在当今数字化医疗时代,医疗数据呈爆炸式增长,这些数据蕴含着丰富的信息,对医疗决策具有极为重要的意义。通过对医疗数据的深入挖掘,可以发现潜在的疾病模式、治疗效果关联以及患者的健康风险因素,从而为精准医疗、个性化治疗方…

STM32串口第一次接收数据时第一个字节丢失的问题

解决方法:开启中断之前,先清除标志位【1】。 串口清除标志位: __HAL_UART_CLEAR_PEFLAG(&huart1); HAL_UART_Receive_IT(&huart1,&RxUart, 1); 定时器清除标志位: __HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE);…

深度学习中的残差网络、加权残差连接(WRC)与跨阶段部分连接(CSP)详解

随着深度学习技术的不断发展,神经网络架构变得越来越复杂,而这些复杂网络在训练时常常遇到梯度消失、梯度爆炸以及计算效率低等问题。为了克服这些问题,研究者们提出了多种网络架构,包括 残差网络(ResNet)、…

Pytorch | 从零构建EfficientNet对CIFAR10进行分类

Pytorch | 从零构建EfficientNet对CIFAR10进行分类 CIFAR10数据集EfficientNet设计理念网络结构性能特点应用领域发展和改进 EfficientNet结构代码详解结构代码代码详解MBConv 类初始化方法前向传播 forward 方法 EfficientNet 类初始化方法前向传播 forward 方法 训练过程和测…

音视频入门基础:MPEG2-TS专题(20)——ES流简介

《T-REC-H.222.0-202106-S!!PDF-E.pdf》第27页对ES进行了定义。ES流是PES packets(PES包)中编码的视频、编码的音频或其他编码的比特流。一个ES流(elementary stream)在具有且只有一个stream_id的PES packets序列中携带&#xff1…

天水月亮圈圈:舌尖上的历史与传承

在天水甘谷县,有一种美食如同夜空中的明月,散发着独特的魅力,它就是有着百年历史的月亮圈圈。月亮圈圈原名甘谷酥圈圈,据传,由大像山镇蒋家庄一姓李的厨师创制而成,后经王明玖等厨师的光大传承,…

YOLOv11融合[CVPR2023]FFTformer中的FSAS模块

YOLOv11v10v8使用教程: YOLOv11入门到入土使用教程 YOLOv11改进汇总贴:YOLOv11及自研模型更新汇总 《Efficient Frequency Domain-based Transformers for High-Quality Image Deblurring》 一、 模块介绍 论文链接:https://arxiv.org/abs…

java如何使用poi-tl在word模板里渲染多张图片

1、poi-tl官网地址 http://deepoove.com/poi-tl/ 2、引入poi-tl的依赖 <dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version></dependency>3、定义word模板 释义&#xf…

《信管通低代码信息管理系统开发平台》Windows环境安装说明

1 简介 《信管通低代码信息管理系统应用平台》提供多环境软件产品开发服务&#xff0c;包括单机、局域网和互联网。我们专注于适用国产硬件和操作系统应用软件开发应用。为事业单位和企业提供行业软件定制开发&#xff0c;满足其独特需求。无论是简单的应用还是复杂的系统&…

8K+Red+Raw+ProRes422分享5个影视级视频素材网站

Hello&#xff0c;大家好&#xff0c;我是后期圈&#xff01; 在视频创作中&#xff0c;电影级的视频素材能够为作品增添专业质感&#xff0c;让画面更具冲击力。无论是广告、电影短片&#xff0c;还是品牌宣传&#xff0c;高质量的视频素材都是不可或缺的资源。然而&#xff…

Git远程仓库的使用

一.远程仓库注册 1.github&#xff1a;GitHub Build and ship software on a single, collaborative platform GitHub 2.gitee&#xff1a;GitHub Build and ship software on a single, collaborative platform GitHub github需要使用魔法&#xff0c;而gitee是国内的仓…

Echarts连接数据库,实时绘制图表详解

文章目录 Echarts连接数据库&#xff0c;实时绘制图表详解一、引言二、步骤一&#xff1a;环境准备与数据库连接1、环境搭建2、数据库连接 三、步骤二&#xff1a;数据获取与处理1、查询数据库2、数据处理 四、步骤三&#xff1a;ECharts图表配置与渲染1、配置ECharts选项2、动…

【Java基础面试题038】栈和队列在Java中的区别是什么?

回答重点 栈&#xff08;Stack&#xff09;&#xff1a;遵循后进先出&#xff08;LIFO&#xff0c;Last In&#xff0c;First Out&#xff09;原则。即&#xff0c;最后插入的元素最先被移除。主要操作包括push&#xff08;入栈&#xff09;和pop&#xff08;出栈&#xff09;…

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

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