嵌入式入门练习_3
用 gcc 生成 .a 静态库和 .so 动态库
例子1:写三个文件,包括,函数定义的头文件hello.h,函数内容的c文件hello.c,还有测试用的主程序c文件main.c。
程序为:
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;
}
程序作用是调用hello输出Hello everyone
一、先使用文件编辑器编辑三个文件:
二、无论静态库,还是动态库,都是由.o 文件创建的。因此,我们必须将源程序 hello.c 通过 gcc 先编译成.o 文件:
三、由.o 文件创建静态库,在系统提示符下键入以下命令将创建静态库文件 libmyhello.a:
四、在程序中使用静态库:
五、检测公用函数 hello 是否真的连接到目标文件 hello 中,删除静态库,测试程序是否正常运行:
删除静态库之后程序正常运行,说明内部函数已经被连接到了目标代码中。
六、以hello.o创建动态库,在系统提示符下键入以下命令得到动态库文件 libmyhello.so:
七、在程序中使用动态库,将文件 libmyhello.so 复制到目录/usr/lib 中,不然调用动态库时系统会找不到这个文件,调用并生成hello2可执行文件,并运行:
注意:是将动态库文件复制到用户的lib目录下,原来的目录下也要保留动态库文件,否则系统也会找不到动态库,导致编译失败。
Linux下静态库.a与.so库文件的生成与使用
一、准备阶段;创建四个文件,分别为
A1.c:
#include <stdio.h>
void print1(int arg)
{ printf("A1 print arg:%d\n",arg); }
A2.c:
#include <stdio.h>
void print2(char *arg)
{ printf("A2 printf arg:%s\n", arg); }
A.h:
#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif
test.c:
#include <stdlib.h>
#include "A.h"
int main()
{ print1(1);
print2("test");
exit(0); }
二、静态库的生成:静态库是由.o文件生成的,所以先编译c文件成为.o文件:
三、接下来由两个.o文件生成名称为libafile.a的静态库
四、调用库文件编译然后执行
五、共享库.so 文件的生成:动态库也是根据.o文件来生成的,所以先编译c文件成为.o文件:
六、根据.o文件生成动态库:
在生成动态库之后还要将库拷贝到用户的lib下,否则系统无法找到库,导致无法调用。
七、使用.so 库文件,创建可执行程序:
关于静态库的生成与使用的自主练习
题目:除了x2x函数之外,再扩展写一个x2y函数(功能自定),main函数代码将调用x2x和x2y ;将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序
一、先编写三个主程序:
二、编译文件生成.o文件:
三、根据x2x.o和x2y.o生成静态库文件:
四、调用静态文件连接mian.c生成可执行文件,并运行:
关于动态库的生成与使用的自主练习
一、在上个静态库练习题的基础上进行动态库练习,同样根据.o文件生成动态库:
二、将动态库拷贝到用户的lib目录中:
三、调用静态文件连接mian.c生成可执行文件,并运行:
GCC常用命令
一、gcc的详细编译过程, 预处理:
二、编译为汇编代码:
三、汇编:
四、 连接并运行:
五、 多个程序文件的编译:
gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc test1.o test2.o -o test
六、库文件连接
gcc –c –I /usr/dev/mysql/include test.c –o test.o
gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test
七、强制链接时使用静态链接库
gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test
GCC的汇编与Binutils的共同使用以及 ELF 文件
一、预处理后,.i文件部分字段:
二、编译文件后.s文件中的部分字段:
三、使用Binutils中的as命令进行汇编:
四、连接:
1、使用动态库进行链接:
2、使用静态库进行链接:
通过对比发现生成的ELF文件由于两种不同的连接形式尺寸差距变得很大,由此可见,动态相比静态更节省空间。
五、查看ELF文件各部分信息:
六、反汇编 ELF:
objdump -D hello
nasm命令的使用以及生成的可执行文件大小的对比
明显对比执行文件的大小,对比发现使用nasm命令编译生成的可执行文件要小得多。
curses的主要函数功能,写出几个基本函数名称及功能
curses工作在屏幕,窗口和子窗口之上。屏幕是设备全部可用显示面积(对终端是该窗口内所有可用字符位置),窗口与具体例程有关。如基本的stdscr窗口等
关于屏幕的常用部分代码:
int addch(const chtype char_to_add);//当前位置添加字符
int addchstr(chtype *const string_to_add);//当前位置添加字符串
int printw(char *format, ...);//类似与printf
int refresh(void);//刷新物理屏幕
int box(WINDOW *win_ptr, chtype vertical, chtype horizontal);
//围绕窗口绘制方框,用vertical绘制垂直边,用horizontal绘制水平边
int insch(chtype char_to_insert); //插入一个字符(已有字符后移)
在 win10 系统中体验BBS
在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”,启用 “telnet client” 和"适用于Linux的Windows子系统"。 然后打开一个cmd命令行窗口,命令行输入 telnet bbs.newsmth.net
安装curses库,以及头文件和库文件的安装位置
安装代码:
sudo apt-get install libncurses5-dev
用gcc编译生成一个终端游戏并运行(贪吃蛇游戏)。
写入贪吃蛇源代码,gcc编译并运行可执行文件:
总结
此次试验对于入门初步了解静态库和动态库相当重要,在静态库、动态库的创建与使用中,深刻了解到了静态库和动态库的差别,与两者工作状态的差别,这让我对库文件的基本构成和工作原理有了更多的认识,特别是可执行程序的组装过程,在摸索过程中,能明显感受到,难点在于动态库在拷贝时要启用管理员权限,并且原来目录下也要存在动态库。另外在了解ELF文件格式,汇编语言格式,在编译中与gcc共同工作的工具。还有gcc编译时的分布执行实验,让我对gcc的工作原理也有了新的见解。