[Beginning Linux Programming] 第一章 入门
Beginning Linux Programming(3rd Edition)
第一章 入门
1.1 UNIX、Linux和GNU简介
Linux的成功归功于——UNIX和GNU软件。
1.1.1 什么是UNIX
多用户、多任务操作系统。
1. UNIX简史
UNIX由Open Group(开放组织)管理的一个商标;
它指的是一种遵循特定规范(单一UNIX规范)的计算机操作系统。
2. UNIX哲学
典型的UNIX程序和系统具有如下特点:
- 简单性
- 集中性
- 可重用组件
- 过滤器
- 开放的文件格式
- 灵活性
1.1.2 什么是Linux
Linux是一个类UNIX内核的可以自由发布的实现版本,是一个操作系统的底层核心。
1.1.3 GNU项目和自由软件基金会
GNU(GUN's Not Unix)项目的宗旨:
试图创建一个与UNIX系统兼容,但并不受UNIX名字和源代码私有权限限制的操作系统和开发环境。
在GNU通用公共许可证(GPL)条款下发布的一些主要GNU项目软件有:
- GCC: GNU编译器集,包括GNU C编译器
- G++: C++编译器,是GCC的一部分
- GDB: 源代码级的调试器
- GNU make: UNIX make命令的免费版本
- Bison: 与NUIX yacc兼容的语法分析器
- bash: 命令解释器(shell)
- GNU Emacs: 文本编辑器及环境
1.1.4 Linux发行版
(通常称为flavor)
- Red Hat Linux
- SuSE Linux
- Debian GNU\Linux
......
1.2 Linux程序设计
1.2.1 Linux程序
Linux应用程序表现为两种特殊类型的文件:可执行文件、脚本文件。
登陆Linux系统时,我们与一个shell程序(通常是bash)进行交互,它像Windows中的命令提示窗口一样运行程序。
shell变量PATH包括:
- /bin
- /usr/bin
- /usr/local/bin
系统管理员(例如root用户)登录还包括存放系统管理程序的目录,如/sbin和/usr/sbin。
可选的操作系统组件和第三方应用程序可以安装在/opt目录下。
注:
Linux像UNIX一样,使用冒号(:)分隔PATH变量里的条目。
Linux用正斜线(/)分隔文件名里的目录名。
1.2.2 C语言编译器
在UNIX系统中,C语言编译器几乎总被称为cc。
在Linux系统中,你会发现c89、cc和gcc这些命令全部或部分地指向系统的C语言编译器,通常是GNU C编译器,或者简称gcc。
第一个Linux C语言程序
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main()
5 {
6 printf("Hello World\n");
7 exit(0);
8 }
编译、链接和运行我们的程序
$ gcc -o hello hello.c $ ./hello Hello World $
./hello中的./是用来指示shell去执行当前目录下给定名称的程序。
如果忘记用-o name选项告诉编译器将可执行程序放在何处,编译器则会把程序放在一个名为a.out的文件里。
1.2.3 开发系统导引
1. 应用程序
系统为正常使用提供的程序,包括用于程序开发的工具,都可在目录/usr/bin中找到;
系统管理员为某个特定的主机或本地网络添加的程序通常可在目录/usr/local/bin或/opt中找到;
其他一些功能特性和编程系统都可能有其自己的目录结构和程序目录。
注:
系统管理员一般喜欢使用/usr/local目录,它分离了厂商提供及后续添加文件与系统本身提供的应用程序。
当需要升级操作系统时,只需保留目录/usr/local里的内容。
2. 头文件
程序设计时用来提供对常量的定义和对系统及库函数调用的声明。
对C语言来说,这些头文件几乎总是在/usr/include目录及其子目录下。
3. 库文件
通常由一组相互关联的函数组成并执行某项常见的任务。
标准系统库文件一般存储在/lib和/usr/lib目录中。
- .a代表传统的静态函数库
- .so代表共享函数库
函数库可用la/usr/lib命令查看。
$ gcc -o fred fred.c /usr/lib/libm.a
这条命令指示编译器除搜索标准的C语言函数库外,还搜索数学库以解决函数引用问题。
也可简写为:
$ gcc -o fred fred.c -lm
注:
-lm标志的另一个好处是如果有共享库,编译器会自动选择共享库。
4. 静态库
(也称作归档文件(archive))
下面来创建一个小型函数库,它包含两个函数,然后在一个示例程序中调用其中一个函数。
第一个函数的源文件:
1 #include <stdio.h>
2
3 void fred (int arg)
4 {
5 printf("fred: you passed %d\n", arg);
6 }
第二个源文件:
#include <stdio.h>
void bill (char *arg)
{
printf("bill: you passed %s\n", arg);
}
分别编译这些函数,产生要包含在库文件中的目标文件:
$ gcc -c bill.c fred.c $ ls *.o bill.o fred.o
现在编写一个调用bill函数的程序。
首先,创建头文件声明我们的库文件中的函数,希望使用这个库文件的应用程序都必须包含。
然后,编辑调用程序(program.c)。
1 void bill (char *);
2 void fred(int);
3
4 #include "lib.h"
5
6 int main
7 {
8 bill ("Hello World");
9 exit(0);
10 }
编译并测试这个程序:
$ cgcc -c program.c $ cgcc -o program.o bill.o $ ./program bill : we passed Hello World $
创建并使用一个库文件:
$ ar crv libfoo.a bill.o fred.o a - bill.o a - fred.o
在某些系统,要想成功地使用函数库,还需要为函数库生成一个内容表:
注:
在Linux中,如果我们使用的是GNU的软件开发工具,这一步就不是必需的(但做了也无妨)。
$ ranlib libfoo.a
我们的函数库现在即可使用了:
$ gcc -o program program.o libfoo.a $ ./program bill : you passed Hello World $
要查看目标文件、函数库或可执行文件里包含的函数,我们可以使用nm命令。
5. 共享库
程序使用共享库时,它的链接方式是这样的:
它本身不再包含函数代码,而是引用运行时可访问的共享代码。当编译好的程序被装载到内存中执行时,函数引用被解析并产生对共享库的调用,如果有必要共享库才被加载到内存中。
我们可通过运行工具ldd来查看程序需要的共享库:
$ ldd program
1.3 获得帮助
man命令可用来访问在线手册页。
可以通过特殊的程序info或通过emacs编辑器中的info命令来在线浏览全部的文档。
1.4 小结
这章刚看完的时候感觉不明不白的,等写完这篇blog的时候思路清晰了很多,有一些地方虽然还不是很理解,不过相信后面的几章会解开我的一些疑问。毕竟这一章只是作为入门,从宏观上对Linux各个方面有一个感性的认识。