LInux网络编程
LInux下的GCC编译工具集
GCC简介
GCC的C编辑器时gcc,命令格式为:
gcc [options] file...
GCC的默认扩展名策略如下所示
编译程序的基本知识
GCC编译器对程序的编译分为四个阶段:预编译,编译和优化,汇编,链接。
源文件:通常指存放可编辑代码的文件
目标文件:指经过编译器的编译生成的CPU可识别的二进制代码,但是函数过程没有相关的指示和声明。
可执行文件:目标文件与相关的库链接后的文件,可执行。
预编译过程中将程序引用的头文件包含进源代码中,并对一些宏进行替换
编译过程将用户可识别的语言转化为处理器可识别的操作码
单个文件编译成可执行文件
Linux下编译单个文件十分简单,直接使用gcc命令后加上要编译的C语言的源文件,GCC会自动生成a.out文件。
$gcc hello.c
将生成默认的文件名a.out
如果希望生成指定的可执行文件名,选项-o可以使编译程序生成指定文件名,例如将上述程序编译输出一个名为test的执行程序
$gcc -o test hello.c
编译生成目标文件
目标文件是指经过编译器编译生成的二进制代码,因为其中一些函数过程没有相关的指示和说明,目标文件不能执行。
很多时候要生成中间文件以便不同的编译目标
GCC的-c选项用于生成目标文件,这一选项将源文件生成目标文件,而不是可执行文件。默认情况下生成的目标文件的文件名与源文件的名称一样,只是扩展名为.o。
$gcc -c hello.c
这个命令会生成一个名字为hello.c的目标文件。如果要生成指定的文件名,使用-o选项。下面的命令将源文件hello.c编译成目标文件,文件名为test.o
$gcc -c -o test.o hello.c
一条命令编译多个源文件,生成目标文件
$gcc -c file1.c file2.c file3.c
多文件编译
GCC可以自动编译链接多个文件,不管是目标文件还是源文件,都可以使用一个命令编译到一个可执行文件中.
源文件string.c
1 #define ENDSTRING '\0'
2 int StrLen(char *string)
3 {
4 int len =0;
5 while(*string++ != ENDSTRING)
6 len++;
7 return len;
8 }
源文件main.c
#include<stdio.h>
extern int StrLen(char* str);
int main(void)
{
char src[]="Hello Dynamic";
printf("string length is:%d\n",StrLen(src));
return 0;
}
编译运行
下面是进行编译的命令行
$gcc -o test string.c main.c
也可以先将源文件编译成目标文件,然后进行链接
预处理
预处理就是将源文件中的头文件包含进源文件中
$gcc -E string.c
如果使用中间名需要使用选项-o
编译成汇编语言
生成汇编语言的命令行
$gcc -S string.c
生成和使用静态链接库
静态库是obj文件的一个集合,通常静态库以“.a"为后缀。静态库由程序ar生成,现在大多数程序都在使用动态库。
静态库的优点是可以在不用重新编译程序库代码的情况下进行程序的重新链接,
生成静态链接库
生成静态库,命令为
$ar -rcs libstr.a string.o
使用静态链接库
gcc链接时使用库函数和一般的obj文件的形式是一致的,
$gcc -o main.c libstr.a
也可以使用"-l 库名"进行,库名是不包含函数库和扩展名的字符串。例如编译main.c链接静态库libstr.a的命令可以修改为:lib str .a->str
$gcc -o test main.c -lstr
上面的命令将在系统默认的路径下查找str函数库,并把它链接到要生成的目标程序上。可能系统会提示无法找到库文件str,这是由于str库函数没有在系统默认的查找路径下,需要显示的指定库函数的路径,例如库文件和当前编译文件在同一目录下:
$gcc -o test main.c -L./ -lstr
使用-l时,-o选项要出现在-l链接的库名称之前,否则-o会错判目标
生成动态链接库
生成动态链接库的命令很简单,使用选项-fPIC选项或者-fpic选项的作用是使得gcc生成的代码是位置无关的
$gcc -shared -Wl,-soname,listr.so -o libstr.so.l string.c
其中选项"-soname,libstr.so"表示生成动态链接库时的别名是libstr.so
"-o libstr.so.l"选项则表示是生成名字为libstr.so.l的实际动态链接库文件
"-shared"告诉编译器生成一个动态链接库
生成的动态链接库一般放到系统默认的动态链接库的搜索路径下,通常有/lib, /usr/lib, /user/local/lib
动态链接库的配置
在运行的程序中使用动态链接库,需要指定系统的动态链接库搜索的路径,让系统找到运行所需的动态链接库在可以。
系统的配置文件/etc/ld.so.conf是动态链接库的搜索路径配置文件。在这个文件夹中,存放着可被Linux共享的动态链接库所在目录的名字(系统目录/lib,/usr/lib除外),多个目录名间 以空白字符或者冒号或逗号进行分隔。
查看系统中的动态链接库配置文件中的内容
[root@bogon ~]# cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
动态链接库管理命令
为让新增加的动态链接库能够被系统共享,需要运行动态链接库的管理命令ldconfig。ldconfig的命令作用是在系统的默认搜索路径,和动态链接库配置文件中列出的目录里搜索动态链接库,创建动态链接库装入程序需要的连接以及缓存文件。
搜索完毕后,将结果写入缓存文件/etc/ld/.so.cache中,文件中保存的是已经排列好顺序的动态链接库名字列表。
如果希望知道系统中有哪些数据链接库,可以使用ldconfig的-p选项来列出缓存文件中的动态链接库列表。
使用ldconfig命令,默认情况下并不将扫描的结果输出。使用-v选项将会ldconfig在运行过程中扫描到的目录和共享库信息输出到终端,用户可以看到运行的结果和中间的信息。
使用动态链接库
在编译数据时,使用动态和静态链接库是一致的,使用"-l 库名"的方式。
$gcc -o test main.c -L./ -lstr
-L指定动态链接库的路径。但是编译时链接动态链接库和运行时使用动态连接板库的概念是不同的。
在运行时,程序链接的动态链接库需要在系统目录下才行,有以下几种方法
- 将动态链接库的目录加入到环境变量LD_LIBRARY_PATH中实现
- 另一种方式是使用ld-Linnux.so.2来加载路径
动态加载库
动态加载库和一般的动态链接库不同的是,一般动态链接库在程序启动的时候就要寻找动态库,找到库函数;而动态加载库可以使用程序的方式来控制什么时候加载。动态加载库主要有函数
- dlopen()
- dlerror()
- dlsym()
- dlclose()
-
打开动态库dlopen()函数
函数dlopen()按照用户指定的方式打开动态链接库其中参数filename为动态链接库的文件名,flag为打开方式,一般为RTLD_LASY,函数的返回值为库的指针
void * dlopen(const char *filename, int flag);
例如,下面的代码使用dlopen代开当前目录下的动态库libstr.so
void *phandle = dlopen("./libstr.so",RTLD_LAZY);
-
获得函数指针dlsym()函数
获得动态链接库中指定函数的指针,然后使用这个函数指针进行操作
void * dlsym(void *handle,char *symbol);
handle为dlopen()打开动态库后返回的句柄,参数symble为函数的名称,返回值为函数指针