问题
-
请说明可执行程序是如何被组装的?
-
请说明gcc编译工具集中各软件的用途,了解EFF文件格式,汇编语言格式。
-
了解实际程序是如何借助第三方库函数完成代码设计。
一、可执行程序是如何被组装的
1.用gcc生成静态库和动态库
1.先创建一个作业目录,保存本次练习的文件。
2.然后用 vim编辑器编辑、生成所需要的 3 个文件。
创建文件:vim+文件名
进入vim编辑页面,键入i进入输入模式,分别敲完以下程序代码
程序 1: hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
//hello.h为该函数库的头文件
程序 2: hello.c
#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
//hello.c是源程序,含公用函数 hello,将在屏幕上输出"Hello XXX!"。
程序 3: main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
//main.c为测试库文件的主程序,在主程序中调用了公用函数 hello。
按ESC退出输入模式,shift+:进入命令模式。键入wq=保存退出。
3.将 hello.c 编译成.o 文件。
无论静态库,还是动态库,都是由.o 文件创建的。因此,必须将源程序 hello.c 通过 gcc 先编译成.o 文件。
//在系统提示符下键入以下命令得到 hello.o 文件。
# gcc -c hello.c
#
版本ubuntu16,从hello.c 生成 hello.o,需要将 gcc -c hello.c 换成 gcc -fpic -c hello.c
//我们运行 ls 命令看看是否生存了 hello.o 文件。
#ls
hello.c hello.h hello.o main.c
#
//在 ls 命令结果中,我们看到了 hello.o 文件,本步操作完成。
4.由.o 文件创建静态库。
静态库文件名= lib 前缀+静态库名+扩展名为.a。
//创建静态库文件libmyhello.a:
#ar -crv libmyhello.a hello.o
#
//同样运行 ls 命令查看结果:
#ls
hello.c hello.h hello.o libmyhello.a main.c
#
//ls 命令结果中有 libmyhello.a
5.在程序中使用静态库。
如何使用静态库内部的函数呢?
只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后用 gcc 命令生成目标文件时指明静态库名,gcc 将会从
静态库中将公用函数连接到目标文件中。
方法一:
#gcc -o hello main.c -L. –lmyhello
//自定义的库时,main.c 还可放在-L.和 –lmyhello 之间,不能之后,否则会提示 myhello 没定义.
//系统的库时,如 g++ -o main(-L/usr/lib) -lpthread main.cpp就不出错。
方法二:
#gcc main.c libmyhello.a -o hello
方法三:
//先生成 main.o:
gcc -c main.c
//再生成可执行文件:
gcc -o hello main.o libmyhello.a
//动态库连接时也可以这样做。
# ./hello
Hello everyone!
#
//删除静态库文件试试公用函数 hello 是否真的连接到目标文件 hello 中了。
# rm libmyhello.a
rm: remove regular file `libmyhello.a'? y
# ./hello
Hello everyone!
#
//程序照常运行,静态库中的公用函数已经连接到目标文件中了。
我们继续看看如何在 Linux 中创建动态库。我们还是从.o 文件开始。
6.如何在 Linux 中创建动态库,由.o 文件创建动态库文件。
动态库文件名:前缀 lib+文件名+扩展名.so。
//用 gcc 来创建动态库。
//在系统提示符下键入以下命令得到动态库文件 libmyhello.so。
# gcc -shared -fPIC -o libmyhello.so hello.o (-o 不可少)
#
//我们照样使用 ls 命令看看动态库文件是否生成。
# ls
hello.c hello.h hello.o libmyhello.so main.c
#
7.在程序中使用动态库;
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明动态库名进行编译。
//先运行 gcc 命令生成目标文件,再运行它看看结果。
# gcc -o hello main.c -L. -lmyhello
//或 #gcc main.c libmyhello.so -o hello 不会出错(没有 libmyhello.so 的话,会出错)
//但是这种接下来./hello 会提示出错
//虽然连接时用的是当前目录的动态库,但是运行时,是到/usr/lib 中找库文件的
//将文件 libmyhello.so 复制到目录/usr/lib 中就 OK 了