Linux开发入门笔记——C程序设计

Linux下的程序设计主要指C程序设计,它与其他环境中的C程序设计一样,主要涉及到编辑器、编译链接器、调试器及项目管理工具。

GNU CC编程

GCC编译器能将C、C++语言源程序、汇编程序和目标程序编译、连接成可执行文件,如果没有给出可执行文件的名字,GCC将生成一个名为a.out的文件。
在Linux系统中,编译器通过程序的扩展名可分辨出编写原始程序代码所用的语言,由于不同程序所需要执行编译的步骤是不同的。因此GCC可根据不同的扩展名对它们进行分别处理。

GCC所支持的扩展名文件
在这里插入图片描述

GCC 编译过程

编译过程分为四个阶段
预处理(Pre-Processing)
编译(Compiling)
汇编(Assembling)
链接(Linking)

基本语法格式
gcc [选项] 源文件 [选项] [目标文件]

举例

$gcc -E hello.c -o hello.i
#“-E”  指定只进行预处理
#“hello.c”是源程序文件
#“-o”指定生成目标文件
#“hello.i”是预处理过程生成的目标文件

$gcc -S hello.i -o hello.S
#“-S”指定只进行到编译阶段
#“hello.i”是进行编译的源文件
#“-o”指定生成目标文件
#“hello.S”是编译生成的目标文件名

$gcc -c hello.S -o hello.o
#“-c”指定只进行到汇编阶段结束为止
#“hello.S”是进行汇编的源文件
#“-o”指定生成目标文件
#“hello.o”是编译生成的目标文件名。hello.o为二进制目标代码文件

$gcc hello.o -o hello
#该命令gcc之后无选项参数,表示对指定的源文件进行编译,直到输出执行文件(示例中的源文件为hello.o,输出的执行文件hello)。

$./hello
#运行该可执行文件

在这里插入图片描述

函数库创建和使用

函数库一般分为静态库动态库两种。

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时运行链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的libc.so.6就是动态库。GCC在编译时默认使用动态库。

  • 静态库创建步骤一
    编辑源文件libhello.h
#ifndef _libhello_H_
#define _libhello_H_
void print_hello(void);
#endif

编辑源文件libhello.c

#include <stdio.h>
void print_hello(void)
{
   printf(“hello library\n”);
}
  • 静态库创建步骤二
    生成目标文件libhello.o
$gcc –c libhello.c –o libhello.o
  • 静态库创建步骤三
    使用ar命令创建静态库libhello.a
$ar –rc libhello.a libhello.o
$file libhello.a
  • 静态库的使用
    编辑测试文件usehello.c
    生成可执行文件usehello_static
$gcc –o usehello_static usehello.c libhello.a
  • 运行
$./usehello_static

动态库的创建

  1. 编辑源文件libhello.h,libhello.c
  2. 生成共享库目标文件libhello.o
 $gcc –fPIC –Wall –g
  1. 生成共享库目标文件libhello.o
$gcc –fPIC –Wall –g–c libhello.c –o libhello.o 
  1. 编译共享库libhello.so.1.0
 $gcc –g –shared –W1,-soname,libhello.so –o libhello.so.1.0 libhello.o 
 $file libhello.so.1.0 
  1. 创建共享库的符号连接
 $ln –s libhello.so.1.0 libhello.so
  1. 动态库的使用
    编辑测试文件usehello.c
    生成可执行文件usehello_dy
$gcc –g –o usehello_dy usehello.c –lhello –L ./ 
  1. 运行
$LD_LIBRARY_PATH=$(pwd)  ./usehello_dy

静态库与共享库的区别
可执行文件大小不同

  • 当多个进程使用同一共享库,将共享库中存放的可执行代码在内存共享;
  • 静态库将直接加载到可执行文件。

共享库可很大程度上节约系统内存。
共享库发生错误,只需要修改当前共享库,无需重新编译每个使用该库的程序

多个源文件编译

$gcc foo1.c foo2.c -o foo

解释:对于源文件不止一个情况,GCC编译过程仍然按照预处理、编译、汇编和链接的过程依次进行。因此,上面这条命令相当于依次执行如下三条命令。

$gcc -c foo1.c -o foo1.o 
$gcc -c foo2.c -o foo2.o 
$gcc foo1.o foo2.o -o foo

GCC选项汇总
在这里插入图片描述

