编译器背后的故事

本文详细介绍了如何使用GCC编译器生成Linux下的静态库.a和动态库.so,包括创建、使用及库文件的管理。同时,文章探讨了Linux系统中curses库的应用,并分享了LinuxGCC的常用命令。在实践中,通过实例展示了静态库和动态库的优先级选择。此外,还介绍了Linux环境下BBS系统的远古体验和curses库的安装方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

  • 用 gcc 生成 .a 静态库和 .so 动态库
  • Linux下静态库.a与.so库文件的生成与使用
  • LinuxGCC常用命令
  • GCC编译器背后的故事
  • Linux 系统中终端程序最常用的光标库(curses)的主要函数
  • 参考资料

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

  • 先创建一个目录,保存本次的文件。
    在这里插入图片描述
  • 然后用gedit文本编辑器生成下面三个文件。

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

  • 用gcc -c指令吧hello.c文件编译成.o文件,可以用ls 指令看看是否生成了hello.o文件
    在这里插入图片描述
  • 由.o文件创建静态库
    用ar指令创建静态库,同样我们用ls指令查看结果。
    在这里插入图片描述
  • 第四步,在程序中使用静态库

可以使用以下方法在程序中使用静态库。
在这里插入图片描述
我们可以删除静态库文件试试公用函数hello是否真的连接到目标文件hello中了
在这里插入图片描述

  • 第五步,由.o创建动态库文件
    输入以下命令创建动态库:在这里插入图片描述
    同样的,用ls指令查看是否创建成功:在这里插入图片描述
  • 第六步,在程序中使用动态库
    我们先运行gcc命令生成目标文件,再运行它看看结果。
    在这里插入图片描述
    但是接下来./hello会提示出错,因为虽然连接时用的是当前目录的动态库,但是运行时,是到usr/lib中找库文件的,将文件libmyhello.so复制到目录/usr/lib中就OK了。在这里插入图片描述
    我们将文件libmyhello.so复制到目录/usr/lib中,就会成功了。在这里插入图片描述
    这说明了动态库在程序运行时是需要的。我们会过头看着过程,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样。那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,继续下一步。
  • 先删除除.c和.h外的所有文件,恢复成我们刚刚编辑完举例程序状态在这里插入图片描述
  • 再来创建静态库文件libmyhello.a和动态库文件libmyhello.so。
    在这里插入图片描述

然后,我们运行gcc命令来使用函数库myhello生成目标文件hello,并运行程序hello。
在这里插入图片描述
从程序hello运行的结果中很容易知道,当静态库和动态库同名时,gcc命令将优先使用动态库,默认去连/usr/lib和/lib等目录中的动态库,将文件libmyhello.so复制到目录/usr/lib中即可。

Linux下静态库.a与.so库文件的生成与使用

  1. 先创建一个目录:在这里插入图片描述
    然后分别用gedit文本编辑器编辑生成所需要的四个文件A1.c、A2.c、A.h、test.c四个文件。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 静态库.a的生成和使用

a.生成目标文件在这里插入图片描述
b.生成静态库.a文件在这里插入图片描述
c.使用.a库文件,创建可执行程序在这里插入图片描述

在这里插入图片描述

3.共享库.so文件的生成与使用
a.生成目标文件(xxx.o)(此处生成.o文件必须添加"-fpic"(小模式,代码少),否则在生成.so文件时会出错)
在这里插入图片描述
b.生成共享库.so文件
在这里插入图片描述
c.使用.so库文件,创建可执行程序
在这里插入图片描述
发现出现错误,运行ldd test,查看连接情况
在这里插入图片描述
发现确实是找不到对应的.so文件。这是由于linux自身系统设定的相应的设置的原因,即其只在/liband/usr/lib下搜索对应的.so文件,故需将对应so文件拷贝到对应路径。
在这里插入图片描述
再次运行,即可成功。

LinuxGCC常用命令

示例程序:在这里插入图片描述
这个程序,一步到位的编译指令是:gcc test.c- o test实质上,上述编译过程是分为四个阶段进行的,即预处理、编译、汇编和连接。

  • 预处理gcc -E test.c-o test.i或gcc -E test.c
  • 编译为汇编代码,预处理之后,可直接对生成的test.i文件编译,生成汇编代码:gcc -Stest.i -o test.s
  • 汇编:对于之前生成的汇编代码文件test.s,gas汇编器负责将其编译为目标文件,如下:gcc-c test.s -o test.o
  • 连接:对于之前生成的test.o,将其与C标准输入输出库进行连接,最终生成程序test,代码如下:gcc test.o- o test
    -多个文件的编译
    通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。假设有一个由testa.c和tesb.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序test,可以使用下面这条命令:gcc testa.c testb.c -o test
    如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。
  • 检错
    gcc -pedantic illcode.c -o illcode
    gcc-Wallillcode.c-oillcode
  • 库文件链接
    首先我们要进行编译test.c为目标文件,这个时候需要执行
gcc –c –I /usr/dev/mysql/include test.c –o test.o

最后我们把所有目标文件链接成可执行文件:

gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test
  • 强制链接时使用静态链接库
    在/usr/dev/mysql/lib目录下有链接时所需要的库文件libmysqlclient.so和libmysqlclient.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令:
gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test

