编译器gcc背后的故事

一、可执行程序的组装

1、用gcc生成静态库和动态库的实例练习与静态库.a与.so库文件的生成与使用的实例练习
1)、用gcc生成静态库和动态库的实例练习
  • 用gcc生成.a静态库

步骤一:写入源代码hello.h、hello.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.c 编译成.o 文件

输入命令行gcc -c hello.c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DVZ7oTeJ-1602685279294)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.png)]

步骤三:由.o 文件创建静态库

输入命令行ar -crv libmyhello.a hello.o

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i3cUnOyz-1602685279296)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.png)]

步骤四:在程序中使用静态库

建立可执行程序

输入命令行gcc main.c libmyhello.a -o hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ufLGXcw-1602685279297)(E:\大三学习\嵌入式系统开发\第三次作业\截图\4.png)]

运行可执行程序hello

输入命令行./hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oS7gqLO8-1602685279300)(E:\大三学习\嵌入式系统开发\第三次作业\截图\6.png)]

步骤五:删除libmyhello.a后hello是否还可执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xhSDrkJQ-1602685279301)(E:\大三学习\嵌入式系统开发\第三次作业\截图\7.png)]

结果发现:程序照常运行,静态库中的公用函数已经连接到目标文件中了。

  • 用gcc生成.so动态库
    步骤一:运用之前的源代码由.o 文件创建动态库文件

    输入命令行gcc -shared -fPIC -o libmyhello.so hello.c

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZAvflmf7-1602686927927)(E:\大三学习\嵌入式系统开发\第三次作业\截图\8.png)]

    步骤二:在程序中使用动态库

    输入命令行gcc -o hello1 main.c -L. -lmyhello形成hello1可执行程序

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dWE4yiMk-1602686927929)(E:\大三学习\嵌入式系统开发\第三次作业\截图\9.png)]

    输入命令行mv libmyhello.so /usr/lib

    再输入命令行./hello1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iSEczt9c-1602686927930)(E:\大三学习\嵌入式系统开发\第三次作业\截图\10.png)]

    当我们未将文件 libmyhello.so 复制到目录/usr/lib 中时。程序在运行时, 不能在/usr/lib 和/lib 等目录中查找需要的动态库文件。会出现错误。

  • 当静态库和动态库同时存在时,优先权的问题

    步骤一:创建静态库文件 libmyhello.a 和动态库文件 libmyhello.so

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PFCCTAuk-1602686927933)(E:\大三学习\嵌入式系统开发\第三次作业\截图\12.png)]

    步骤二:运行 gcc 命令来使用函数库 myhello 生成目 标文件 hello

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-70Ax9966-1602686927934)(E:\大三学习\嵌入式系统开发\第三次作业\截图\13.png)]

    步骤三:运行程序 hello

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-umkPxwYq-1602686927936)(E:\大三学习\嵌入式系统开发\第三次作业\截图\14.png)]

    从程序 hello 运行的结果中很容易知道,当静态库和动态库同名时,gcc 命令将优先使用动 态库,默认去连/usr/lib 和/lib 等目录中的动态库,将文件 libmyhello.so 复制到目录/usr/lib 中即可。

2)、静态库.a与.so库文件的生成与使用的实例练习
  • 用gcc生成.a静态库

    步骤一:写入源代码A.h、A1.c、A2.c、test.c分别如下

    A.h

    #ifndef A_H
    #define A_H
    void print1(int);
    void print2(char *);
    #endif
    

    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);
    }
    

    test.c

    #include <stdlib.h>
    #include "A.h"
    int main(){
    print1(1);
    print2("test");
    exit(0);
    }
    

    步骤二:将 A1.c 、A2.c编译成.o 文件

    输入命令行gcc -c A1.c A2.c

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7qG1yl3K-1602690451908)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.png)]

    步骤三:生成静态库.a 文件

    输入命令行ar crv libafile.a A1.o A2.o

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFdh8Jdz-1602690451922)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.2.png)]

    步骤四:在程序中使用静态库

    输入命令行gcc -o test test.c libafile.a

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-grAWEnRE-1602690451930)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.3.png)]

    再输入命令行./test

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4I70Xyrx-1602690451946)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.8.png)]

  • 用gcc生成.so动态库

    步骤一:运用之前的源代码由.o 文件创建动态库文件

    输入命令行gcc -c -fpic A1.c A2.c

    gcc -shared *.o -o libsofile.so

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rznCa6Au-1602690451953)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.4.png)]

    步骤二:在程序中使用动态库

    输入命令行gcc -o test test.c libsofile.so

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IPhLewST-1602690451957)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.5.png)]

    再输入命令行mv libmyhello.so /usr/lib与./test

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2O2PXXmH-1602690451960)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.7.png)]

    注意事项同上

2、对第一次作业进行改编,进行静态库与动态库的生成
1)、 用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小