GCC选项——-I dir选项
在当前路径下有文件hello1.c ,“/root/work/gcc/”目录下有my.h:
编译命令:

$gcc hello1.c -I /root/work/gcc/ -o hello1

GCC选项——==-L dir ==选项
“-L dir”的功能与“-I dir”类似,能够在库文件的搜索路径列表中添加dir目录。例如有程序hello2.c需要用到目录“/root/work/gcc/lib/” /下的一个动态库libxch.so,则只需键入如下命令即可:

$gcc hello2.c –L root/work/gcc/lib/ hello2

注意:“-I dir”和“-L dir”都只是指定了路径,而没有指定文件,因此不能在路径中包含文件名。

调试—GDB

GDB概述

对于Linux程序员来讲,GDB(GNU Debugger)通过与GCC的配合使用,为基于Linux的软件开发提供了一个完善的调试环境。
将调试符号插入到生成的二进制代码中的gcc编译

$gcc -g hello.c -o hello 

GDB调试举例

#【GDBTest.c】
#include <stdio.h>
void sum(int m);
int main()
{
   int i,n=0;
   sum(50);
   for(i=1; i<=50; i++)
   {
      n += i;
   }
   printf("The sum of 1-50 is %d \n", n );
   return(0);
}
void sum(int m)
{
   int i,n=0;
   for(i=1; i<=m;i++) n += i;
   printf("The sum of 1-m is %d\n", n);
}
  1. 首先使用GCC对test.c进行编译。
    注意:GDB进行调试的是可执行文件,而不是如“.c”的源代码,因此,需要先通过GCC编译生成可执行文件才能用GDB进行调试。编译时一定要加上选项“-g”,这样编译出的可执行代码中才包含调试信息,否则Gdb无法载入该可执行文件。
$gcc -g test.c -o test
  1. 进入GDB调试环境
$gdb test

在这里插入图片描述

  1. 查看程序源文件
    (gdb) list
    在这里插入图片描述

  2. 设置断点
    (gdb) break 6
    在这里插入图片描述

  3. 查看断点设置情况
    (gdb) info b
    在这里插入图片描述

  4. 运行程序
    (gdb) run
    在这里插入图片描述

  5. 查看变量值
    (gdb) print n
    (gdb) print i
    在这里插入图片描述

  6. 单步运行
    (gdb)next
    在这里插入图片描述
    (gdb)step

  7. 恢复程序运行
    (gdb) c
    在这里插入图片描述

GDB调试选项

  • GDB的命令可以通过查看help进行查找
    (gdb) help
    (gdb) help data
    (gdb) help call
  • GDB中的命令主要分为以下几类:
    1.工作环境相关命令;
    2.设置断点与恢复命令;
    3.源代码查看命令;
    4.查看运行数据相关命令及修改运行参数命令。
  • 工作环境相关命令
    在这里插入图片描述
  • 断点设置与恢复命令
    在这里插入图片描述
    1.函数断点
    (gdb) break sum
    2.条件断点
    (gdb) break 8 if i= =10
  • 源码查看相关命令
    在这里插入图片描述
  • 查看运行数据相关命令
    在这里插入图片描述
  • 修改运行参数相关命令
    1.修改运行时的参数,并使该变量按照用户当前输入的值继续运行。设置方法:在单步执行的过程中,键入命令“set 变量=设定值”
    在这里插入图片描述

GNU make

make简介

Make工程管理器

  1. 一个“自动编译管理器”
  • GNU的make能够使整个软件工程的编译、链接只需要一个命令就可以完成。
  • “自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量。
  1. Linux程序员必须学会使用GNU make 来构建和管理自己的软件工程。

常用的make命令行选项
在这里插入图片描述

Makefile

  1. Make在执行时需要一个命名为Makefile的文件
  2. Makefile是一个文本形式的数据库文件
  • 描述了整个工程的编译、链接等规则
  • 工程中的哪些文件需要编译,具体怎么编译
  • 需要创建哪些库文件以及如何创建这些库文件
  • 如何产生我们最后想要得到的可执行文件
  1. make在执行时就会找到Makefile文件

Makefile实例
在这里插入图片描述

makefile的编写

Makefile术语

  1. 规则
    用于说明如何产生一个或者多个目标文件
    规则格式:
target: dependency
	COMMAND

