GCC处理静态库与动态库与各种命令用途、小游戏体验

GCC处理静态库与动态库与各种命令用途、小游戏体验

一、用gcc处理静态库与动态库

1、用gcc生成.a静态库和.so的动态库

(1)编辑所需要的程序hello.h,hello.c,main.c

在写代码之前先创建一个目录保存此次作业

nivechen@nivechen-virtual-machine:~$ mkdir homework3.1
nivechen@nivechen-virtual-machine:~$ cd homework3.1

程序代码如下:
hello.h文件

#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H

hello.c文件

#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}

main.c文件

#include "hello.h"
int main()
{
hello("everyone");
return 0;
}

(2)将hello.c文件编译成hello.o文件

nivechen@nivechen-virtual-machine:~/homework3.1$ gcc -c hello.c
nivechen@nivechen-virtual-machine:~/homework3.1$ ls   //通过ls命令查看hello.o文件确实存在
hello.c  hello.h  hello.o  main.c

(3)由.o文件创建静态库

nivechen@nivechen-virtual-machine:~/homework3.1$ ar -crv libmyhello.a hello.o
a - hello.o
nivechen@nivechen-virtual-machine:~/homework3.1$ ls
hello.c  hello.h  hello.o  libmyhello.a  main.c

(4)使用静态库文件,创建可执行程序,并运行

nivechen@nivechen-virtual-machine:~/homework3.1$ gcc main.c libmyhello.a -o outputhello1
nivechen@nivechen-virtual-machine:~/homework3.1$ ls
hello.c  hello.h  hello.o  libmyhello.a  main.c  outputhello1
nivechen@nivechen-virtual-machine:~/homework3.1$ ./outputhello1
Hello everyone!

我们删除静态库文件看看公用函数hello是否真的已经连接到目标文件中

nivechen@nivechen-virtual-machine:~/homework3.1$ rm libmyhello.a
nivechen@nivechen-virtual-machine:~/homework3.1$ ls
hello.c  hello.h  hello.o  main.c  outputhello1 
nivechen@nivechen-virtual-machine:~/homework3.1$ ./outputhello1
Hello everyone!

注:上面可以清晰看出静态库文件已经被删除,但是程序还是正常的运行,因为静态库文件在编译时就会连接到目标文件中,程序运行不需要再使用静态库文件。下面我们看动态库文件与之的区别。

(5)由.o文件创建动态库文件

nivechen@nivechen-virtual-machine:~/homework3.1$ gcc -shared -fPIC -o libmyhello.so hello.o
nivechen@nivechen-virtual-machine:~/homework3.1$ ls
hello.c  hello.h  hello.o  libmyhello.so  main.c  outputhello1

(6)使用动态库文件,创建可执行程序,并运行

nivechen@nivechen-virtual-machine:~/homework3.1$ gcc main.c libmyhello.so -o outputhello2
nivechen@nivechen-virtual-machine:~/homework3.1$ ls
hello.c  hello.h  hello.o  libmyhello.so  main.c  outputhello1  outputhello2
nivechen@nivechen-virtual-machine:~/homework3.1$ ./outputhello2
./outputhello2: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory //这里发现不能正常运行可执行文件outputhello2,这是因为虽然连接时用的是当前目录的动态库,但是运行时,是到/usr/lib 中找库文件的,我们将文件 libmyhello.so 复制到目录/usr/lib 中就可以正常运行了。
nivechen@nivechen-virtual-machine:~/homework3.1$  mv libmyhello.so /usr/lib 
nivechen@nivechen-virtual-machine:~/homework3.1$ ./outputhello2
Hello everyone!

2、.a与.so库文件的生成与使用

(1)编写需要用到的文件A1.C,A2.C,A.h,test.c

首先还是先建一个目录存放该练习的文件

nivechen@nivechen-virtual-machine:~$ mkdir homework3.2
nivechen@nivechen-virtual-machine:~$ cd homework3.2
nivechen@nivechen-virtual-machine:~/homework3.2$ gedit A1.c
nivechen@nivechen-virtual-machine:~/homework3.2$ gedit A2.c
nivechen@nivechen-virtual-machine:~/homework3.2$ gedit A.h
nivechen@nivechen-virtual-machine:~/homework3.2$ gedit test.c
nivechen@nivechen-virtual-machine:~/homework3.2$ ls
A1.c  A2.c  A.h  test.c