GCC编译器背后的故事

  • 准备工作
    编写一个test4.c如下:在这里插入图片描述
    1.预处理:在这里插入图片描述
    2.编译:在这里插入图片描述
    3.汇编:在这里插入图片描述
    或者在这里插入图片描述
    4.链接
    动态链接
    在这里插入图片描述
    可用size指令查看大小
    如果使用命令“gcc -s tatic Hello.c -o Hello”则会使用静态库进行链接也可以用size查看大小在这里插入图片描述
    分析ELF文件
    LF文件格式如下图所示,位于ELFHeader和SectionHeaderTable之间的都是段(Section)。一个典型的ELF文件包含下面几个段:
    .text:已编译程序的指令代码段。
    .rodata:ro代表readonly,即只读数据(譬如常数const)。
    .data:已初始化的C程序全局变量和静态局部变量。
    .bss:未初始化的C程序全局变量和静态局部变量。
    .debug:调试符号表,调试器用此段的信息帮助调试。可以使用readelf -S查看其各个section的信息。
    反汇编ELF
    由于ELF文件无法被当做普通文本文件打开,如果希望直接查看一个ELF文件包含的指令和数据,需要使用反汇编的方法。使用objdump-D对其进行反汇编如下:objdump -D Hello
    使用objdump-S将其反汇编并且将其C语言源代码混合显示出来:gcc -o Hello -g Hello.c ,objdump -S Hello

Linux 系统中终端程序最常用的光标库(curses)的主要函数

  • 功能一、初始化和重置函数(以initscr函数开始,以endwin函数结束)
WINDOW *initscr(void); //在一个程序中只调用一次
int endwin(void);
  • 功能二、键盘模式功能
int echo();//用于开启键盘输入字符
int noecho();  //用于关闭键盘输入字符
int cbreak();   //设置cbreak模式,字符一键入,直接传给程序
int nocbreak();  //关闭
int raw();    //关闭特殊字符处理
int noraw();   //同时h恢复默认模式和特殊字符处
int getch();//读取一个字符
int getstr(char *string);//读取一个字符串
  • 功能三、管理屏幕功能
int addch(const chtype char_to_add);//当前位置添加字符
int addchstr(chtype *const string_to_add);//当前位置添加字符串
int printw(char *format, ...);//输出
int refresh(void);//刷新物理屏幕
int box(WINDOW *win_ptr, chtype vertical, chtype horizontal);//围绕窗口绘制方框
int insch(chtype char_to_insert);   //插入一个字符(已有字符后移)
int insertln(void);   //插入空白行
int delch(void);//删除光标左边的字符
int deleteln(void);   //删除空白行
int beep(void);   //终端响铃
int flash(void);   //闪烁
chtype inch(void);  //返回光标位置字符
int instr(char *string);  //读取字符到string所指向的字符串中
int innstr(char *string, int numbers);//读取numbers个字符到string所指向的字符串中
int erase(void);//在屏幕的每个位置写上空白字符
int clear(void);//清除整个屏幕
int clrtobot(void);//清除光标位置到屏幕结尾的内容
int clrtoeol(void);//清除光标位置到该行行尾的内容
int move(int new_y, int new_x);    //移动stdcsr的光标位置
int leaveok(WINDOW *window_ptr,bool leave_flag);//设置一个标志,用于控制在屏幕刷新后curses将物理光标放置的位置。
int attron(chtype attribute);//启用某属性
int attroff(chtype attribute);//关闭某属性
int attrset(chtype attribute);//设置某属性
int standout(void);//启动standout模式
int standend(void);//关闭standout模式
  • win10下的远古时代的 BBS

在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”,
在这里插入图片描述
启用 “telnet client” 和"适用于Linux的Windows子系统"(后面会使用)。
在这里插入图片描述
然后打开一个cmd命令行窗口,命令行输入 telnet bbs.newsmth.net,以游客身份体验一下即将绝迹的远古时代的 BBS (一个用键盘光标控制的终端程序)。在这里插入图片描述
在这里插入图片描述

安装curses库

在Ubuntu中可以用 sudo apt-get install libncurses5-dev 安装curses库
在这里插入图片描述
头文件(比如curses.h)和库文件都被安装到的目录:
在这里插入图片描述

参考资料

chrome-extension://ibllepbpahcoppkjjllbabhnigcbffpi/http://d0.ananas.chaoxing.com/download/94fdef0ff9306a1d78c5d95704d1e248?fn=Linux+GCC%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4&mt=
chrome-extension://ibllepbpahcoppkjjllbabhnigcbffpi/http://d0.ananas.chaoxing.com/download/dc36405faf8e7dc66d657fcc6b780cd7?fn=%E7%94%A8gcc%E7%94%9F%E6%88%90%E9%9D%99%E6%80%81%E5%BA%93%E5%92%8C%E5%8A%A8%E6%80%81%E5%BA%93&mt=
chrome-extension://ibllepbpahcoppkjjllbabhnigcbffpi/http://d0.ananas.chaoxing.com/download/dc36405faf8e7dc66d657fcc6b780cd7?fn=%E7%94%A8gcc%E7%94%9F%E6%88%90%E9%9D%99%E6%80%81%E5%BA%93%E5%92%8C%E5%8A%A8%E6%80%81%E5%BA%93&mt=
chrome-extension://ibllepbpahcoppkjjllbabhnigcbffpi/http://d0.ananas.chaoxing.com/download/b9616c5b28b9b0b12e4df8411148087e?fn=GCC%E7%BC%96%E8%AF%91%E5%99%A8%E8%83%8C%E5%90%8E%E7%9A%84%E6%95%85%E4%BA%8B&mt=
https://blog.youkuaiyun.com/qq_44644740/article/details/109090003

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值