Hello World
源代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello World\n");
exit(0);
}
编译、连接和运行程序
$ gcc -o hello hello.c
$ ./hello
输出
Hello World
实验解析
使用C语言编译器gcc将C语言源代码转换为可执行文件hello。
应用程序管理
标准位置
/usr/bin
/usr/local/bin
/opt
头文件
使用头文件来提供对常量的定义和对系统函数及库函数调用的声明。
标准位置
/usr/include目录及其子目录
包含非标准位置头文件
$ gcc -I/usr/linux/include hello.c
搜索包含特定定义和函数原型的头文件
$ grep EXIT_ *.h
库文件
库是一组预先编译好的函数的集合,这些函数都是按照可重用的原则编写的。
标准位置
/lib和/usr/lib
默认情况下,C语言编译器(连接程序)仅仅搜索C语言库。即使把库文件放在标准目录中,还是需要在命令行中明确指明。
命名规范
lib+库名+.+库类型(a/o)
.a代表传统的静态函数库
.so代表共享函数库
指定库文件
$ gcc -o hello hello.c /usr/lib/libm.a
或者
$ gcc -o hello hello.c -lm
包含非标准位置库文件
$ gcc -o hello -L/usr/linux/lib hello.c -lm
使用/usr/linux/lib目录中的libm库版本来编译和链接程序hello。
静态库
函数源文件bill.c和fred.c
#include <stdio.h>
void bill(char *arg)
{
printf("bill: you passed %s\n", arg);
}
#include <stdio.h>
void fred(int arg)
{
printf("fred: you passed %d\n", arg);
}
生成目标文件(将要包含在库文件中)
使用-c选项,阻止编译器创建一个完成的程序
$ gcc -c bill.c fred.c
头文件lib.h
/*
This is lib.h. It declares the functions fred and bill for users
*/
void bill(char *);
void fred(int);
调用程序program.c
#include <stdlib.h>
#include "lib.h"
int main()
{
bill("Hello World");
exit(0);
}
编译和测试(显式指定目标文件)
编译你的文件并将其与先前编译好的目标模块bill.o链接。
$ gcc -c program.c
$ gcc -o program program.o bill.o
$ ./program
输出
Bill: we passed Hello World
创建库文件
使用ar程序创建一个归档文件并将你的目标文件添加进去。
$ ar crv libfoo.a bill.o fred.o
编译和测试(使用库文件)
$ gcc -o program program.o libfoo.a
$ ./program
查看哪些函数被包含在目标文件、函数库或可执行文件里
nm命令:显示二进制目标文件的符号表
$ nm program |grep T
输出
08048466 T bill
080484f4 T _fini
0804a000 d _GLOBAL_OFFSET_TABLE_
080482cc T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
08049f10 d __JCR_LIST__
080484f0 T __libc_csu_fini
08048490 T __libc_csu_init
0804843b T main
08048340 T _start
0804a020 D __TMC_END__
08048370 T __x86.get_pc_thunk.bx
共享库
静态库的一个缺点
当你同时运行许多应用程序并且它们都使用来自同一个函数库的函数时,内存中就会有同一函数的多份副本,这将消耗大量宝贵的内存和磁盘空间。
当一个程序使用共享库时,它的链接方式是这样的:程序本身不再包含函数代码,而是引用运行时可访问的共享代码。当编译好的程序被装载到内存中执行时,函数引用被解释并产生对共享库的调用,如果有必要,共享库才被加载到内存中。
对Linux系统来说,负责装载共享库并解析客户程序函数引用的程序(动态加载器)是ld.so。
共享库的
/etc/ld.so.conf
查看程序所需要的共享库
$ ldd program
输出
linux-gate.so.1 => (0xb771c000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb754b000)
/lib/ld-linux.so.2 (0x8007d000)
——《Linux程序设计 第四版》