通过ls命令可以看见我们创建的目录下面已经存在这四个文件,也可以在桌面打开文件,这里也可以看见四个文件已经存在

在这里插入图片描述

(2)生成.o文件

nivechen@nivechen-virtual-machine:~/homework3.2$ gcc -c A1.c A2.c
A2.o

(3)生成静态库.a文件

nivechen@nivechen-virtual-machine:~/homework3.2$ ar -crv libmyfile.a A1.o A2.o

(4)使用静态库文件,创建可执行程序,并运行

nivechen@nivechen-virtual-machine:~/homework3.2$ gcc -o output1 test.c libmyfile.a
nivechen@nivechen-virtual-machine:~/homework3.2$ ./output1
A1 print arg:1
A2 printf arg:test

(5)生成动态库.so文件

nivechen@nivechen-virtual-machine:~/homework3.2$ gcc -shared -fPIC -o libmyfile.so A1.o A2.o

注:.a和.so文件都是由.o文件生成的,所以这里不再生成.o文件,这里有多个.o文件,只需要依次写在后面即可。

(6)使用动态库文件,创建可执行程序,并运行

nivechen@nivechen-virtual-machine:~/homework3.2$ gcc -o output2 test.c libmyfile.so
nivechen@nivechen-virtual-machine:~/homework3.2$ sudo cp  libmyfile.so /usr/lib
[sudo] nivechen 的密码: 
nivechen@nivechen-virtual-machine:~/homework3.2$ ./output2
A1 print arg:1
A2 printf arg:test

注:我这里使用的cp命令,将libmyfile.so文件复制到/usr/lib下,上面用的mv,作用都差不多,cp是复制一份,mv是直接搬移过去。

3、对第一篇博客中由原来的一个x2x函数,扩展为两个函数,在进行相关静态库,动态库的操作

(1)编写相关函数sub1.c,sub2.c ,main.c,sub.h

nivechen@nivechen-virtual-machine:~/homework3.2$ gedit sub1.c
nivechen@nivechen-virtual-machine:~/homework3.2$ gedit sub2.c
nivechen@nivechen-virtual-machine:~/homework3.2$ gedit main.c
nivechen@nivechen-virtual-machine:~/homework3.2$ gedit sub.h

在这里插入图片描述

上图可以清楚看见编写的四个文件已经存在。

(2)生成相关的.o文件

nivechen@nivechen-virtual-machine:~/homework3.2$gcc -c main.c sub1.c sub2.c

在这里插入图片描述

(3)用ar工具,将x2x和x2y的目标文件生成一个.a文件

nivechen@nivechen-virtual-machine:~/homework3.2$ ar crv libmyfile1.a sub1.o sub2.o
a - sub1.o
a - sub2.o

在这里插入图片描述

(4)用gcc将main.o文件与生成的.a文件链接生成最终的可执行文件,并运行

nivechen@nivechen-virtual-machine:~/homework3.2$ gcc -o output3  main.o libmyfile1.a
nivechen@nivechen-virtual-machine:~/homework3.2$ ls
A1.c  A1.o  A2.c  A2.o  A.h  libmyfile1.a  libmyfile.a  libmyfile.so  main.c  main.o  output  output1  output2  output3  sub1.c  sub1.o  sub2.c  sub2.o  sub.h  test.c
nivechen@nivechen-virtual-machine:~/homework3.2$ ./output3
请输入两个整数
2
3
11.000000

(5)记录该可执行文件output3的大小

nivechen@nivechen-virtual-machine:~/homework3.2$ size output3
   text	   data	    bss	    dec	    hex	filename
   2094	    624	      8	   2726	    aa6	output3

(6)将x2x和x2y的目标文件生成一个.so文件

nivechen@nivechen-virtual-machine:~/homework3.2$ gcc -shared -fPIC -o libmyfile1.so sub1.o sub2.o
nivechen@nivechen-virtual-machine:~/homework3.2$ ls
A1.c  A2.c  A.h           libmyfile1.so  libmyfile.so  main.o  output1  output3  sub1.o  sub2.o  test.c

