目录
第1关:第一个C程序
任务描述
相关知识
编译C程序
编程要求
答案及其步骤:
第2关:Linux编译C程序
任务描述
相关知识
gcc编译器使用方法
编程要求
答案及其步骤:
第3关:Linux之静态库编写
任务描述
相关知识
生成静态库
使用静态库
编程要求
答案及其步骤:
第4关:Linux之动态库编写
任务描述
相关知识
生成动态库
使用动态库
更新/etc/ld.so.cache来运行动态库
修改LD_LIBRARY_PATH环境变量
编程要求
答案及其步骤:
第1关:第一个C程序
任务描述
本关任务:在
Linux
系统上编写第一个C
语言程序Hello world
。相关知识
C
语言是Linux
操作系统中最常用的编程语言,部分原因在于Linux
操作系统本身几乎是采用C
语言编写的。使用C
语言,程序员可以通过函数库和系统调用非常容易地访问系统服务。另外,还有很多有用的工具为程序开发和维护提供了便利。本实训将讲解如何编译和链接
C
语言程序,假设用户掌握了C
语言的基本语法。在Windows
系统上我们编写C
语言程序,我们只需在IDE
(windows
常使用的IDE
有visual studio
系列)中写入代码,然后点击编译,如果程序没有语法错误则会生成可执行文件,然后点击运行即可运行生成的可执行文件。其实IDE
帮助我们自动的编译和运行程序,所以我们不需要关注程序是如何被编译的,而在Linux
系统上我们通常要学会如何使用命令来编译程序,此时,我们需要手动的去编译程序,然后手动的运行程序。编译C程序
Linux
系统上常用的C
编译器是gcc
,大多数开发板都包含了这个工具。
gcc
是开源领域应用最广泛的编译器之一,其具有功能强大,编译代码支持性能优化等特点。而Windows
系统上常用的编译器叫cl.exe
,该编译器就是Visual Studio
集成开发环境所使用的默认编译器。当我们点击编译按钮,Visual Studio
则会自动帮我们调用cl.exe
编译器去编译我们所写的程序。使用
gcc
编译C
程序非常简单,可以使用如下命令来编译程序:gcc 源文件
案例演示1:
使用
vim
编辑器编写一个“Hello world”C
程序,并将源文件保存为test.c
,然后编译运行test.c
,可以使用如下命令:vim test.c gcc test.c ./a.out
使用
vim
编写如下代码#include <stdio.h> int main() {printf("Hello world\n");return 0; }
[请在右侧“命令行”里直接体验]
注意
`gcc`默认使用`a.out`作为可执行文件的名字; ./a.out表示运行当前目录下的a.out命令;
编程要求
本关任务是学会使用
gcc
编译C
程序。具体编程要求如下:
在当前目录下编写一个简单的
C
程序,输入“Hello world”字符串;使用
gcc
编译生成a.out
可执行文件;
答案及其步骤:
首先输入如下:
vim test.c //使用vim编辑器编写,并将源文件保存为test.c
进入编写如下c语言代码:
#include <stdio.h> int main() {printf("Hello world\n"); }
按i键开始编写
编写完后按Esc键退出编写模式,按Shift键+:键,输入wq保存并退出
gcc test.c //编译test.c ./a.out //运行test.c
第2关:Linux编译C程序
任务描述
本关任务:学会
gcc
编译器的基本使用方法。相关知识
通过上一关内容学会了如何使用
gcc
命令来编译C
程序,本关将进一步学习gcc
编译器。
C
语言程序从源代码到二进制行程序需要经历如下四个步骤:
预处理 编译 汇编 链接
[C语言编译流程]
预处理 预处理是根据预处理指令组装新的
C/C++
程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。编译 编译是指将预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后,产生相应的汇编代码文件。
汇编 汇编是指将编译完的汇编代码文件翻译成机器指令,并生成可重定位目标程序的.o文件,该文件为二进制文件,字节编码是机器指令。
链接 链接过程是指链接器将一个个目标文件(或许还会有库文件)链接在一起生成一个完整的可执行程序,这个可执行程序才是我们最后直接执行的文件。
gcc编译器使用方法
gcc
命令具体使用方法如下:gcc 命令选项 参数
常用命令选项如下:
-o:指定生成的输出文件名字; -E:仅执行编译预处理; -S:将C代码转换为汇编代码; -c:仅执行编译和汇编操作,不进行连接操作; -I:包含库的头文件路径(大写i); -L:指定库所在的路径; -l:指定使用的库(小写l);
案例演示1:
使用
vim
编辑器编写一个“Hello world"C
程序,并将源文件保存为test.c
,编译test.c
,指定输出可执行文件为test
,并运行test
,可以使用如下命令:gcc test.c -o test ./test
使用
vim
编写如下代码#include <stdio.h> int main() {printf("Hello world\n");return 0; }
[请在右侧“命令行”里直接体验]
案例演示2:
仅编译
test.c
生成汇编语言,可以使用如下命令:gcc -S test.c
[请在右侧“命令行”里直接体验]
注意编译生成的汇编文件使用
.s
为后缀名,汇编生成的二进制文件使用.o
为后缀名。
编程要求
本关任务是学会使用
gcc
编译C
程序。具体编程要求如下:
在当前目录下编写一个简单的
C
程序,输入“Hello GCC”字符串;使用
gcc
编译生成名为firstExec
的可执行文件;
答案及其步骤:
首先输入如下:
vim test.c //使用vim编辑器编写,并将源文件保存为test.c
进入编写如下c语言代码:
#include <stdio.h> int main() {printf("Hello GCC\n"); }
按i键开始编写
编写完后按Esc键退出编写模式,按Shift键+:键,输入wq保存并退出
gcc test.c -o firstExec //编译test.c文件,并指定生成的输出出文件的名字 ./firstExec //运行firstExec文件
第3关:Linux之静态库编写
任务描述
本关任务:学会在
Linux
系统上生成C
语言的静态库。相关知识
在实际的软件开发时, 应该遵守一个基本原则:不要重复造轮子。如果某些代码经常要用到,不仅这个项目能使用,而且也能复用到其它项目上,那么就应该把这部分代码从项目中分离出来,将其编译为库文件,供需要的程序调用。
程序库分为两类,分别是静态库和动态库。本关将主要讲解如何生成静态库。
Windows
系统上的静态库是以.lib
为后缀,而Linux
系统上的静态库是以.a
为后缀的特殊的存档。
Linux
系统的标准系统库可在目录/usr/lib
与/lib
中找到。比如,在类Unix
系统中C
语言的数序库一般存储为文件/usr/lib/libm.a
。该库中函数的原型声明在头文件/usr/include/math.h
中。生成静态库
在
Linux
下,我们可以使用gcc
和ar
工具制作和使用自己的静态库,具体过程如下:将源码文件编译成.o目标文件; 使用ar工具将多个目标文件打包成.a的静态库文件;
注意
Linux
系统上默认的静态库名格式为:libxxx.a
,其中xxx
为生成库的名称。案例演示1:
编写一个函数
printHello
,其功能为打印“Hello world"字符串,将其编译生成名为Hello
的静态库,可以使用如下命令:vim printHello.h vim printHello.c gcc -c printHello.c -o printHello.o ar rcs libHello.a printHello.o
使用
vim
编写printHello.h
(声明printHello
函数,方便以后被其它程序调用)#ifndef __PRINTHELLO_H__ #define __PRINTHELLO_H__ #include <stdio.h> void printHello(); #endif
使用
vim
编写printHello.c
#include <stdio.h>void printHello() {printf("Hello world\n"); }
[请在右侧“命令行”里直接体验]
使用静态库
静态库的使用方法只需要在编译程序的时候指明要链接的库名称即可,
gcc
中有两个参数是关于链接库时所使用的,分别是:-L
和-l
。-L:用于告诉gcc要链接的库所在目录; -l:用于指明链接的库名称(小写l);
案例演示1:
调用以上案例生成的
printHello
函数,可以使用如下命令:vim main.c gcc main.c -o exe -L ./ -lHello ./exe
使用
vim
编写main.c
#include "printHello.h" int main() {printHello();return 0; }
[请在右侧“命令行”里直接体验]
编程要求
本关任务是学会生成和使用静态库。
具体编程要求如下:
在当前目录下编写一个简单的函数
int Add(int a, int b)
,其功能为计算输入参数a+b
的结果;将Add函数编译生成一个静态库
libAdd.a
,并存放在当前目录下;
答案及其步骤:
vim Add.h
进入如下输入:
#include<stdio.h> int Add(int a,int b);
vim Add.c
进入如下输入:
#include<stdio.h> int Add(int a,int b) {return a+b; }
gcc -c Add.c -o Add.o ar rcs libAdd.a Add.o vim main.c
进入如下输入:
#include "Add.h" int main() {int c=Add(1,1);return c; }
gcc main.c -o exe -L ./ -lAdd ./exe
全部输入如下:
第4关:Linux之动态库编写
任务描述
本关任务:学会在
Linux
系统上生成C
语言的动态库。相关知识
上一关学习了如何生成静态库,本关将继续讲解如何生成动态库。
静态库与动态库的区别:
静态库 动态库 名称 命名方式是"libxxx.a",库名前加"lib",后缀用".a","xxx"为静态库名 命名方式是"libxxx.so", 库名前加"lib",后缀用".so", "xxx"为动态库名 链接时间 静态库的代码是在编译过程中被载入程序中 动态库在编译的时候并没有被编译进目标代码,而是当你的程序执行到相关函数时才调用该函数库里的相应函数 优点 在编译后的执行程序不在需要外部的函数库支持,因为所使用的函数都已经被编进去了。 动态库的改变并不影响你的程序,所以动态函数库升级比较方便 缺点 如果所使用的静态库发生更新改变,你的程序必须重新编译 因为函数库并没有整合进程序,所以程序的运行环境必须提供相应的库
Windows
系统上的动态库是以.dll
为后缀,而Linux
系统上的动态库是以.so
为后缀的特殊的存档。生成动态库
在
Linux
下,我们可以使用gcc
制作和使用动态库,具体制作过程如下:使用gcc命令加-fPIC参数将源码文件编译成.o目标文件; 使用gcc命令加-shared参数将多个目录文件生成一个动态库文件;
注意
Linux
系统上默认的动态库名格式为:libxxx.so
,其中xxx
为生成库的名称。案例演示1:
编写一个函数
printHello
,其功能为打印"Hello world"字符串,将其编译生成名为Hello
的动态库,可以使用如下命令:vim printHello.h vim printHello.c gcc -fPIC -c printHello.c -o printHello.o gcc -shared printHello.o -o libHello.so
使用
vim
编写printHello.h
(申明printHello
函数,方便以后被其它程序调用)
#ifndef __PRINTHELLO_H__ #define __PRINTHELLO_H__ #include <stdio.h> void printHello(); #endif
使用
vim
编写printHello.c
#include <stdio.h> void printHello() {printf("Hello world\n"); }
[请在右侧“命令行”里直接体验]
使用动态库
动态库的使用方法与静态库使用方式略有不同,除了使用
gcc
中的-L
和-l
参数外,想要调用动态库还需要更新Linux
系统中/etc/ld.so.cache
或者修改LD_LIBRARY_PATH
环境变量,否则在运行程序的时候会报**"No such file or directory"**错误。案例演示1:
调用以上案例生成的
printHello
函数,可以使用如下命令:vim main.c gcc main.c -o exe -L ./ -lHello ./exe
[使用
vim
编写程序][请在右侧“命令行”里直接体验]
此时编译正常,当运行的时候会报**"No such file or directory"**错误。
更新/etc/ld.so.cache来运行动态库
编辑/etc/ld.so.conf配置文件,然后加入需要加载的动态库目录。 运行ldconfig更新/etc/ld.so.cache
案例演示1:
更新
/etc/ld.so.cache
,然后运行上一个案例生成的exe
,可以使用如下命令:sudo vim /etc/ld.so.conf sudo ldconfig ./exe
[使用
vim
向/etc/ld.so.conf
文件添加/home/fzm
路径][请在右侧“命令行”里直接体验]
修改
LD_LIBRARY_PATH
环境变量在运行可执行文件前修改
LD_LIBRARY_PATH
变量为可执行程序指定需要加载的动态库路径。案例演示1:
修改
LD_LIBRARY_PATH
,然后运行上一个案例生成的exe
,可以使用如下命令:LD_LIBRARY_PATH=. ./exe
[请在右侧“命令行”里直接体验]
注意:
LD_LIBRARY_PATH告诉了exe程序现在当前目录下寻找链接的动态库; 当运行环境中同时存在同名的静态库和动态库时,默认优先链接动态库;
编程要求
本关任务是学会生成和使用动态库。
具体编程要求如下:
在当前目录下编写一个简单的函数
int Sub(int a, int b)
,其功能为计算输入参数a-b
的结果;将Sub函数编译生成一个动态库
libSub.so
,并存放在当前目录下;修改
/etc/ld.so.conf
,添加当前目录,并更新/etc/ld.so.cache
;
答案及其步骤:
vim Sub.h
进入如下输入:
#include<stdio.h> int Sub(int a,int b);
vim Sub.c
进入如下输入:
#include<stdio.h> int Sub(int a,int b) {return a-b; }
gcc -fPIC -c Sub.c -o Sub.o gcc -shared Sub.o -o libSub.so vim main.c
进入如下输入:
#include "Sub.h" int main() {int c=Sub(1,1);return c; }
gcc main.c -o exe -L ./ -lSub vim /etc/ld.so.conf
进入如下输入:
/root //输入/root
ldconfig ./exe
全部输入如下: