内容提要:本文主要讨论 Linux 下的 C 语言编程环境,包括编辑器、编译器、Make、调试器等, 最主要是 vi 编辑器的使用。通过介绍 Linux 下 C 语言编程的基本工具,使读者可以很快地进入到 Linux 下编程环境中来。 关键字:编程环境、编程风格、发展前景 引言:Linux 是多用户、多进程的操作系统,它具有稳定、安全、高效、开放性、免费、兼容 性和可移植性好等优点。正是由于这些优点,近年来,Linux 的发展很快,在服务器市场上足以和 微软的 Windows 抗衡。Linux 也非常适合用于大型分布式计算,如动画制作、科学计算、数据库及 文件服务器等。
1 Linux 的发展和特点
Linux 最初是专门为基于 Intel 处理器的个人计算机而设计的。Linux 的前身是赫尔辛基大学 (University of Helsinki)一位名叫 Linus Torvald 的计算机科学系学生的个人项目。Linus 把 Linux 建立在一个基于 PC 机上运行的、小的、名为 Minux 的 UNIX 基础之上,Minux 突出体现了 UNIX 的各种特性。而 Linux 又在 Minux 之上增加和完善了 UNIX 系统的各种特性。后来 Linus Torvald 通 过新闻组(USENET)宣布这是一个免费的系统,主要在 x86 电脑上使用,希望大家一起来将它完 善,并将源代码放到了芬兰的 FTP 站点上供人免费下载。本来他想把这个系统称为 freax,可是 FTP 的工作人员认为这是 Linus 的 Minux,就用 Linux 这个子目录来存放,于是它就成了 Linux。这时的 Linux 只有核心程序,还不能称作是完整的系统,不过由于许多专业用户(主要是程序员)自愿地 开发它的应用程序,并借助 Internet 拿出来让大家一起修改,所以它的周边程序越来越多,Linux 本 身也逐渐发展壮大起来。 近些年来,Linux 操作系统得到了迅猛的发展,这与 Linux 具有的良好特性是分不开的。Linux 包含了 UNIX 的全部功能和特性,在中高端服务器上得到了广泛的应用,国际上很多有名的硬、软 件厂商都与之结盟、捆绑,将其用作产品的操作系统。 Linux 操作系统的特点可总结为以下几点。 1. 自由软件 Linux 项目从一开始就与 GNU 项目紧密结合起来, 它的许多重要组成部分直接来自 GNU 项目。 Linux 可以说是作为开放源码的自由软件的代表,便于定制和再开发。在遵从 GPL 版权协议的条件 下,各部门、企业、单位或个人就可以免费得到 Linux 源程序,并根据实际需要和使用环境对 Linux 系统进行裁剪、扩充、修改,再开发和发布程序的源码,并公布在 Internet 上。这样就激发了世界 范围内热衷于计算机事业的人们的创造力。通过 Internet,这一软件的传播和使用迅速蔓延。Linux 操作系统可以从互联网上很方便地免费下载,且由于可以得到 Linux 的源码,因而操作系统的内部 逻辑可见,这样就可以准确地查明故障原因,及时采取相应对策。 2. 开放性 开放性是指系统遵循世界标准规范,特别是遵循开放系统互连(OSI)国际标准。凡遵循国际 标准所开发的硬件和软件,都能彼此兼容,可方便地实现互连。 3. 多用户 系统资源可以被不同用户各自拥有使用,即每个用户对自己的资源(例如:文件、设备)有 特定的权限,互不影响,允许多个用户从相同或不同终端上同时使用同一台计算机。 4. 多任务 是指计算机允许多个程序同时执行,而且各个程序的运行互相独立。Linux 系统调度每一个进 程,平等地访问微处理器。由于 CPU 的处理速度非常快,启动的应用程序看起来好像在并行运行, ※ 1 ※
事实上,从处理器执行一个应用程序中的一组指令到 Linux 调度微处理器再次运行这个程序之间只 有很短的时间延迟,用户是感觉不出来的。Linux 充分利用了 x86CPU 的任务切换机制,实现了真 正多任务、多用户环境,允许多个用户同时执行不同的程序,并且可以给紧急任务以较高的优先级。 5. 与 UNIX 有良好的兼容性 Linux 是从一个比较成熟的操作系统 UNIX 发展而来的,UNIX 上的绝大多数命令都可以在 Linux 里找到并有所加强。可以认为它是 UNIX 系统的一个变种,因而 UNIX 的优良特点如可靠性、 稳定性以及强大的网络功能, 强大的数据库支持能力以及良好的开放性等都在 Linux 上一一体现出 来。 且在 Linux 的发展过程中, Linux 的用户能很好地从 UNIX 团体贡献中获利, 它能直接获得 UNIX 相关的支持和帮助。现在,Linux 已成为具有全部 UNIX 特征、完全符合 POSIX 标准的操作系统。 POSIX 是基于 UNIX 的第一个操作系统簇国际标准,该标准最初由 IEEE 开发,部分已经被 ISO 接 受为国际标准。POSIX.1 和 POSIX.2 分别定义了 POSIX 兼容操作系统的 C 语言系统接口以及 shell 和工具标准。这两个标准是通常提到的标准。Linux 遵循这一标准,这使 UNIX 下许多应用程序可 以很容易地移植到 Linux 下,相反也是这样,所有 UNIX 的主要功能都有相应的 Linux 工具和实用 程序。对于 UNIX System V 来说,其软件程序源码在 Linux 上重新编译之后就可以运行;而对于 BSD UNIX,它的可执行文件可以直接在 Linux 环境下运行。所以,Linux 实际上就是一个完整的 UNIX 类操作系统。Linux 系统上使用的命令多数都与 UNIX 命令在名称、格式、功能上相同。 6. 性能和稳定性好 在相同的硬件环境下,Linux 可以像其他优秀的操作系统那样运行,提供各种高性能的服务, 可以作为中小型 ISP 或 Web 服务器工作平台。Linux 可以运行在 386 以上及各种 RISC 体系结构机 器上。Linux 最早诞生于微机环境,一系列版本都充分利用了 x86CPU 的任务切换能力,使 x86CPU 的效能发挥得淋漓尽致,而这一点连 Windows 都没有做到。Linux 能运行在笔记本电脑、PC、工作 站,甚至巨型机上,而且几乎能在所有主要 CPU 芯片搭建的体系结构上运行(包括 Intel、AMD、 HP-PA、MIPS、PowerPC、UltraSPARC、ALPHA 等 RISC 芯片) ,其性能远远超过了 Windows NT 操作系统目前所能达到的水平。 7. 可靠的系统安全 Linux 上包含了大量网络管理、网络服务等方面的工具,用户可利用它建立起高效和稳定的防 火墙、路由器、工作站、Intranet 服务器及 WWW 服务器。Linux 还包含了大量系统管理软件、网络 分析软件、网络安全软件等。由于 Linux 源码是公开的,所以可消除系统中是否有后门的疑惑。这 对于关键部门、关键应用来说是至关重要的。Linux 采取了许多安全技术措施,包括对读、写进行 权限控制、带保护的子系统、审计跟踪、核心授权等,这为网络多用户环境中的用户提供了必要的 安全保障。 8. 可移植性好 可移植性是指代码从一种体系结构移植到另外一种不同的体系结构上的方便程度。Linux 是一 个可移植性非常好的操作系统,它广泛支持了许多不同体系结构的计算机,能够在从微型计算机到 大型计算机的任何环境中和任何平台上运行,包括 Intel、AMD、ARM、Mips 等。可移植性为运行 Linux 的不同计算机平台与其他机器进行准确而有效的通信提供了便利,不需要另外增加特殊的和 昂贵的通信接口。 9. 多种用户界面 主要有命令接口、系统调用和图形界面。Linux 的传统用户界面是基于文本的命令行界面,即 shell,它既可以联机使用,也可存在文件上脱机使用。shell 有很强的程序设计能力,用户可方便地 用它编制程序,从而为扩充系统功能提供了更高级的手段。可编程 Shell 是指将多条命令组合在一 起,形成一个 shell 程序,这个程序可以单独运行,也可以与其他程序同时运行。系统调用给用户提 供编程时使用的界面,用户可以在编程时直接使用系统提供的系统调用命令。系统通过这个界面为 用户程序提供低级、高效率的服务。Linux 还为用户提供了丰富的图形用户界面,如 GNOME、KDE 等。它利用鼠标、菜单、窗口、滚动条等设施,给用户呈现一个直观、易操作、交互性强的友好的 图形化界面。Linux 的 X Window 可以做 Windows 下的所有事情,而且更有趣、更丰富,用户甚至
可以在几种不同风格的窗口之间来回切换。 10. 支持多种文件系统 Linux 可以支持十多种文件系统类型:JFS、ReiserFS、ext、ext2、ext3、ISO9660、XFS、Minx、 MSDOS、UMSDOS、VFAT、NTFS、HPFS、NFS、SMB、SysV、PROC 等。在 Linux 系统中,每个 分区都是一个文件系统,都有自己的目录层次结构,Linux 可以将这些文件系统直接挂载为系统的 一个目录。Linux 支持多种文件系统,这样使得它更加灵活,并可以和许多其他种操作系统共存。 virtual File System(虚拟文件系统)使得 Linux 可以支持多个不同的文件系统。由于系统已将 Linux 文件系统的所有细节进行了转换,所以 Linux 核心的其他部分及系统中运行的程序将看到统一的文 件系统。Linux 的虚拟文件系统允许用户能同时透明地安装许多不同的文件系统。虚拟文件系统是 为 Linux 用户提供快速且高效的文件访问服务而设计的。随着 Linux 的不断发展,它所支持的文件 格式系统也会越来越多。 11. 开发功能强 Linux 支持一系列的 UNIX 开发,Linux 已经具有全部 UNIX 特征,它是一个完整的 UNIX 开发 平台,几乎所有的主流程序设计语言都已移植到 Linux 上并可免费得到,如 C、C++、Fortran77、 ADA、PASCAL、Modual2 和 3、Tcl/TkScheme、SmallTalk/X 等。 12. 具有强大的网络功能 支持 Internet。Linux 免费提供了大量支持 Internet 的软件,Internet 是在 UNIX 领域中建立并繁 荣起来的, 在这方面使用 Linux 是相当方便的, 用户能用 Linux 与其他人通过 Internet 网络进行通信。 支持文件传输。用户能通过一些 Linux 命令完成内部信息或文件的传输。支持远程访问。Linux 不 仅允许进行文件和程序的传输,它还为系统管理员和技术人员提供了访问其他系统的窗口。通过这 种远程访问的功能,一位技术人员能够有效地为多个系统服务。实际上,Linux 就是依靠互联网才 迅速发展了起来。它可以轻松地与 TCP/IP、LANManager、Windows for Workgroups、Novell Netware 或 Windows NT 网络集成在一起。Linux 不仅能够作为网络工作站使用,还可以胜任各类服务器,如 X 应用服务器、文件服务器、打印服务器、邮件服务器、新闻服务器等等。 13. 设备独立性 设备独立性是指操作系统把所有外部设备统一当成文件来看待,只要安装它们的驱动程序,任何 用户都可以像使用文件一样,操纵、使用这些设备,而不必知道它们的具体存在形式。具有设备独立 性的操作系统,通过把每一个外围设备看作一个独立文件来简化增加新设备的工作。Linux 是具有设 备独立性的操作系统,它的内核具有高度适应能力,随着更多的程序员加入 Linux 编程,会有更多硬 件设备加入到各种 Linux 内核和发行的版本中来。 14. 虚拟内存 虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,当内存占用完时,电脑就会自动调用 硬盘来充当内存,以缓解内存的紧张。当物理内存满时(实际上,在内存满之前) ,虚拟内存就在硬 盘上创建了。当物理内存用完后,虚拟内存管理器选择最近没有用过的,低优先级的内存部分写到 交换文件上。这个过程对应用程序是隐藏的,应用程序把虚拟内存和物理内存看作是一样的,这样 就提高了系统的效率。 15. 动态链接共享库 每个应用程序共享一个公用的、运行时可调用的子程序库,而不是保留各自的软件备份,这样 可以为系统节省大量空间。在/lib 目录下,有许多以.so 作后缀的文件,这就是 Linux 系统应用的动 态链接库,以 so 结尾,即 Shared Object,共享对象(在 Linux 下,静态函数库是以.a 作后缀的) 。X Window 作为 Linux 下的标准图形窗口界面,它本身就采用了很多的动态链接库(在/usr/X11R6/lib 目录下) ,以方便程序间的共享,节省占用空间。著名的 Apache 网页服务器,也采用了动态链接库, 以便扩充程序功能。这就是动态链接的好处。
2 Linux C 简介
Linux 作为一个优秀的操作系统,一项非常重要的功能就是支持系统调用。C 语言具有高速、灵活、简洁、可移植性好等特点,从而很快成为了世界上最受欢迎的编程语言之一。因而它和 Linux 很快形成了完美的结合,Linux 为 C 语言提供了很好的支持,为用户提供了一个强大的编程环境。 事实上,Linux 操作系统本身是用 C 语言写的,Linux 下的很多软件也是用 C 语言写的,特别是一 些著名的服务软件,比如 MySQL、Apache、Oracle 等。
C 语言的简介和特点
1963 年,剑桥大学将 ALGOL 60 语言发展成为 CPL(Combined Programming Language)语言。 1967 年, 剑桥大学的 Matin Richards 对 CPL 语言进行了简化, 于是产生了 BCPL 语言。 1970 年, AT&T 贝尔实验室的 Ken Thompson 将 BCPL 进行了修改,设计出较先进的并取名为 B 语言。并且他用 B 语 言写了第一个 UNIX 操作系统。1973 年,AT&T 贝尔实验室的 D.M.RITCHIE 在 B 语言的基础上最终 设计出了一种新的语言,他取了 BCPL 的第二个字母作为这种语言的名字,这就是 C 语言。 随着 C 语言在各种计算机上的快速推广, 从而出了许多 C 语言版本。 这些版本虽然是类似的, 但并不兼容。为了明确定义与机器无关的 C 语言,1989 年美国国家标准协会制定了 C 语言的标准 (ANSI C) 。在 ANSI 标准化后,C 语言的标准在相当长的一段时间内都基本保持不变,Normative Amendment1 在 1995 年开发了一个新的 C 语言版本,但是这个版本很少为人所知。ANSI 标准在 20 世纪 90 年代又经历了一次比较大的改进,这就是 ISO9899:1999(1999 年出版) 。这个版本就是 现在所说的 C99,成为现行的 C 语言标准。 C 语言之所以发展迅速,并且成为最受欢迎的语言之一,主要是因为它具有强大的功能。许多 著名的系统软件,如 UNIX/Linux、Windows 都是由 C 语言编写的。用 C 语言加上一些汇编语言子 程序,就更能显示语言的优势,像 PC-DOS、WORDSTAR 等就是用这种方法编写的。 总而言之,C 语言具有以下特点: 1. C 语言是中级语言 C 语言被程序员广泛使用的另一个原因是可以用它代替汇编语言。汇编语言使用的汇编指令, 是能够在计算机上直接执行的二进制机器码的符号表示。汇编语言的每个操作都对应为计算机执行 的单一指令。虽然汇编语言有给予程序员达到最大灵活性和最高效率的潜力,但开发和调试汇编语 言程序的困难是难以忍受的。非结构性使得汇编语言程序难于阅读、改进和维护。也许更重要的是, 汇编语言程序不能在使用不同 CPU 的机器间移植。C 语言同时具有汇编语言和高级语言的优势,它 把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以像汇编语言一样对位、字 节和地址进行操作,而这三者是计算机最基本的工作单元。 2. C 语言是结构式语言 结构式语言比非结构式语言更易于程序设计,用结构式语言编写的程序的清晰性使得它们更易 于维护。结构式语言的显著特点是代码及数据的模块化,即程序的各个部分除了必要的信息交流外 彼此独立。这种结构式方式可使程序层次清晰,便于使用、维护以及调试。语言是以函数形式提供 给用户的,这些函数可方便地调用,并采用多种循环、条件语句控制程序流向,从而使程序完全结 构化。在 C 语言中,除实现顺序、选择和循环三种基本结构的 9 条控制语句外,输入输出操作均由 标准库函数(不是 C 语言的组成部分)来实现。所以学习 C 语言,不仅要学习这 9 条控制语句和各 种运算符,而且要学习并掌握常用标准库函数的使用。 3. C 语言简洁、灵活,运算符和数据结构类型极其丰富 所有的高级语言都支持数据类型的概念。一个数据类型定义了一个变量的取值范围和可在其 上操作的一组运算。常见的数据类型是整型、字符型和实数型。虽然 C 语言有五种基本数据类型, 但与 Pascal 或 Ada 相比,它却不是强类型语言。C 程序允许几乎所有的类型转换。例如,字符型 和整 型 数 据 能够 自 由 地 混合 在 大 多 数表 达 式 中 进行 运 算 。 这在 强 类 型 高级 语 言 中 是不 允 许 的 。C 语言的另一个重要特点是它仅有 32 个关键字,这些关键字就是构成 C 语言的命令。和 IBM PC 的 BASIC 相比,后者包含的关键字达 159 个之多。 4. C 语言可移植性好 C 语言程序非常容易移植,可移植性表示为某种计算机写的软件可以用到另一种机器上去。举例来说,如果为苹果机写的一个程序能够方便地改为可以在 IBM PC 上运行的程序,则称为是可移 植的。几乎所有的计算机上都有 C 语言编译程序,这使用户可以很少改动甚至不加改动地将为一种 机器写的 C 语言源程序在另一种机器上编译执行。可移植性节省了时间和财力。 5. C 语言生成的目标代码质量高,程序执行效率高 C 语言具有各种各样的数据类型,并引入了指针概念,可以直接操纵硬件,使程序执行效率更 高,但这也使得初学者难于掌握它。用 C 语言编程,可以获得高效机器代码,其效率几乎接近汇编 语言代码。 6. C 语言适用范围大 C 语言最初被用于系统程序设计。一个系统程序是一大类程序的一部分,这一大类构成了计算 机操作系统及应用程序。通常被称为系统程序的有操作系统、翻译程序、编辑程序、汇编程序、编 译程序、数据库管理程序。随着 C 语言的普及,加之其可移植性和高效率,许多程序员用它设计各 类程序。而且 C 语言计算功能、逻辑判断功能也强大,可以实现决策目的。C 语言也有强大的图形 处理功能,支持多种显示器和驱动器。
4
4.1 Linux 程序设计基础知识
头文件 glibc_header 是 Linux 下的系统头文件。缺少了系统头文件的话,很多用到系统功能的 C 程序将 无法编译。假如用户在安装过程中少装了这些包,就会无法编译 C 源程序。在使用 C 语言和其他语 言进行程序设计的时候,需要头文件来提供对常数的定义和对系统函数及库函数调用的声明。对 C 语 言来说,这些头文件几乎永远保存在/usr/include 及其下级子目录里。那些依赖于所运行的 UNIX 或 Linux 操作系统特定版本的头文件一般可以在/usr/include/sys 或/usr/include/Linux 子目录里找到。其他 的程序设计软件也可以有一些预先定义好的声明文件,它们的保存位置可以被相应的编译器自动查找 到。 比如, 窗口系统的/usr/include/X1R6 子目录和 GNU C++编译器的/usr/include/g++ -2 子目录等。 X 在调用 C 语言编译器的时候,可以通过-I 编译命令标志来引用保存在下级子目录或者非标准位 置的头文件。用 grep 命令来查找含有某些特定定义与函数声明的头文件是很方便的。 头文件的保存位置如下: /usr/include:系统头文件 /usr/local/include:本地头文件4.2
函数库是一些预先编译好的函数的集合,那些函数都是按照可再使用的原则编写的。它们通常 由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况的函数(curses 库)等。 标准的系统库文件一般保存在/lib 或者/usr/lib 子目录里。编译时要告诉 C 语言编译器(更确切 地说是链接程序)应去查找哪些库文件。默认情况下,它只会查找 C 语言的标准库文件。库文件必 须遵守一定的命名规则,还必须在命令行上明确地给出来。 库文件的名字永远以 lib 这几个字母打头,随后是说明函数库情况的部分(比如用 c 表示这是 一个 C 语言库;而 m 表示这是一个数学运算库等) ,文件名的最后部分以一个句点(.)开始,然后 给出这个库文件的类型,如下所示: .a:传统的静态型函数库。 .so 和.sa:共享型函数库。 函数库一般分为静态和共享两种格式,用 ls /usr/lib 命令可以查看得到。在通知编译器查找某个 库文件的时候,既可以给出其完整的路径名,也可以使用-l 标志。 1. 静态库 函数库最简单的形式就是一组处于可以“拿来就用”状态下的二进制目标代码文件。当有程序 需要用到函数库中的某个函数时,就会通过 include 语句引用对此函数做出声明的头文件。编译器和 链接程序负责把程序代码和库函数结合在一起成为一个独立的可执行程序。如果使用的不是标准的 C 语言运行库而是某个扩展库,就必须用-l 选项指定它。 静态库也叫做档案(archive) ,它们的文件名都以.a 结尾。比如 C 语言标准库为/usr/lib/libc.a, X11 库为/usr/X11R6/lib/libX11.a 等。 建立和维护静态库的工作并不困难,用 ar(建立档案)程序就可以做到。另外要注意,应该用 gcc -c 命令对函数分别进行编译,尽量把函数分别保存到不同的源代码文件里。如果函数需要存取 普通数据,可以把它们放到同一个源代码文件里并使用在其中声明为 static 类型的变量。 GNU 的 C 函数库,即 glibc,是 Linux 上最重要的函数库,它定义了 ISO C 语言标准指定的所 有的库函数,以及由 POSIX 或其他 UNIX 操作系统变种指定的附加特色,还包括与 GNU 系统相关 的扩展。glibc 基于如下标准: (1)ISO C:C 语言的国际标准,即 ANSI C。 (2)POSIX:GNU C 函数库实现了 ISO/IEC 9945-1:1996(POSIX 系统应用程序编程接口,即 POSIX.1)指定的所有函数。该标准是对 ISO C 的扩展,包括文件系统接口原语、设备相关的终端 控制函数以及进程控制函数。同时,GUN C 函数库还支持部分由 ISO/IEC 9945-2:1993(POSIX Shell 和工具标准,即 POSIX.2)指定的函数,其中包括用于处理正则表达式和模式匹配的函数。 (3)Berkeley UNIX:BSD 和 SunOS。GNU C 函数库定义了某些 UNIX 版本中尚未标准化的函 数, 尤其是 4.2 BSD, BSD, BSD UNIX 系统 4.3 4.4 (即 Berkeley UNIX) 以及 SunOS (流行的 4.2 BSD 变种,其中包含有某些 UNIX System V 的功能) 。BSD 函数包括符号链接、select 函数、BSD 信号 处理函数以及套接字等等。 (4)SviD:System V 的接口描述。GNU C 函数库定义了大多数由 SviD 指定而未被 ISO C 和 POSIX 标准指定的函数。来自 System V 的支持函数包括进程间通信和共享内存、hsearch 和 drand48 函数族、fmtmsg 以及一些数学函数。 (5)XPG:X/Open 可移植性指南。GNU C 函数库遵循 X/Open 可移植性指南(Issue 4.2)以及 所有的 XSI(X/Open 系统接口)兼容系统的扩展,同时也遵循所有的 X/Open UNIX 扩展。 除 glibc 之外, 流行的 Linux 发行版本中还包含有一些其他的函数库, 这些函数库具有重要地位, 例如: (1)GNU Libtool:GNU Libtool 实际是一个脚本生成工具,它可以为软件包开发者提供一般性 的共享库支持。以前,如果源代码包的开发者要利用共享库的优点,则必须为每个软件包可支持的 平台编写定制的支持代码,并且还需要设计配置接口,以便软件包的安装程序能够正确选择要建立 的库类型。利用 GNU Libtool,则可以简化开发者的这一工作。它在一个单独的脚本中同时封装了 与平台相关的依赖性以及用户界面。GNU Libtool 可使每个宿主类型的完整功能可通过一般性的接 口获得,同时为程序员隐藏了宿主的特殊性。GNU Libtool 一致性接口是可靠的,用户不必阅读那 些晦涩的文档,只需运行软件包的配置脚本,而由 Libtool 完成繁复的工作,以便在每个平台上建立 共享库。 (2)CrackLib:CrackLib 为用户提供了一个 C 语言函数接口,利用这一函数,可避免用户选择 容易破解的密码。该函数库可在类似 passwd 的程序中使用。 (3)LibGTop:LibGTop 是一个能够获取进程信息以及系统运行信息的函数库,这些信息包括: 系统的一般信息、SYS V IPC 限制、进程列表、进程信息、进程映射、文件系统使用信息等。 图形文件操作函数库包括 libungif、libtiff、libpng、Imlib、libjpeg 等,可分别用来操作 GIF、 TIFF、PNG、JPEG 以及其他一些格式的图形文件。 2. 共享库 静态库的缺点是,如果在同一时间运行多个程序而它们又都使用着来自同一个函数库里的函数 时,内存里就会有许多份同一函数的备份,在程序文件本身也有许多份同样的备份。这会消耗大量 宝贵的内存和硬盘空间。 许多 UNIX 系统支持共享库,它同时克服了在这两方面的无谓消耗。对共享库和它们在不同系 统上实现方法的详细讨论超出了本书的范围,有兴趣的读者可以自行查找相关资料进行学习。 共享库的存放位置和静态库是一样的,但有着不同的文件后缀。在一个典型的 Linux 系统上, C 语言标准库的共享版本是 /usr/lib/libc.so N,其中 N 是主版本号。 共享库及其相关配置如下: /etc/ld.so.conf:包含共享库的搜索位置。 ldconfig:共享库管理工具,一般在更新了共享库之后要运行该命令。 ldd:可查看可执行文件所使用的共享库。 3. 函数库的保存位置 /lib:系统必备共享库。 /usr/lib:标准共享库和静态库。 /usr/i486-Linux-libc5/lib:libc5 兼容性函数库。 /usr/X11R6/lib:X11R6 的函数库。 /usr/local/lib:本地函数库。
4.3系统调用
系统调用是操作系统提供给外部程序的接口。在 C 语言中,操作系统的系统调用通常通过函数 调用的形式完成,这是因为这些函数封装了系统调用的细节,将系统调用的入口、参数以及返回值 用 C 语言的函数调用过程实现。在 Linux 系统中,系统调用函数定义在 glibc 中。 谈到系统调用时,需要注意如下几点: (1)系统调用函数通常在成功时返回 0 值,不成功时返回非零值。如果要检查失败原因,则要 判断 errno 这个全局变量的值,errno 中包含有错误代码。 (2)许多系统调用的返回值通常通过引用参数传递。这时,需要在函数参数中传递一个缓冲区 地址,而返回值就保存在该缓冲区中。 (3) 不能认为系统调用函数就要比其他函数的执行效率高。这是因为系统调用是一个非常耗时 的过程。
4.4帮助文档
1. man ma n , 即 manunal, 是 U NI X 系 统 手 册 的 电 子 版 本 。 根 据 习 惯 , U NI X 系 统 手 册 通 常 分 为 不 同 的 部 分 或 小 节( 即 section ) ,每 个 小 节 阐 述 不 同 的 系 统 内 容 。目 前 的 小 节 划 分 如 下: (1)命令:普通用户命令。 (2)系统调用:内核接口。 (3)函数库调用:普通函数库中的函数。 (4)特殊文件:/dev 目录中的特殊文件。 (5)文件格式和约定:/etc/passwd 等文件的格式。 (6)游戏。 (7)杂项和约定:标准文件系统布局、手册页结构等杂项内容。 (8)系统管理命令。 (9)内核例程:非标准的手册小节。便于 Linux 内核的开发而包含。 (10)其他手册小节。 l:PostgreSQL 数据库命令 n:TCL/TK 命令。 手册页一般保存在/usr/man 目录下,其中每个子目录(如 man1,man2,……,manl,mann)包含 不同的手册小节。可以使用 man 命令查看手册页。 man 命令行格式如下:
man [-acdfFhkKtwW] [-m system] [-pstring] [-C config_file] [-M path] [-P pager] [-S section_list] [section]name 常用的 man 命令行: $ man open $ man 7 man $ man ./myman.3 2. info Linux 中的大多数软件开发工具都是来自自由软件基金会的 GNU 项目, 这些工具软件件的在线 文档都以 info 文件的形式存在。info 程序是 GNU 的超文本帮助系统。 info 文档一般保存在/usr/info 目录下,使用 info 命令查看 info 文档。 要运行 info,可以在 shell 提示符后输入 info。 info 帮助系统的初始屏幕显示了一个主题目录,用户可以将光标移动到带有*的主题菜单上面, 然后按回车键,进入该主题,也可以键入 m,后面跟着输入主题菜单的名称而进入该主题。例如, 键入 m,然后再键入 gcc,进入 GCC 主题。 如果要在主题之间跳转,则必须记住如下的几个命令键: * n:跳转到该节点的下一个节点。 * p:跳转到该节点的上一个节点。 * m: 指定菜单名而选择另外一个节点。 * f:进入交叉引用主题。 * l:进入该窗口中的最后一个节点。 * TAB:跳转到该窗口的下一个超文本链接。 * RET:进入光标处的超文本链接。 * u:转到上一级主题。 * d:回到 info 的初始节点目录。 * h:调出 info 教程。 * q:退出 info。 3. HOWTO 可供用户参考的联机文档的另一种形式是 HOWTO 文件, 这些文件位于系统的/usr/doc/HOWTO 目录下。HOWTO 文件的文件名都有一个-HOWTO 后缀,并且都是文本文件。 每一个 HOWTO 文件包含 Linux 某一方面的信息,例如它支持的硬件或如何建立一个引导盘。
要想查看这些文件,进入/usr/doc/HOWTO 目录,使用 more 命令,具体形式如下:
$ cd /usr/doc/HOWTO; more topic-name-HOWTO
另 外 , HOWTO 文 档 还 有 其 他 格 式 的 文 件 , 例 如 HTML 和 PS 等 , 保 存 在
Linux 的内核文档一般包含在内核源代码中,目录如下: /usr/src/Linux-2.x.x/Documentation
/usr/doc 目录下包含有大量与特定软件或函数库相关的说明性文档。
5
5.1
Linux 下 C 语言编程环境
vi 编辑器的使用 1. vi 简介
vi(Very involved) ,意思是包含全部。对 UNIX 操作系统而言,大多数 UNIX 系统都具有各自 类型的编辑器,但是实际使用的工具不尽相同,这取决于使用的 UNIX 系统。所有 Linux 操作系统 机器上都安装有 vi 可视化编辑器,一旦掌握 vi 的使用技巧,用户就可以在所有的 Linux 操作系统中 随意编辑文件。
在机器上安装 vi 无需特别的安装路径。当安装系统的时候,vi 自动会出现。因为系统管理员需 要使用 vi 处理很多工作,包括创建系统文本等。Red Hat 的 Linux 在系统中提供了安装特定编辑器 的选择,但是在 Linux 操作系统不安装 vi 的情况相当少见。 2. 进入 vi在系统提示字符(如$、#)下敲入 vi <文件名称>,vi 可以自动载入所要编辑的文件或开启 一个新文件(如果该文件不存在或缺少文件名) 。进入 vi 后屏幕左方会出现波浪符号,凡是行首有 该符号就代表此行目前是空的。 现在用户可以动手试用一下。首先,在工作站打开一个终端窗口,只需在$提示中输入 vi 然后
按回车键就可以启动 vi 编辑器。 不会显示出来。
接着,将看到弹出一个页面左下角有一个~符号的空白文件。当对文件保存之后,这些符号就 若要编辑某个文件或者为一空白文件命名,可输入 vi filename。filename 可以是一个已经存在 的文件名或者是一个给新文件指定的名称。 3. 三种模式
在介绍如何使用 vi 之前,了解 vi 具有三种基本模式是很重要的。这三种基本模式为输入模式、
命令模式和底行模式。在命令模式下输入的按键将作为命令来处理,如输入 a,vi 即认为是在当前位置插入字符。而在输入模式下,vi 则把输入的按键当作插入的字符来处理。命令模式切换到输入 模式只需键入相应的输入命令即可(如 a,A) ,而要从输入模式切换到命令模式,则需在输入模式 下按 Esc 键,如果不知道现在是处在什么模式下,可以多按几次 Esc 键,系统如发出嘟嘟声就表示 已处于命令模式下了。在底行模式下可以将文件保存或退出 vi,也可以设置编辑环境,如寻找字符
串、列出行号等。在命令模式下按:键可以切换到底行模式。一般在使用时把 vi 简化成两个模式,
就是将底行模式也算作是命令行模式。 在默认状态下,vi 以命令模式启动,因此输入命令时不会显示文字,除非输入命令切换至输入 模式。大多数 vi 命令不会在屏幕上显示任何东西,用户只需要知道它们的工作过程就足够了。 以下命令可以从命令模式进入输入模式: (1)插入(insert) 。 i:这是一个输入命令,即从光标所在位置前面开始插入文字,光标后的文字随新增文字向向移 动。如果是一个空白文档,文字将会输入在文档的左上角。 I:在行命令开始处的输入模式,即在当前行的开始处输入文字。与 Word 中的按下键后输入文 字类似。 (2)新增(append) 。 a:这是一个新增命令,即从光标所在位置后面开始新增文字,光标后的资料随新增文字向后移 动。 A:这是一个新增到行命令的操作,即从光标所在行最后面的地方开始新增文字。这与 Word 中的按下键后输入文字类似。 (3)开始(open) 。 o:这是一个命令之下的打开行命令,即在光标所在行下面新增一行并进入输入模式。 O:这是一个命令之上的打开命令,即在光标所在行上方新增一行并进入输入模式。 4. 退出 vi 在命令模式下键入:q,:q!,:wq 或:x(注意:号) ,就会退出 vi。其中:wq 和:x 是存盘退出,而:q 是直接退出。如果文件已有新的变化,vi 会提示用户保存文件而:q 命令也会失效,这时可以用:w 命 令保存文件后再用:q 退出,或用:wq 或:x 命令退出,如果不想保存改变后的文件,就需要用: q!命令, 这个命令将不保存文件而直接退出 vi。
5. 基本编辑 配合一般键盘上的功能键,如方向键、Insert 键、Delete 键等等,就可以利用 vi 来编辑文件了。 当然 vi 还提供其他许多功能让文字的处理更为方便。 (1)删除与修改命令。 x:删除光标所在字符。 dd:删除光标所在的行。 r:修改光标所在字符,r 后接要修改的字符。 R:进入取替换状态,新增文字会覆盖原先文字,直到按 Esc 键回到命令模式下为止。 s:删除光标所在字符,并进入输入模式。 S:删除光标所在的行,并进入输入模式。 dw:删除文字命令,即删除光标处的文字。 D:删除到行末端,即删除从光标所在位置到行末端的所有文本。 cw:改变文字命令,即光标所有位置的文字将随着输入文字而改变,直到按下 Esc 键。 这些指令的大多数都可以通过组合来提高其功能。例如,如果输入 2dd,vi 将删除两行文本。 (2)剪切与粘贴等操作。 与其他很多编辑器一样,用户可以在文档中剪切与粘贴文本。以下命令是可以使用的最为简单 的剪切与粘贴操作。 yy:复制行命令。光标所在行的文本将被复制到类似剪切板的缓冲器,可以使用多个复制命令 更改这一命令以将多行文字剪切到缓冲器。 yl:复制字符命令。光标所在行的字符将被复制到类似剪切板的缓冲器,可以使用多个复制命 令更改这一命令以将多行字符剪切到缓冲器。 p:后放置命令。在当前光标位置之后放置或粘贴缓冲器中的内容。对于复制行命令,缓冲器的 内容将被粘贴在当前行之后。对于复制字符行命令,缓冲器内容将被粘贴在光标的右边。 P:前放置命令。在当前光标位置之前放置或粘贴缓冲器的内容。对于复制行命令,缓冲器的 内容将被粘贴在当前行之前。对于复制字符行命令,缓冲器内容将被粘贴在光标的左边。 使用复制和放置指令时,也可以通过字符指令使用多个缓冲器或剪切板。这些字符可为 a-z,并 且只能是小写字母。例如,ayy 将当前行内容复制到缓冲器 A,ap 命令将缓冲器 A 的内容粘贴在当 前行之前。 vi 中最为重要的命令是 undo 指令。这一命令十分简单,只需要按下 u 键就可以撤消最近使用 的一次指令。 与 undo 命令类似的是 redo 命令。按下句号键(.)将会重新键入最近的指令。例如,如果使用 cw 来改变一个文字,可以查找这一文字然后使用句号(.)来改变这一文字。 (3)查找与替代命令。 /查找字符。先按/键,再输入想寻找的字符,如果第一次找的关键字不是所要找的,可以一直 按 n,往后寻找到要找的关键字为止。按大写 N 则向前查找。 ?查找字符。先按?键,再输入想寻找的字符,如果第一次找的关键字不是所要找的,可以一直 按 n,往前寻找到要找的关键字为止。按大写 N 则向后查找。 :%s/find_text/replace_text/ 可以改变查找命令为一个查找与替代命令。上面的命令告诉 vi 查询文档中所有行。/find_text 命令与以上的查询命令类似,当其后缀为/replace_text/时,/find_text 操作结果的第一行将会被替代。 为了将/find_text 所有内容被替代,可以增加一个 g(全局) ,比如:%s/find_text/replace_text/g。 :3,7s/old_string/new_string/ 仅将文件中的第 3 行到第 7 行中的 old_string 替换成 new_string。 :1,$s/^M//g 将 dos 格式文本转成 UNIX 格式文本。其中^M 是指按组合键 Ctrl+V+M,表示回车。 g/^/s//NewString/g :%s/^/NewString/g 在文本每行的行首添加 NewString 字符串。 :g/$/s//NewString/g :%s/$/NewString/g 在每行的行尾添加 NewString 字符串。 :3,$s/^/NewString/ 从文本的第 3 行至最后一行的行首全部插入 NewString 字符串。 注意,其中 s 为表示替换动作,%表示所有行,g 表示全文,^表示行首或段首,$表示行尾或段 尾。
注意,只有输入内容完全匹配的情况下,才可以查找到所要查找的内容。vi 不支持混合查找或者 模糊查找。 (4)光标移动命令。 在 PC 机上输入和编辑都可以在输入模式下完成。例如要删除字符,直接按 Delete 键就可以了。 而插入状态与取代状态可以直接用 Insert 键切换。这些指令几乎是每台终端机都能用,而不仅仅在 PC 上。在命令模式下移动光标的基本指令是 h,j,k,l。也就是说,要移动光标只要直接用方向键 就可以了,而不论是在命令模式或输入模式下。 (5)浏览命令。 接下来学习 vi 中的浏览命令。以命令模式在文档中移动,可以使用以下的命令: h:将一个文字移动到左边。 j:往下移动一个文字。 k:往上移动一个文字。 l:将一个文字移动到右边。 Ctrl+f:向下移动一页指令。这将使得光标在文本中向下移动一页。 Ctrl+b:向后移动一页指令。这将使得光标在文本中向后移动一页。 Ctrl+u:向下移动半页指令。这将使得光标在文本中向下移动半页。 Ctrl+d:向上移动半页指令。这将使得光标在文本中向上移动半页。 ^:行命令开始处。光标将会移动到行的开始处。 $:行命令结束处。光标将会移动到行的结束处。 w:移动到上一个文字的开始。 b:移动到下一个文字的开始。 e:文字末端指令。 G:移动到文件的末端。 数字 0:移到文章的开头。 Ctrl+g:列出光标所在行的行号。 #G:移动光标至文章的第行行首(#表示一个数字) 。例如,5G 表示移动光标至文章的第 5 行 行首。 #:#号表示一个数字,在进入底行模式后输入一个数字,再按回车键就跳到该行,如输入数字 15,再回车,就会跳到文章的第 15 行。
(6)加密和解密文件。 在命令模式输入:X 命令,接着输入密码、确认输入密码,最后输入:wq 命令保存退出。文件就 被加密了。 经过上面方法加密后的文件变成密文文件。要阅读原来的明文,则在打开文件后,会提示用户 输入密码。如果密码输入正确,就能看到原来的明文。另外可以看到在最后的状态行上有此文件已 被加密的提示。 取消加密的方法很简单。在命令模式输入“:X”命令,首先会提示输入密码,这时直接敲回车 键。接下来在提示重复输入密码时也直接敲回车键,最后输入:wq 命令保存退出。这样文件的加密 就被取消了。 ※ 11 ※
6. 助力编程 (1)语法加亮。在 vi 中编写程序,如果为了方便想开启语法加亮功能,只需在命令模式下输 入:syntax on 即可。而如果想关闭语法加亮功能,就在命令模式下输入:syntax off 即可。 (2)快速查看函数帮助。在用 vi 阅读和编写程序(主要是指 C 或 C++程序)时,如果需要了 解某个函数的具体功能,可以将光标移到该函数上,然后在命令模式下输入 K,就可以调动 Linux Programmer's Manual 中对此函数的 man 帮助。 (3)ctags 命令。在阅读和编写 C 或 C++程序时,可用 ctags 命令对当前目录下的 C 源程序进 行扫描。命令$ ctags *.c 将为当前目录下的.c 文件生成 tags 文件,然后使用“ta 函数名”命令来快 速打开相应函数所在文件,并将光标定位在对应函数的开头。 (4)自动对齐。在命令模式下使用:set ai 命令可以让程序中各行自动对齐。 (5)显示匹配。在编程中{}、[]、()常常是成对出现的,而且常常有多层的嵌套,很容易遗漏 和失误,这样一来显示匹配就显得非常有用。在命令模式下使用:set sm 命令会在用户键入)、]、} 时显示出对应匹配的{、[、(。 (6)缩写文本。在编程中常常要输入一些重复且很长的信息,比如较长的名词和公司信息等, 这时可以用 vi 的缩写功能。 它可以将一个很长的词用一个很短的缩写来代替。 比如一个较长的 URL, 可以给它一个缩写,在命令模式下使用:ab myurl http://www.123456.com,然后在插入模式下输入 myurl 后,myurl 就会自动变成刚才定义的那个长的 URL。另外,在插入模式下输入:una myurl,则 是取消 myurl 这个缩写。 (7)set 选项。使用:set 可以设置 vi 的环境变量。vi 的环境变量有很多。使用:set all 可以显示 所有环境变量。使用“:set 变量名及参数”可以设置对应的环境变量。 下面的命令可显示行号。 :set nu 下面的命令可将文件设为只读。 :set readonly 下面的命令使 vi 在“:n”和“:!”命令之前都自动保存文件。 :set autowrite 下面的命令显示用户处在什么模式下。 :set showmode 而:set noshowmode 则关闭此显示。 vi 环境变量还有很多。了解它们,将给用户使用 vi 带来更多方便。用户可以通过 vi 的联机帮 助查到对应的环境变量的详细作用。 vi 的宏提供了更强大的功能,用户可以根据自己的需要来定制宏,然后通过宏来完成事先定义 好的一整套操作。用“map”来定义一个宏,用“unmap”来删除。在熟悉了 vi 的基本命令后,将 这些命令组合起来就能完成复杂的工作。如果再将这些命令的组合定义成宏的话,就可以方便用户 经常性地调用了。 7. vi 常用的指令 (1)新增(append) 。
a:从光标所在位置后面开始新增资料,光标后的资料随新增资料向后移动。 A:从光标所在列最后面的地方开始新增资料。 (2)向后(back) 。 b:移动到下个字的第一个字母(以所有可能的字符为分隔符) 。 B:移动到下个字的第一个字母(以回车和空格为分隔符) 。 (3)修改(change)。 c:删除文字后,并且进入插入模式。要与其他命令一起使用。 如:cl,ch,cj,ck,cw,cb,cW,cB,c0,c$,c(,c),c{,c}。 C:删除光标到该列结束为止所有的文字,并且进入插入模式。
(4)删除(delete) 。 d:删除文字后,还是在编辑模式。要与其他命令一起使用。 如:dl,dh,dj,dk,dw,db,dW,dB,d0,d$,d(,d),d{,d}。 D:删除光标到该行结束为止所有的文字。 (5)最后(end) 。
e:光标所在位置到该字的最后一个字母(以所有的可能的字符为分隔符) 。 E:光标所在位置到该字的最后一个字母(以回车和空格为分隔符) 。 (6)插入(insert) 。
i:从光标所在位置前面开始插入资料,光标后的资料随新增资料向后移动。 I:从光标所在列的第一个非空白字母前面开始插入资料。 (7)下一个(next) 。 n:配合/&?使用,重复一次。 N:配合/&?使用,反方向重复一次。 (8)开始(open) 。 o:在光标所在列下方新增一列并进入输入模式。 O:在光标所在列上方新增一列并进入输入模式。 (9)放置(put) 。 p:后放置命令。在当前光标位置之后放置或粘贴缓冲器的内容。对于复制行命令,缓冲器的内 容将被粘贴在当前行之后。对于复制字符行命令,缓冲器内容将被粘贴在光标的右边。
P:前放置命令。在当前光标位置之前放置或粘贴缓冲器的内容。对于复制行命令,缓冲器的
内容将被粘贴在当前行之前。对于复制字符行命令,缓冲器内容将被粘贴在光标的左边。 (10)替换(replace) 。 r:修改光标所在字符,r 后接要修正的字符。 R:进入取替换状态,新增文字会覆盖原先文字,直到按 Esc 键回到指令模式下为止。 (11)撤消(undo) 。 u:撤消。
cn w. ww
U:恢复光标所在行(如果光标所在行没有改变,则光标跳到最近的有改变过的行)的所有改
(12)可视化的选择(visual) 。 v:一个字符一个字符地选择。 V:一行一行地选择。 (13)字符(word) 。 W:光标所在位置到下个字的第一个字母(以回车和空格为分隔符) 。 (14)复制(yank) 。
w :光标所在位置到下个字的第一个字母(以所有的可能的字符为分隔符) 。
y:复制命令。要与其他命令一起使用,如:yl,yh,yj,yk,yw,yb,yW,yB,y0,y$,y(,y), y{,y}。 Y:复制一行命令。 (15)vi 其他常用指令。 fx:往右移动到 x 字符上。 Fx:往左移动到 x 字符上。
gg:移动到文件的第一行的第一个字符。 G:移动到文件的最后一行的第一个字符。 h:光标左移一个字符。 H:移动到视窗的第一行。 ※ 13 ※
j:光标下移一行。 J:删除光标所在行的下面那一行。 k:光标上移一行。
K:快速查看函数帮助。在用 vi 阅读和编写程序(主要是指 C 或 C++程序)时,如果需要了解
某个函数的具体功能,可以将光标移到该函数上,然后在命令模式下输入 K,就可以调动 Linux Programmer's Manual 中对此函数的 man 帮助。 l:光标右移一个字符。 L:光标移动到视窗的最后一行。 M:光标移动到视窗的中间那一行。 Q:进入 ex 模式。 s:删除光标所在字符,并进入输入模式。 S:删除光标所在的行,并进入输入模式。 tx:往右移动到 x 字符前。 Tx:往左移动到 x 字符前。 x:删除光标后面的字符。 X:删除光标前面的字符。
ZZ:与:x 和:wq 这两个命令功能相同。 分号(;) :配合 f&t 使用,重复一次。 逗号(,) :配合 f&t 使用,反方向重复一次。
句号(.) :重做最近一次使用过的命令。 $:光标所在位置到该行的最后一个字母。 0:光标所在位置到该行的第一个字母。 ):光标所在位置到下个句子的第一个字母。 (:光标所在位置到该句子的第一个字母。 }:标所在位置到该段落的最后一个字母。 {:光标所在位置到该段落的第一个字母。 Ctrl+d:向下半页。 Ctrl+f:向下一页。 Ctrl+u:向上半页。 Ctrl+b:向上一页。 c 和 d 的区别是 c 进入插入模式,d 则留在编辑模式。 dw:删除文字命令,即删除光标处的文字,并进入插入模式。
dd:删除行命令,即删除光标所在的行。 cc:删除行命令,即删除光标所在的行,并进入插入模式。 cw:改变文字命令,即光标所在位置的文字将随着输入文字而改变,直到按下 Esc 键。 2dd 或 d2d:删除两行文本。 #l:光标移到该行的第#个位置,如:5l,56l。 c#w:更改#个字。例如,c3w 表示更改 3 个字。 yy:复制行命令。光标所有行的文本将被复制到类似剪切板的缓冲器。注意到可以使用多个复
制命令更改这一命令以将多行文字剪切到缓冲器。
yl:复制字符命令。光标所有行的字符将被复制到类似剪切板的缓冲器。可以使用多个复制命 令更改这一命令以将多行字符剪切到缓冲器。 n-:减号移动到上一列的第一个非空白字元前面,加上数字可以指定移动到以上 n 行。
n+:加号移动到下一列的第一个非空白字元前面,加上数字可以指定移动到以下 n 行。 nG:直接用数字 n 加上大写 G 移动到第 n 行。 ※ 14 ※
n(:光标往前移动 n 个句子,句子由!、.、?三种符号来界定。 n):光标往后移动 n 个句子,句子由!、.、?三种符号来界定。 n{:光标往前移动 n 个段落,段落是以段落间的空白列界定。
n}:光标往后移动 n 个段落,段落是以段落间的空白列界定。 xp:交换两个字符。 ddp:交换两行。 Ctrl+v:可视化的选择(visual) ,逐块地选择。 Ctrl+g:列出光标所在行的行号。 Ctrl+a:光标所在数字加 1。 Ctrl+c:取消一个命令的执行。 以上涉及到的例子和指令只是 vi 功能的一小部分。用户可以一起执行指令串,以标记方式复制 和粘贴文本,或者使用 sed 指令。还可以将 shell script 的输出或其他指令插入到文档中。 vi 是类 UNIX 操作系统上常用的缺省编辑器。了解了 vi,用户就能利用它高效地编辑文件。
5.2
GCC 编译器的介绍
Linux 中最重要的软件开发工具是 GCC(GNU C Compiler) 。它是 GNU 的代表作品之一。GCC 是可以在多种硬件平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均要 高 20%~30%。 GCC 的基本用法: gcc [options] [filenames] 这条命令使 GCC 在给定的文件上,执行编译选项指定的操作。options 是选项列表,filenames 是文件列表。下面用例子来说明如何使用 GCC。 例如有 main.c 和 fac.c 两个源文件,现在要编译生成一个计算阶乘的程序。 //fac.c #include #include int fac (int n) { return n<=1?1:fac (n - 1) * n; } //main.c #include #include int fac (int n); int main (int argc, char **argv) { if (argc < 2) { printf ("Usage: %s n\n", argv [0]); return -1; } else { int n = atoi (argv[1]); printf ("Factorial of %d is %d.\n", n, fac (n)); } return 0; } 利用如下的命令可编译生成可执行文件,并执行程序: $ gcc -o fac main.c fac.c $ ./fac 5 Factorial of 5 is 120. 上述的-o 选项表示生成一个名称为 fac 的可执行文件,如果没有给出-o 选项,GCC 将生成一个 名为 a.out 的文件。
5.3
GNU make 的介绍
5.4
一个工程中有很多源文件,按类型、功能、模块分别放在若干个目录中。这么多的源文件,如 果要一个一个文件地去编译,那是相当麻烦的,Makefile 就可以实现自动编译。如果某一个源文件 修改了,而要去编译整个工程,那也是很费时的。Makefile 可以做到只编译修改了的源文件,而不 去编译整个工程,从而减少了编译的时间。 make 是一个命令工具,是一个解释 Makefile 中指令的命令工具,一般来说,大多数的 IDE 都 有这个命令。比如,Delphi 的 make,Visual C++的 nmake,Linux 下 GNU 的 make。可见,Makefile 已成为了一种在工程方面的编译方法。UNIX 系统上很多软件包都是使用 make 程序和 Makefile 文 件来实现自动编译的。Makefile 带来的好处是自动化编译,只需要一个 make 命令,整个工程就完 全自动编译,极大地提高了软件开发的效率。 GDB 调试工具的介绍
一般来说,GDB 调试工具主要完成以下四个方面的功能: (1)启动程序,可以按照自定义的要求随心所欲的运行程序。 (2)可让被调试的程序在指定的调置的断点处停住(断点可以是条件表达式) 。 (3)当程序被停住时,可以检查此时程序中所发生的事。 (4)动态地改变程序的执行环境。 从上述功能来看,GDB 调试工具和一般的调试工具大致一样,基本上也是完成这些功能,不过 在细节上 GDB 这个调试工具却更为强大。读者可能习惯了图形化的调试工具,但有时候,命令行 的调试工具却有图形化工具所不能完成的功能。 注意,使用任何一个调试选项都会使最终生成的二进制文件的大小急剧增加,同时增加程序在 执行时的开销,因此调试选项通常仅在软件的开发和调试阶段使用。调试选项对生成代码大小的影 响可以从下面的对比过程中看出来: $ gcc deb.c -o deb $ ls deb –l -rwxrwxr-x 1 cc cc 11649 Nov 20 06:17 deb (未加入调试选项) $ gcc -g deb.c -o deb $ ls deb –l -rwxrwxr-x 1 cc cc 15889 Nov 20 06:18 deb (加入了调试选项) 虽然调试选项会增加文件的大小,但事实上 Linux 中的许多软件在测试版本甚至最终发行版本 中仍然使用了调试选项来进行编译,这样做的目的是鼓励用户在发现问题时自己动手解决,这是 Linux 的一个显著特色。
Linux 程序设计的特点
1. 集成性 Linux 下的软件比 Windows 下的软件更能有机地结合,各自发挥各自的长处,组合成功能更为 强劲的软件。而 Windows 下的软件基本上是各自为营,互相不能调用,很不利于各种软件的相互集 成。 2. 简单性 许多最有用的 Linux 软件工具的安装、使用都非常的简单,使得开发过程也变得简单。 3. 重点性 一个所谓功能齐全的程序可能既不容易使用,也不容易维护。如果程序只用于一个目的,那么 当更好的算法或更好的操作界面被开发出来的时候,它就更容易得到改进。在 Linux 世界里,通常 会在需求出现的时候把小的工具程序组合到一起来完成一项更大的任务,而不是用一个巨大的程序 预测一个用户的需求。 4. 可反复性 使用的程序组件把应用程序的核心部分组建成一个库。带有简单而又灵活的程序设计接口,并 ※ 16 ※
7
7.1
且文档齐备的函数库能够帮助其他人开发同类的项目,或者能够把这里的技巧用在新的应用领域。 例如 dbm 数据库函数库就是一套由不同功能的函数组成的集合,而不是一个单一的数据库管理系 统。 5. 过滤性 许多 Linux 应用程序可以用作过滤器,即它们可以把自己的输入转换为另外一种形式的输出。 Linux 提供的工具程序能够将其他 Linux 程序组合成相当复杂的应用软件。当然,这类程序组合正 是由 Linux 独特的开发方法支撑着的。 6. 开放性 比较成功和流行的 Linux 程序所使用的配置文件和数据文件的文件格式都是普通的 ASCII 文本。 如果在程序开发中遵循该原则,将是一种很好的做法。它使用户能够利用标准的软件工具对配置数 据进行改动和搜索,从而开发出新的工具,并通过新的函数对数据文件进行处理。源代码交叉引用 检查软件 ctags 就是这样一个好例子,它把程序中的符号位置信息以规则表达式的形式记录下来供 检索程序使用。 7. 灵活性 因为根本无法预测用户会怎样使用程序,因此在进行程序设计时,要尽可能地增加灵活性,尽 量避免给数据域长度或者记录条数加上限制。同时如果可能, 应尽量编写能够响应网络访问的程序, 使它既能够跨网络运行又能够在本地单机上运行。
Linux 下 C 语言编程的风格
如果只是编写一些小的练习程序,程序只有一两百行长的话,编程风格可能并不重要。然而, 如果和许多人一起进行开发工作,要在过一段时间之后,还能够正确理解自己的程序的话,就必须 养成良好的编程习惯。在诸多编程习惯当中,编程风格是重要的一项内容。而有些程序员编写的程 序由于没有很好的缩进及顺序,让人看得直皱眉头。代码编写得美观,可以使代码更容易阅读。 良好的编程风格可以在许多方面帮助开发人员,而编程风格能体现一个程序员的综合素质。 Linux 上的编程主要有两种编程风格:GNU 风格和 Linux 核心风格。下面将分别介绍。 基于 GNU 的编程风格
(1)函数开头的左花括号放到最左边,避免把任何其他的左花括号、左括号或者左方括号放到 最左边。 (2)尽力避免让两个不同优先级的操作符出现在相同的对齐方式中。 (3)每个程序都应该由一段简短地说明其功能的注释开头。 (4)为每个函数书写注释,以说明函数做了些什么,需要哪些种类的参数,参数可能值的含义 以及用途。 (5)不要在声明多个变量时跨行。在每一行中都以一个新的声明开头。 (6)当在一个 if 语句中嵌套了另一个 if-else 语句时,应用花括号把 if-else 括起来。 (7)要在同一个声明中同时说明结构标识和变量,或者结构标识和类型定义(typedef) 。 (8)尽力避免在 if 的条件中进行赋值。 (9)在名字中使用下划线以分隔单词,尽量使用小写;把大写字母留给宏和枚举常量,以及根 据统一的惯例使用的前缀。 (10)使用一个命令行选项时,给出的变量应该在选项含义的说明之后,而不是选项字符之后。
7.2
Linux 内核编程风格
在 Linux 中,经常可以看到定义非常简单的函数接口和变量名称。在 Linux 内核的源代码中, 可以看到 Linux 内核源代码的编码风格说明(/ Documentation/CodingStyle) 。UNIX 系统的一个特点 是设计精巧,并遵守积木式原则。C 语言最初来自 UNIX 操作系统,与 UNIX 的设计原则一样,C 语言被广泛认可和使用的一个重要原因是它的灵活性以及简洁性。 因此, 在利用 C 语言编写程序时, ※ 17 ※
do {
始终应当符合其简洁的设计原则,而不应当使用非常复杂的变量命名方法。Linus 为 Linux 内核定义 的 C 语言编码风格要点如下: (1)缩进时,使用长度为 8 个字符宽的 Tab 键。如果程序的缩进超过 3 级,则应考虑重新设计 程序。 这是因为缩进的大小是为了清楚的定义一个块的开始和结束。特别是当用户已经在计算机前面 呆了 20 多个小时以后,就会发现一个大的缩进格式使得对程序的理解更容易。 有一些人说,使用 8 个字符的缩进使得代码离右边很近,在 80 个字符宽度的终端屏幕上看程序 很难受。但当程序有 3 个以上的缩进的时候,就应该修改程序。 总之,8 个字符的缩进使得程序易读,还有一个附加的好处,就是它能在程序嵌套层数变得太 多的时候给用户警告。 (2)大括号的位置。除函数的定义体外,应当将左大括号放在行尾,而将右大括号放在行首。 函数的定义体应将左右大括号放在行首。如下所示: int function(int a, int b) { if (a == b) { …… } else if (a > b) { …… } else { …… }
…… } while (condition); return 0;
} 这种大括号的放置方法减小了空行的数量,但却没有减少可读性。于是在屏幕大小受到限制的 时候,用户就可以有更多的空行来写些注释了。 (3)应采用简洁的命名方法。对变量名,不赞成使用大小写混写的形式,但鼓励使用描述性的 名称;尽可能不使用全局变量;不采用匈牙利命名法表示变量的类型;采用短小精悍的名称表示局 部变量;保持函数短小,从而避免使用过多的局部变量。局部变量的数量应该在 5-10 个,否则有可 能会出错。当超出这个范围时,则应重新考虑这个函数,将它们分割成更小的函数。 (4)保持函数短小精悍。函数应该短小而迷人,它应只覆盖一到两个屏幕(80*24 一屏) ,并 且只做一件事情,而且将它做好。然而,假如要写一个很复杂的函数,而且已经估计到一般人读这 个函数,对方可能都不知道这个函数在说些什么,则应使用具有描述性名字的有帮助的函数。 (5) 不应过分强调注释的作用, 应尽量采用好的编码风格而不是添加过多的注释。 通常情况下, 注释是说明代码做些什么,而不是怎么做,要避免将注释插在一个函数体里。
8
Linux 的发展前景
Linux 正在以飞快的速度发展。从技术与应用看,Linux 正走向成熟,不仅与 Windows 抗衡, 还从 UNIX 手中夺取了不少份额。 虽然其实时处理能力还没有 UNIX 好 (在 2.6 内核中已有所改进) , 但 Linux 在嵌入式系统中的应用已经是非常普遍。为了进一步促进这方面的应用,在 Linux 2.6 中, 引入了很多非常有利于嵌入式应用的功能,使得 Linux 的支持者、使用者大受鼓舞。 Palm OS 和 WinCE 是目前嵌入式应用中最广泛的两种嵌入式操作系统。但这两种操作系统的许 可费用都不低,所以不少信息家电的厂商也开始自行开发操作系统。这些厂商最看好的就是 Linux。 Linux 和开放资源的发展正在进入一个新的阶段。开放资源正在成为主流企业服务器平台。惠
普看重 Linux 发展前景,成立了新的 Linux 部门,意图扩大该公司在此领域上的影响。而在中国的 电子政务领域,Linux 以其得天独厚的优势而一枝独秀。IBM 公司、惠普公司、戴尔公司、Red Hat 公司、Sun 公司、Oracle 公司和 AMD 公司以及其他的一些公司都在推出新的产品,建立新的合作 联盟。Sun 公司和 Red Hat 公司正在讨论进行新的重要投资,向公司客户推出应用 Linux 操作系统 的桌面型电脑。 目前 Linux 操作系统的三大主要发行商(Mandrake 公司、Red Hat 公司和 SuSE 公司)的产品都 已经通过了 LSB 认证。这意味着这三家公司都采用了共同的界面标准,从而保证了应用程序能够在 开放资源平台中得到共用。 由于 Windows、UNIX 技术的独占性,Linux 是源代码开放软件,不存在黑箱技术。Linux 凭借 其源代码完全开放的优势得到业界及众多用户的认可。开放源代码也可以让技术得到最快速的推广 和实现。而遍布全球的众多 Linux 爱好者又能给予 Linux 开发者强大的技术支持。Linux 更小、更稳 定,而且是免费的,在应用上极具竞争力。相信自由、开放源代码的 Linux 一定有一个更大的发展。
1