步骤一:写入源代码sub1.h、sub1.c、main.c分别如下

sub1.c

#include<stdio.h>
int x2x(int a,int b){       //定义x2x函数供main1.c使用
int c;
c=a+b;
return c;
}
int x2y(int a,int b){
int c;
c=a*b;
return c;
}

sub1.h

#ifndef SUB1_H
#define SUB1_H
int x2x(int,int);
int x2y(int,int);
#endif

main.c

include<stdio.h>
#include "sub1.h"       //从sub1.c中引入x2x函数
int main(){
int a,b;
int x,y;
scanf("%d%d",&a,&b);
x=x2x(a,b);
printf("a+b=%d\n",x);
y=x2y(a,b);
printf("a*b=%d\n",y);
return  0;
}

步骤二:将 sub1编译成.o 文件

输入命令行gcc -c sub1.c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xJwEZUmx-1602695385658)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.1.png)]

步骤三:生成静态库.a 文件

输入命令行ar -crv libasub.a sub1.o

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JojWfLXi-1602695385677)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.2.png)]

步骤四:在程序中使用静态库

输入命令行gcc -o main main.c libasub.a

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z91qooUO-1602695385687)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.3.png)]

再输入命令行./main

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-StnPSaMz-1602695385698)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.4.png)]

2)、用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录文件的大小

步骤一:运用之前的源代码由.o 文件创建动态库文件

输入命令行gcc -shared -fPIC -o libsosub.so sub1.c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xgeqhqyS-1602695385705)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.5.png)]

步骤二:在程序中使用动态库

输入命令行gcc -o main1 main.c -L. -lsosub

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyRD4WkC-1602695385710)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.6.png)]

再输入命令行mv libsosub.so /usr/lib与./main1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DWidCbej-1602695385712)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.7.png)]

注意事项同上

3)、静态库下的可执行文件与动态库下的可执行文件大小的比较

由下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NwDEUa4A-1602695385715)(E:\大三学习\嵌入式系统开发\第三次作业\截图\1.1.8.png)]

可见,动态库下的可执行文件的大小要大于静态库下的可执行文件的大小。

二、gcc编译工具集中各软件的用途

1、Linux 常用命令GCC的简单编译功能

用gcc进行编译可一步到位的编译,但实际上的编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译 (Compilation)、汇编 (Assembly)和连接(Linking)。

下面我们创建两个测试文件,test.c与test1.c,两个文件的内容一致,均为:

#include<stdio.h>
int main(){
printf("hello world!\n");
return 0;
}

通过这两个文件我们来看gcc一步到位的编译与实际上的编译过程。

  • 一步到位的编译

    直接输入命令行gcc test.c -o test

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BoBMW3Ep-1602729086888)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.2.png)]

    输入命令行./test

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P9B9evoY-1602729086889)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.3.png)]

  • 实际上的编译过程

    步骤一:预处理

    输入命令行gcc -E test1.c -o test1.i

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fg1FxiLV-1602729086890)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.4.png)]

    发现目录下生成了test1.i文件。

    步骤二:编译为汇编代码

    输入命令行gcc -S test1.i -o test1.s

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sVp7My9z-1602729086892)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.5.png)]

    发现目录下生成了test1.s文件。

    步骤三:汇编

    输入命令行gcc -c test1.s -o test1.o

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A7Q8jEdA-1602729086894)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.6.png)]

    发现目录下生成了test1.o文件。

    步骤四:连接

    输入命令行gcc test1.o -o test1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-edfTZRZK-1602729086895)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.7.png)]

    发现目录下生成了test1可执行文件。

    输入命令行./test1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UcW3ZF9b-1602729086896)(E:\大三学习\嵌入式系统开发\第三次作业\截图\2.8.png)]

2、分析 ELF 文件
  • ELF 文件的段

    输入命令行readelf -S test

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6eFY6JrM-1602730832690)(E:\大三学习\嵌入式系统开发\第三次作业\截图\11.1.png)]

  • 反汇编 ELF

    输入命令行objdump -D hello

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JXxsP13r-1602730832693)(E:\大三学习\嵌入式系统开发\第三次作业\截图\11.2.png)]

  • 使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示

    输入命令行gcc -o hello -g hello.c

    objdump -S hello

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4wNSOVUS-1602730832695)(E:\大三学习\嵌入式系统开发\第三次作业\截图\11.3.png)]

3、用nasm汇编编译器编译生成执行程序

准备工作:下载所给hello.asm

步骤一:形成目标文件hello.o

输入命令行nasm -f elf32 hello.asm hello.o

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhImtwNf-1602733012246)(E:\大三学习\嵌入式系统开发\第三次作业\截图\22.1.png)]

发现目录下已生成hello.o文件

步骤二:形成可执行文件hello

