嵌入式Linux2月11日学习笔记

19.头文件.h的作用

编译器需要了解函数和类型的定义,才能生成正确的可执行程序,所以需要头文件来声明函数,例如我定义了一个函数int add(int a,int b),我需要在头文件内声明这个函数,这样编译器可以检测我传入的参数是否符合这个函数的要求。.c文件相当于定于(实现)这个函数的要求

20.头文件的区别

#include <stdio.h>

#include "sub.h"

对于使用<>的头文件,会在编译工具链里去寻找默认的指定的路径里的头文件,而””的头文件,会在当前文件夹里去寻找。

21.GCC 编译过程

一个C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)和链接(linking)等 4 步才能变成可执行文件。

常用编译选项

gcc -E -o hello.i hello.c

gcc -S -o hello.s hello.i

gcc -c -o hello.o hello.s

gcc -o hello hello.o

通过不同的 gcc 选项可以控制这些过程:

21.1预处理(.c->.i)

C/C++源文件中,以“#”开头的命令被称为预处理命令,如包含命令“#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些东西输出到一个“.i”文件中等待进一步处理

21.2 编译(.i->.s语法错误是在编译过程检测出来的)

编译就是把 C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码,所用到的工具为 cc1(它的名字就是 cc1,x86 有自己的 cc1 命令,ARM 板也有自己的cc1 命令)。

21.3 汇编(.s->.o)

汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux 系统上一般表现为 ELF 目标文件(OBJ 文件),用到的工具为 as。x86 有自己的 as 命令,ARM 版也有自己的 as 命令,也可能是 xxxx-as(比如 armlinux-as)。

“反汇编”是指将机器代码转换为汇编代码,这在调试程序时常常用到。

21.4 链接(.o->APP)

链接就是将上步生成的 OBJ 文件和系统库的 OBJ 文件、库文件链接起来,最终生成了可以在特定平台运行的可执行文件,用到的工具为 ld 或 collect2。

22.怎么编译多个文件

一起编译、链接: gcc -o test main.c sub.c

分开编译,统一链接:

gcc -c -o main.o main.c gcc -c -o sub.o sub.c gcc -o test main.o sub.o

在编译多个c文件时,可以单独把各个的c文件编译成机器文件(gcc -c -o main.o main.c),最后在统一链接为APP(gcc -o test main.o sub.o),这样在后续修改时,不用每一个文件都在编译一次,提高效率。

23.静态库和动态库

23.1概念

静态库(Static Library)

静态库是一个文件,包含了代码和数据。当程序被编译或链接时,这个库会被直接嵌入到目标文件中。使用静态库不需要额外的操作,它会永久地存在于可执行文件中。

动态库(Dynamic Library)

动态库也是一个包含代码和数据的文件,但它是在程序运行时通过特定的调用(如dlopen)加载到内存中的。与静态库不同,动态库不会被直接嵌入到可执行文件中,而是以共享的方式加载。

静态库的优点:一次编译多次使用,节省时间;没有依赖性问题,程序不会因缺少库文件而崩溃。

静态库的缺点:增加可执行文件的体积,因为会复制库内容到目标文件中;不支持版本控制和动态更新,如果需要更改库,必须重新编译整个程序。

动态库的优点:支持模块化设计,便于维护和扩展,只需重新编译或更新特定部分;允许版本控制和动态更新,可以在不停机的情况下升级库;节省内存,按需加载代码和数据,适合资源受限的环境;支持延迟绑定,减少启动时间。

动态库的缺点:可能需要更多的管理和维护,确保所有依赖的动态库都正确地加载和调用;如果某个动态库版本不兼容或被破坏,可能导致程序崩溃或功能异常。

23.2配置静态库

gcc -c -o main.o main.c

gcc -c -o sub.o sub.c

ar crs libsub.a sub.o sub2.o sub3.o(可以使用多个.o 生成静态库)

gcc -o test main.o libsub.a (如果.a 不在当前目录下,需要指定它的绝对或相对路径)

可以理解为将多个.o文件整合到一起,成为libsub.a,方便后续编译

23.3配置动态库

gcc -c -o main.o main.c

gcc -c -o sub.o sub.c

gcc -shared -o libsub.so sub.o sub2.o sub3.o(可以使用多个.o 生成动态库)

gcc -o test1 main.o -lsub -L ./

gcc -o test1 main.o libsub.so          这两句性质一样

动态库可以理解为调用api,他不需要嵌入到执行文件内,可以节省空间,但需要配置相应的环境变量。

编译为可执行文件后还需要配置环境变量,因为libsub.so是在当前目录,执行app是是在默认的工具链的lib库内寻找,所以需要配置环境变量。

第2步 配置环境变量:

先把 libsub.so 放到 Ubuntu 的/lib 目录,然后就可以运行 test 程序。如果不想把 libsub.so 放到/lib,也可以放在某个目录比如/a,然后如下执行:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a (临时环境变量)

./test

23.4 常用选项

echo 'main(){}'| gcc -E -v - // 它会列出头文件目录、库目录(LIBRARY_PATH)

gcc -E main.c // 查看预处理结果,比如头文件是哪个

gcc -E -dM main.c > 1.txt // 把所有的宏展开,存在 1.txt 里

gcc -Wp,-MD,abc.dep -c -o main.o main.c // 生成依赖文件 abc.dep,后面 Makefile 会用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值