[C++系列] UNIX高级编程 day02 静态链接 动态链接 环境变量 协议 接口
in C/C++ with 0 comment

[C++系列] UNIX高级编程 day02 静态链接 动态链接 环境变量 协议 接口

in C/C++ with 0 comment

回忆昨天内容:
一、计算机的框架
二、操作系统
什么是?操作系统的内容,操作系统的分类
三、计算机语言的发展史
预处理、编译、汇编、链接、加载

今天的内容:
一、大型软件的组织架构
研发团队 不是个人英雄主义
NIH综合症

设计一个工程

楼房 画图纸 标注参数 门 尺寸 材料 颜色
窗户 尺寸 材料
用户规定
尺寸 材料 颜色
盖楼
门的加工厂
窗户的加工厂
规则就是协议
协议的使用者 协议的实现者

协议就要写到书面。在c语言中,将协议写在.h文件中。

c语言的头文件中包含哪些内容?
1、头文件卫士
2、文件的包含
3、宏定义
4、函数的声明
5、类型的定义
6、变量的声明

变量的定义和声明的区别
变量定义是需要为变量分配空间的。
变量的声明只是扩充变量的作用域,并不为变量分配空间。

变量的作用域?

实现头文件中声明的函数的程序 .c
举例说明: 两个数的加、减、乘、除运算。
pmath文件夹
pmath.h
padd.c
pmul.c
main.c
1、编译的基本单位是源文件,不是函数。
2、在编译的时候,只是做语法的检测。

补充
nm 二进制文件
T 代表的是在二进制文件中有这些函数的实现代码。指令
U 代表的是在这个二进制文件中,使用到了这个函数,但是没有这个函数的实现代码。
pmath$nm pmul.o
0000000c T pdiv
00000000 T pmul
pmath$nm padd.o
00000000 T padd
0000000e T psub
pmath$nm main.o
00000000 T main

     U padd
     U pmul
     U printf

链接就是将二进制文件的代码合并。
刚才这种链接发生在编译生成可执行文件的时候,称这种链接为静态链接

还有一种链接发生在代码加载到内存以后。这种链接称为动态链接。(延迟绑定)

main函数和用户自定义的函数有区别吗?
真正的编程中,我们需要理清函数之间的关系。调用与被调用的关系。

二、静态库文件的制作和使用
静态库文件的命名 lib库名.a
静态库的制作
1、将需要添加到静态库的源文件编译为目标文件
pmath$ls
padd.c pmath.h pmul.c
pmath$gcc -c *.c
pmath$ls
padd.c padd.o pmath.h pmul.c pmul.o

2、将第一步生成的目标文件打包到静态库文件
pmath$ar -r librmath.a *.o
ar: creating librmath.a
pmath$ls
librmath.a padd.o pmul.c
padd.c pmath.h pmul.o

3、使用静态库文件链接生成可执行文件
day02$gcc -c main.c
day02$ls
main.c main.o pmath 笔记 笔记~
day02$gcc main.o -Lpmath -lrmath
day02$ls
a.out main.c main.o pmath 笔记 笔记~

-L路径 静态库文件所在的路径
-l库名 指定静态库的名字

补充更多的实例
-I路径 将路径添加到系统指定的头文件的搜索路径
链接器搜索库文件的路径默认是/usr/lib 或者/lib
可以使用-L路径指定链接器的搜索路径。

标准c库,怎么没见到-lc

libc.so -lc

三、环境变量初级入门
操作系统需要为程序的运行提供环境。环境通过变量来实现。那么这些变量就是环境变量。
对于我们研究的是在bash下的环境变量。

我们在bash中和操作系统打交道。
如何察看bash中的环境变量?
env

HOME=/home/tarena
环境变量的格式
name=value
千万记住 =的两边不能出现空格

取出环境变量的值:
$环境变量的名字

设置环境变量的值:
export 环境变量的名字=环境变量的值
环境变量只在当前的bash中启作用。

系统为我们提供好的环境变量。
PS1 PATH
PS1 显示提示符的信息

~ 用户工作主目录
pmath$echo $PS1
W$
《鸟哥私房菜》
bash在启动的时候,需要执行一个bash脚本程序。可以在这个脚本文件里设置bash启动后的环境变量。这个脚本文件就是~/.bashrc文件。

PATH
当我们在bash下输入linux命令的时候,到PATH环境变量指定的路径下找这个命令,如果找到执行,找不到到下一个路径中找,找到执行,找不到继续到下一个,如果找到最后都找不到,报错。

/home/tarena/workdir/Android2.3/android-source/jdk1.6.0_16/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/home/tarena/workdir/linux-x86/sdk/android-sdk_eng.root_linux-x86/tools
需要将当前路径添加到PATH环境变量的指定的路径中
/home/tarena/workdir/Android2.3/android-source/jdk1.6.0_16/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/home/tarena/workdir/linux-x86/sdk/android-sdk_eng.root_linux-x86/tools:.
export PATH=$PATH:.

四、动态库的制作和使用
动态库的命名 lib库名.so 共享库

1、将需要添加到动态库的源文件编译为目标文件(与位置无关的目标文件)
pmath$ls
padd.c pmul.c
pmath$gcc -fPIC -c *.c
pmath$ls
padd.c padd.o pmul.c pmul.o

-fPIC 编译源文件的时候,将源文件编译为与位置无关的目标文件

2、将第一步生成的目标文件打包到动态库文件
pmath$gcc -shared -o libsmath.so *.o
pmath$ls
libsmath.so padd.c padd.o pmul.c pmul.o

3、将源文件和动态库文件链接,形成可执行文件
day02$gcc main.o -Lpmath -lsmath
day02$ls
a.out main.c main.o pmath 笔记 笔记~

出错了!!!

day02$a.out
a.out: error while loading shared libraries: libsmath.so: cannot open shared object file: No such file or directory

造成这个错误的原因。加载器找不到libsmath.so这个文件
如何知道a.out依赖哪些动态库?
day02$ldd a.out

linux-gate.so.1 =>  (0xb774b000)
libsmath.so => not found
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb758f000)
/lib/ld-linux.so.2 (0xb774c000)

解决办法是让加载器能找到我的动态库文件
1、加载器的默认路径是/usr/lib 或者 /lib
2、用环境变量指定加载器的搜索路径
LD_LIBRARY_PATH
这个环境变量内容的格式和PATH相同

总结:
一、大型软件的组织
编译的基本单位
协议 接口
头文件中包含的内容
静态链接
框架
二、静态库的制作和使用
三个步骤
三、环境变量
四、动态库的制作和使用

Responses