输入命令行ld -m elf_i386 hello.o -o hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yMv7AHZy-1602733012249)(E:\大三学习\嵌入式系统开发\第三次作业\截图\22.2.png)]

发现目录下已生成hello文件

步骤三:执行可执行文件hello

输入命令行./hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lhWJQEKV-1602733012250)(E:\大三学习\嵌入式系统开发\第三次作业\截图\22.3.png)]

步骤四:比较此可执行文件hello与普通hello world程序可执行文件hello1的文件大小

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wTByQ2XF-1602733012254)(E:\大三学习\嵌入式系统开发\第三次作业\截图\22.4.png)]

可见汇编编译器下形成的hello很小,远小于gcc编译器下形成的hello。

三、借助第三方库函数完成代码设计

1、光标库(curses)的主要函数功能
  • initscr(): initscr() 是一般 curses 程式必须先呼叫的函数, 一但这个函数被呼叫之後, 系统将根据终端机的形态并启动 curses 模式.
  • endwin(): curses 通常以呼叫 endwin() 来结束程式. endwin() 可用来关闭curses 模式, 或是暂时的跳离 curses 模式. 如果您在程式中须要call shell ( 如呼叫 system() 函式 ) 或是需要做 system call, 就必须先以 endwin() 暂时跳离 curses 模式. 最後再以wrefresh() doupdate() 来重返 curses 模式.
  • cbreak() and nocbreak(): 当 cbreak 模式被开启後, 除了 DELETE 或 CTRL 等仍被视为特殊控制字元外一切输入的字元将立刻被一一读取.当处於 nocbreak 模式时, 从键盘输入的字元将被储存在 buffer 里直到输入 RETURN或 NEWLINE.在较旧版的 curses 须呼叫 crmode(),nocrmode() 来取代 cbreak(),nocbreak()
  • nl() and nonl(): 用来决定当输入资料时, 按下 RETURN 键是否被对应为 NEWLINE 字元 ( 如 /n ). 而输出资料时, NEWLINE 字元是否被对应为 RETURN 和 LINDFEED系统预设是开启的.
  • echo() and noecho(): 此函式用来控制从键盘输入字元时是否将字元显示在终端机上.系统预设是开启的.
  • intrflush(win,bf): 呼叫 intrflush 时须传入两个值, win 为一 WINDOW 型态指标, 通常传入标准输出入萤幕 stdscr. bf 为 TRUE 或 FALSE. 当 bf 为 true 时, 当输入中断字元 ( 如 break) 时, 中断的反应将较为快速.但可能会造成萤幕的错乱.
  • keypad(win,bf): 呼叫 keypad 时须传入两个值, win 为一 WINDOW 型态指标, 通常传入标准输出入萤幕 stdscr. bf 为 TRUE 或 FALSE. 当开启 keypad 後, 可以使用键盘上的一些特殊字元, 如上下左右>等方向键, curses 会将这些特殊字元转换成 curses.h 内定义的一些特殊键. 这些定义的特殊键通常以 KEY_ 开头.
  • refresh(): refresh() 为 curses 最常呼叫的一个函式. curses 为了使萤幕输出入达最佳化, 当您呼叫萤幕输出函式企图改变萤幕上的画面时, curses 并不会立刻对萤幕做改变, 而是等到refresh() 呼叫後, 才将刚才所做的变动一次完成. 其馀的资料将维持不变. 以尽可能送最少的字元至萤幕上. 减少萤幕重绘的时间.如果是 initscr() 後第一次呼叫 refresh(), curses 将做清除萤幕的工作.
2、以游客身份体验一下即将绝迹的远古时代的 BBS

步骤一:在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”

步骤二:启用 “telnet client” 和"适用于Linux的Windows子系统"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FsLSxpyE-1602776463661)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.1.png)]

步骤三:以游客身份登录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t2dw8xYH-1602776463670)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.2.png)]

进入后的界面:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kWLWD35j-1602776463680)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.3.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AeA1XsDM-1602776463694)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.3.1.png)]

3、安装curses库

输入命令行sudo apt-get install libncurses5-dev进行安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgvCk8Qz-1602776463704)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.5.png)]

发现头文件curse.h在目录/usr/include下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FPs7gkmA-1602776463711)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.5.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LkN90J78-1602776463716)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.9.png)]

库文件在/usr/lib下。

4、Linux 环境下C语言编译实现贪吃蛇游戏

贪吃蛇源代码链接:http://www.linuxidc.com/Linux/2011-08/41375.htm

输入命令行cc mysnake1.0.c -lcurses -o mysnake1.0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HbPMEMGB-1602776463720)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.6.png)]

输入命令行./mysnake1执行程序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WWckgkYV-1602776463725)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.7.png)]

效果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Li8Rbdh9-1602776463729)(E:\大三学习\嵌入式系统开发\第三次作业\截图\3.8.gif)]

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值