(7)用gcc将main.o文件与生成的.so文件链接生成最终的可执行文件,并运行

nivechen@nivechen-virtual-machine:~/homework3.2$ gcc -o output4  main.o libmyfile1.so
nivechen@nivechen-virtual-machine:~/homework3.2$ sudo cp libmyfile1.so /usr/lib
[sudo] nivechen 的密码: 
nivechen@nivechen-virtual-machine:~/homework3.2$ ./output4
请输入两个整数
2
3
11.000000

(8)记录该可执行文件output4的大小

nivechen@nivechen-virtual-machine:~/homework3.2$ size output4
   text	   data	    bss	    dec	    hex	filename
   2298	    656	      8	   2962	    b92	output4

(9)对比output3和output4这两个文件

 text	   data	    bss	    dec	    hex	filename
   2094	    624	      8	   2726	    aa6	output3
 text	   data	    bss	    dec	    hex	filename
   2298	    656	      8	   2962	    b92	output4

二、gcc编译的内部操作

1.gcc常见命令和内部处理

(1)创建一个新的目录

nivechen@nivechen-virtual-machine:~$ mkdir homework3.3
nivechen@nivechen-virtual-machine:~$ cd homework3.3

程序示例

nivechen@nivechen-virtual-machine:~/homework3.3$ gcc test1.c -o output1//这里一步到位的指令,现在我们来看看分步操作
nivechen@nivechen-virtual-machine:~/homework3.3$ ./output1
Hello World!

(2)预处理

nivechen@nivechen-virtual-machine:~/homework3.3$ gcc -E test.c -o test.i
nivechen@nivechen-virtual-machine:~/homework3.3$ ls
output1  test.c  test.i

注: test.i 文件中存放着 test.c 经预处理之后的代码。打开 test.i 文件。
也可以用 gcc -E test.c指令,这样会直接在命令行窗口中输出预处理后的代码. gcc 的-E 选项,可以让编译器在预处理后停止,并输出预处理结果。在本例中,预处理结果就是将stdio.h 文件中的内容插入到 test.c 中了。

(3)编译为汇编代码(Compilation)

nivechen@nivechen-virtual-machine:~/homework3.3$ gcc -S test.i -o test.s

(4) 汇编(Assembly)

nivechen@nivechen-virtual-machine:~/homework3.3$ gcc -c test.s -o test.o

(5)连接(Linking)

nivechen@nivechen-virtual-machine:~/homework3.3$ gcc test.o -o output2

(6)运行经过连接后产生的output2执行文件

nivechen@nivechen-virtual-machine:~/homework3.3$ ./output2
Hello World!

(7)用gcc相关命令连接动态库,并用size查看大小并记录

nivechen@nivechen-virtual-machine:~/homework3.3$ gcc test.c -o output3
nivechen@nivechen-virtual-machine:~/homework3.3$ ./output3
Hello World!

(8)用gcc相关命令连接静态库,并用size查看大小并记录

nivechen@nivechen-virtual-machine:~/homework3.3$ gcc -static test.c -o output4
nivechen@nivechen-virtual-machine:~/homework3.3$ ./output4
Hello World!

(9)用 ldd命令查看一个可执行程序依赖的共享库

nivechen@nivechen-virtual-machine:~/homework3.3$ ldd output3//动态库
	linux-vdso.so.1 (0x00007fff0898a000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f49da3d5000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f49da9c8000)
nivechen@nivechen-virtual-machine:~/homework3.3$ ldd output4//静态库文件
	不是动态可执行文件

(10)对比两个可执行程序

nivechen@nivechen-virtual-machine:~/homework3.3$ size output3
   text	   data	    bss	    dec	    hex	filename
   1515	    600	      8	   2123	    84b	output3
nivechen@nivechen-virtual-machine:~/homework3.3$ size output4
   text	   data	    bss	    dec	    hex	filename
 743329	  20876	   5984	 770189	  bc08d	output4

可以看出链接静态库的执行文件中text,data,bss,dec代码尺寸都变大了

(11)ELF相关指令