实例
在这里插入图片描述
注意:在command前面有tab,这个不可缺少

  • 伪目标
    Makefile中把那些没有任何依赖只有执行动作的目标称为“伪目标”
    实例
    在这里插入图片描述
    “.PHONY”将“clean”目标声明为伪目标
  • 变量
    在这里插入图片描述
    在这里插入图片描述
  1. Makefile其他变量
    除前面介绍的用户自定义变量(如OBJS、HDRS)外,make也允许使用环境变量、自动变量和预定义变量。
  • 环境变量——工作环境的相关变量,如路径、时间等。

  • 自动变量——用于代表编译语句中出现的目标文件和依赖文件,并且具有本地含义。

  • 预定义变量——通常指编译器、汇编器的名称及其编译选项。

  1. 系统默认自动变量
    在这里插入图片描述
    自动变量使用示例
    在这里插入图片描述

  2. 预定义变量
    在这里插入图片描述

  3. 隐式规则
    Make会自动搜索隐式规则目录来确定如何生成文件。
    举例
    在这里插入图片描述
    常见隐式规则
    在这里插入图片描述

  4. 模式规则
    模式规则是用来定义相同处理规则的多个文件的。它不同于隐式规则,隐式规则仅仅能够用make默认的变量来进行操作,而模式规则还能引入用户自定义变量,为多个文件建立相同的规则,从而简化Makefile的编写。
    模式规则的格式类似于普通规则,这个规则中的相关文件前必须用“%”标明。
    在这里插入图片描述
    在这里插入图片描述

  5. Makefile注释
    makefile文件中只有行注释,其注释用“#”字符,就像C语言中的“//”,如果要在makefile文件中使用“#”字符,可以使用“\”进行转义,即“#”。

  6. Makefile-函数

$(subst  from,to,text)
功能:在文本text中使用to替换每一处form。
举例:$(subst  ee,EE,feet on the street)
$(patsubst  pattern,replacement,text)
功能:寻找text中符合pat的字,并repl替换它们。
举例:$(patsubst  %.c,%.o,x.c.c  bar.c)
$(filter pattern……,text)
功能:返回在text中有空格隔开并匹配pat的字。
举例:sources := foo.c bar.c bar.s ug.h
		         foo:$(sources)
			    cc  $(filter %.c %.s,$(sources))  -o  foo
$(filter-out  pattern……,text)
$(wildcard pattern)
功能:寻找与格式匹配且文件存在的文件名
举例:$(wildcard  %.c  ../src/%.c)
$(addprefix  prefix,names……)
功能:将prefix附加在每一个独立文件名的前面。
举例:$(addprefix  src/,foo bar)


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FPGA自学笔记——设计与验证JMB FPGA(可编程逻辑门阵列)是一种可编程的硬件平台,可以实现各种数字电路的设计与验证。本文将简要介绍使用FPGA自学设计与验证JMB(低功耗、高效能、集成度高的多媒体芯片)的过程。 首先,我们需要了解JMB的功能和特性。JMB是一种面向多媒体应用的芯片,具备低功耗、高效能和高集成度的优势。我们需要详细研究JMB的硬件架构和内部模块,包括处理器核、存储器模块、图像和音频处理模块等。 接下来,我们可以使用FPGA开发板来设计和验证JMB。首先,我们需要熟悉FPGA设计工具,例如Vivado或Quartus等。这些工具提供了图形化界面和硬件描述语言(HDL)等设计方法。我们可以使用HDL编写JMB的功能模块,并将其综合为FPGA可执行的位流文件。 在设计完成后,我们需要验证JMB的功能和性能。我们可以使用仿真工具(例如ModelSim或ISE Simulator)来模拟JMB在不同情况下的行为。通过设计测试程序并运行仿真,我们可以验证JMB的各个模块是否正确地工作,是否满足设计要求。 在验证完成后,我们可以将位流文件下载到FPGA开发板中进行智能芯片的物理实现和测试。通过与外部设备的连接以及相关测试程序的运行,我们可以验证JMB在实际硬件中的功能和性能。 总结起来,学习FPGA设计与验证JMB,我们需要熟悉JMB的硬件架构和内部模块,并使用FPGA开发工具进行设计与验证。通过仿真和物理实现测试,我们可以验证JMB的功能和性能。这些过程需要理论知识和实践经验的结合,希望这些笔记能够给你提供一些参考和指导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邪三一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值