(1)使用 readelf -S 查看其各个 section 的信息如下
(2)使用 objdump -D 对其进行反汇编如下:
(3)使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示出来:
$ gcc -o hello -g hello.c //要加上-g 选项
$ objdump -S hello

2.intel风格的汇编

(1)下载nasm编译器,编写hello.asm文件

nivechen@nivechen-virtual-machine:~/homework3.3$ sudo apt-get install nasm
nivechen@nivechen-virtual-machine:~$ gedit hello.asm

(2)生成目标文件,并且链接生成执行文件

nivechen@nivechen-virtual-machine:~$ nasm -f elf64 hello.asm 
nivechen@nivechen-virtual-machine:~$ ld -s -o output hello.o
nivechen@nivechen-virtual-machine:~$ ./output
Hello, world!

(3)对比用nasm编译生成的可执行程序与gcc编译生成的可执行程序

nivechen@nivechen-virtual-machine:~$ size output//nasm编译
   text	   data	    bss	    dec	    hex	filename
     34	     14	      0	     48	     30	output
nivechen@nivechen-virtual-machine:~$ size output1//gcc编译
   text	   data	    bss	    dec	    hex	filename
   1515	    600	      8	   2123	    84b	output1

三、实际代码与第三方库

1、curse库的主要函数和功能

int insertln(void);   //插入空白行
int deleteln(void);   //删除字符和空白行
int beep(void);   //终端响铃
int erase(void);   //在屏幕的每个位置写上空白字符
int clear(void);    //使用一个终端命令来清除整个屏幕,内部调用了clearok来执行清屏操作,(在下次调用refresh时可以重现屏幕原文)
int clrtobot(void);   //清除光标位置到屏幕结尾的内容
int attroff(chtype attribute);   //启用或关闭某属性
int standend(void);          //这两个表示更加通用的强调模式,通常映射为反白显示
int cbreak();   //设置cbreak模式,字符一键入,直接传给程序

2、Win10系统中,启用 “telnet client” 和"适用于Linux的Windows子系统"(

在这里插入图片描述

3、以游客身份体验一下即将绝迹的远古时代的 BBS

在这里插入图片描述
在这里插入图片描述

4、Ubuntu安装curses库,并查找安装的位置,体验小游戏

(1)安装curses库

nivechen@nivechen-virtual-machine:~$  sudo apt-get install libncurses5-dev

(2)查找头文件和库文件的安装位置

头文件位置:
在这里插入图片描述
库文件:
在这里插入图片描述

(3)体验小游戏

贪吃蛇游戏:
在这里插入图片描述
俄罗斯方块:
在这里插入图片描述

总结:

1、静态库与动态库区别

静态库文件在编译时就会连接到目标文件中,程序运行不需要再使用静态库文件。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。程序在运行时,会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提
示错误而终止程序运行。所以动态库文件创建后,我们将文件 libmyhello.so 复制到目录/usr/lib 中。用mv file /usr/lib 或者cp file /usr/lib均可。

2、静态库与动态库的创建及其使用

(1)静态库和动态库创建

静态库和动态库都是用.o文件创建,所以我们先用gcc -c file.c创建file.o文件;然后用 ar -crv libmyhello.a file.o创建静态库 ;用 gcc -shared -fPIC -o libmyhello.so file.o创建动态库。如果静态库或者动态库由多个.o文件构成,直接写在后面即可
eg:ar -crv libmyhello.a file1.o file2.o
在静态库libmyhello.a的命名中,lib为前缀myhello为自己设计的文件名.a为静态库后缀;动态库类似lib为前缀myhello为自己设计的文件名.so为动态库后缀

(2)静态库和动态库使用

静态库的使用方法:
(1)gcc main.c libmyhello.a -o output
(2)先生成 main.o:
gcc -c main.c
再生成可执行文件:
gcc -o output main.o libmyhello.a
我这里推荐用这两种方法
动态库使用方法:
(1)gcc main.c libmyhello.so -o output
(2)先生成 main.o:
gcc -c main.c
再生成可执行文件:
gcc -o output main.o libmyhello.so

(3)“sub.h”

#ifndef SUB_H
#define SUB_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif

注意这里对x2x,x2y函数定义的类型是float,在后面要与之相匹配,不然在后面编译连接会出错,这里千万注意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值