linux程序设计读书笔记第一章入门

1.1 unix、linux和GNU简介

linux的成功要归功于在他之前诞生的系统和应用程序–UNIX和GNU软件。本届将介绍Linux是怎样产生的,以及它植根于何处。

1.1.1什么是UNIX

现在已经成为一种非常流行的多用户多任务操作系统。适用范围从pc工作站到多处理器服务器和超级计算机。

1.unix简史

unix是由open group管理的一个商标,它指的是一种遵循特定规范的计算机操作系统。这个规范也称为单一unix规范,它定义了所有必需的unix操作系统函数的名称、接口和行为。这个规范早期是由IEEE开发的P1003或POSIX规范的超集。许多类UNIX系统都是具有商业性质的,如IBM的AIX等。还有一些可以免费获得。如今只有少数系统完全遵守开放组织的规范,从而允许他们挂上unix商标。
在过去,不同unix系统之间的兼容性一直是一个实际存在的问题,尽管posix规范在这一方面起了很大帮助。现在,通过遵守一些简单的规则,创建可以运行在所有unix和类unix系统上的应用程序已称为可能。

2.unix哲学

unix和linux开发者对编程和系统开发确实有其独特的观点。
unix操作系统鼓励一种特定的编程风格。下面列出一些典型的unix程序和系统所具有的特点。
简单性:许多很有用的unix工具是非常简单的,因此也是很小并易于理解的。小而简单
集中性:让一个程序很好地执行一项任务要好过把所有功能都乱七八糟地堆在一起。在unix中,当用户出现新的需求时,我们通常时把小工具组合起来以完成更复杂的任务,而不是试图将一个用户期望的所有功能放在一个大程序中。
可重用组件:将应用程序的核心实现为库。具有简单灵活的编程接口、文档齐全的库
过滤器:许多unix应用程序可用作过滤器。他们对输入进行转化并产生输出
开放的文件格式:比较成功流行的unix程序都使用纯ascii码的文本文件或XML文件作为配置文件和数据文件。它使用户可以用标准工具来修改和搜索配置项,并且可以开发出新工具在数据文件上执行新的功能
灵活性:你不能期待用户都能非常正确地使用你的程序。所以你编程的时候尽量考虑到灵活性,尽量避免随意限制字段长度或记录数目

1.1.2什么是linux

linux是一个可以自由发布的类unix内核实现,他是一个操作系统的底层核心。几乎所有的为unix编写的程序都可以在linux上编译运行。而且,一些专用于unix商业版本的商业应用软件,也可以不加改变地以二进制形式运行在linux系统上。现在,使用不同类型cpu的计算机系统都有linux版本可以运行其上。只要这个设备有处理器,就会有人试图让linux运行其上。

1.1.3GNU项目和自由软件基金会

操作系统内核本身仅仅是可用开发系统的一小部分。
传统上,商业化的UNIX系统都包含提供系统服务和工具的应用程序。对linux系统来说,这些额外的程序是由许多程序员编写并自由发布的。
linux社区支持自由软件的概念,即软件本身不应受限,它们应遵守GNU通用公共许可证(GPL)。虽然获得软件可能要支付一定的费用,但ihou就可以随意使用他们,并且他们通常是以源代码的形式发布。
自由软件基金会由Richard Stallman创立。Stallman是自由软件这一概念的倡导者,并发起了GNU项目,这个项目的宗旨是:试图创建一个于UNIX系统兼容,但并不受UNIX名字和源代码私有权限制的操作系统和开发环境。可能有一天,GNU处理硬件和管理运行程序的方式会变得于UNIX完全不同,但他仍会继续支持unix类型的应用程序。
GNU项目已为软件社区提供了许多unix系统上应用程序的仿制品。所有这些程序,即GNU软件,都在GNU通用公共许可证GPL的条款下发布的。
下面是在GPL条款下发布的一些主要的GNU项目软件:GCC,G++,等。
现在有这么多可用的自由软件,再加上linux内核,我们可以说:创建一个GNU的,自由的类UNIX系统的目标已经通过linux系统实现了。
由于认识到GNU软甲的贡献,现在许多人通常都把linux系统称为GNU/Linux。

1.1.4linux发行版

linux实际上只是一个内核。你可以获得内核源代码,编译并安装它,然后获得并安装许多其它自由发布的软件,从而完成一个完整Linux系统的安装。我们通常将这样安装所得的系统称为linux系统。这是因为它包含的远不止一个Linux内核。系统中大多数的工具都来自自由软件基金会的GNU项目。
仅从源代码开始创建Linux系统是一件很不容易的事。许多人 制作了准备好安装的linux发行版,它一般可下载或以CD-ROM/DVD为载体。它不仅包含内核,还包含许多其它编程工具和应用程序。它通常会包含一个X视窗系统的实现,即在许多unix系统上都有的一个图形化环境。如Ubuntu Linux和Red Hat Enterprise Linux等。

1.2linux程序设计

c语言并不是linux程序员或unix程序员的唯一选择。

1.2.1linux程序

linux应用程序表现为两种特殊类型的文件:可执行文件和脚本文件。可执行文件是计算机可以直接运行的程序,脚本文件是一组指令的集合,这些指令将由另一个程序(即解释器)来执行。
linux并不要求可执行文件或脚本文件具有特殊的文件名或扩展名。文件系统属性用来指明一个文件是否为可执行的程序。在linux中,你可以用编译过的程序代替脚本而不会影响其它程序或调用者。事实上,在用户级别,这两者本质上没有任何不同。
当登录进linux系统时,你与一个shell程序(通常是bash)进行交互。它在一组指定的目录路径下按照你给出的程序名搜索与之同名的文件。搜索的目录路径存储咋shell变量PATH里。搜索路径由系统管理员配置,它通常包含如下一些存储系统程序的标准路径。
/bin:二进制文件目录,用于存放启动系统时用到的程序。
/usr/bin:用户二进制文件目录,用于存放用户使用的标准程序。
/usr/local/bin:本地二进制文件目录,用于存放软件安装的程序。
系统管理员(例如root用户)登录后使用的PATH变量可能还包含存放系统管理程序的目录,如/sbin和/usr/sbin。
可选的操作系统组件和第三方应用程序可能被安装在/opt目录下,安装程序可以通过用户安装脚本将路径添加到path环境变量中。
Linux使用冒号:分隔PATH变量里的条目,下面是一个PATH变量的例子
/usr/local/bin:/bin:/usr/bin:.:/home/neil/bin:/usr/X11R6/bin

上面的PATH变量包含的条目有:标准程序存放位置,当前目录(.),一个用户的家目录和X视窗系统目录

1.2.2文本编辑器

编写和输入本书中的代码需要使用一个编辑器。较流行的是vi。作者喜欢用emacs

1.2.3c语言编译器

在POSIX兼容的系统中,C语言编译器称为c89。POSIX委员会决定为C语言编译器创建新的标准命令,就是c89
历史上c语言编译器被简称为cc。
linux系统尽量实现这些标准。GNU C编译器 gcc。

hello程序很可能在你的家目录中。如果path变量不包含指向你的家目录的条目,shell就找不到hello程序。你可以在程序名前加上./(例如)

./hello

它特别指示shell去执行当前目录下给定名称的程序。(符号. 代表当前目录)

如果你忘记用-o name选项告诉编译器可执行程序的名字,编译器就会把程序放在名a.out的文件里。

1.2.4开发系统导引

对linux开发人员来说,了解软件工具和开发资源在系统中存放的位置是很重要的,以下几节将简单介绍一些重要的目录和文件。

1.应用程序

应用程序通常存放在系统为之保留的特定目录中。系统为正常使用提供的程序,包括用于程序开发的工具,都可以在目录/usr/bin中找到;
系统管理员为某个特定的主机或本地网络添加的程序通常可以在目录/usr/local/bin或/opt中找到。他们分离了厂商提供及后续添加的文件与系统本身提供的应用程序。这样在系统升级时就只需要保存/usr/local/和/opt里的内容。
我们建议对于系统级的应用程序,可以将他放在/usr/local目录中运行和访问需要的文件。
对于开发用和个人的应用程序,最好在你的家目录中使用一个文件夹来存放它。
其它一些功能特性和编程系统可能有其自己的目录结构和程序目录。其中最主要的一个就是X视窗系统,它通常安装在/usr/X11或/usr/bin/X11目录中。
GNU编译系统的驱动程序gcc一般位于/usr/bin或/usr/local/bin目录中,但它会从其它位置运行各种编译器支持的应用程序。这个位置是在编译编译器本身时指定的,并且它随主机类型的不同而不同。对于Linux系统来说,这个位置可能是/usr/bin/gcc/目录下的一个版本特定的子目录。作者的目录是/usr/bin/gcc/i586-suse-linux/4.1.3。GNU C/C++编译器的各个工具和GNU专用的头文件都保存在这里。

2.头文件

用c语言及其它言语进行程序设计时,你需要用头文件来提供对常量的定义和对系统函数及库函数调用的声明。
对c语言来说,这些头文件几乎总是位于/usr/include目录及其子目录中。
那些依赖于特定Linux版本的头文件通常可在目录/usr/include/sys和/usr/include/linux中找到。
其它编程系统也有各自的头文件,这些头文件被存储在可被相应编译器自动搜索到的目录里。例如GNU C++的/usr/include/c++目录。

在调用c语言编译器时,你可以使用-I标志来包含保存在子目录或非标准位置中的头文件。例如

gcc -I/usr/openwin/include fred.c

它指示编译器不仅在标准位置,也在/usr/openwin/include目录中查找程序fred.c中包含的头文件。

用grep命令来搜索包含某些特定定义和函数原型的头文件是很方便的。假设想知道用于从程序中返回退出状态的#define定义的名字,你只需要切换到/usr/include目录下,然后用grep命令搜索可能的名字部分

grep EXIT_*.h

上面的grep命令在当前目录下的所有以.h结尾的文件中搜索字符串EXIT_。
这个命令要好好看一看

3.库文件

库是一组预先编译好的函数的集合,这些函数都是按照可重用的原则编写的。他们通常由一组相互关联的函数组成以执行某项常见的任务。
标准系统库文件一般存储在/lib和/usr/bin目录中。c语言编译器需要知道要搜索哪些库文件,因为在默认情况下,它只搜索标准C语言库。库文件必须遵循特定的命名规范并且需要在命令行中明确指出。
库文件的名字总是以lib开头,随后的部分指明是什么库。文件名的最后部分以.开始,然后给出库文件的类型:
.a表示传统的静态函数库
.so表示共享函数库
函数库通常同时同时以静态库和共享库同时存在。可以使用

ls /usr/lib

查看。
可以通过给出完整的库文件路径名或用-l标志来告诉编译器要搜索的库文件。
例如

gcc -o fred fred.c /usr/lib/libm.a

这条命令要求编译器编译文件fred.c,将编译产生的程序文件命名为fred,并且除了搜索标准的c语言函数库外,还搜索数学库以解决函数引用问题。下面的命令也能产生相似的结果

gcc -o fred fred.c -lm

-lm是简写,它代表的是标准库目录中名为libm.a的函数库。-lm标志的一个好处是如果有共享库,编译器会自动选择共享库。
虽然库文件和头文件一样,通常都保存在标准位置,但你也可以通过-L标志为编译器增加库的搜索文件

gcc -o x11fred -L/usr/openwin/lib x11fred.c -lx11

这条命令用/usr/openwin/lib目录中的libX11库版本来编译和链接程序x11fred

4.静态库

函数库最简单的形式是一组处于“准备好使用”状态的目标文件。当程序需要使用函数库中的某个函数时,它包含一个声明该函数的头文件。编译器和链接器负责将程序代码和函数库结合在一起以组成一个单独的可执行文件。你必须使用-l选项指明除标准c语言运行库外还需要使用的库。

静态库,也称为归档文件archive。所以是a结尾。
你可以很容易创建和维护自己的静态库,只要使用ar程序和使用gcc -c命令对函数分别进行编译。你应该尽可能把函数分别保存到不同的源文件中。如果函数需要访问公共数据,你可以把他们放在同一个源文件中,并使用在该文件中声明的静态变量。

###############################################################################
实验 静态库
(1)创建两个文件 fred.c bill.c
(2)分别编译这些函数以产生主要包含在库文件中的目标文件。这可以通过调用带有-c选项的c语言编译器来完成,-c选项的作用是阻止编译器创建一个完整的程序。

gcc -c bill.c fred.c  会生成bill.o fred.o

ls *.o

(3)编写一个头文件,这个文件声明你的库文件中的函数,它应该被所有希望使用你的库文件的应用程序包含。把这个头文件包含在fred.c bill.c中是一个好主意,它将帮助编译器发现所有错误。

void bill(char*);
void fred(int);

(4)调用程序(program.c)非常简单。它包含库的头文件并且调用库的一个函数。
(5)暂时为编译器显式指定目标文件,然后要求编译器编译你的文件并将其与先前编译好的目标模块bill.o链接。

gcc -c program.c
gcc -o program program.o bill.o
./program

(6)现在,你将创建并使用一个库文件。你使用ar程序创建一个归档文件并将你的目标文件添加进去。这个程序之所以称为ar,是因为它将若干单独的文件归并到一个大的文件中以创建归档文件或集合。注意,你可以用ar程序来创建任何类型文件的归档文件。

ar crv libfoo.a bill.o fred.o

(7)你可以在编译器使用的文件列表中添加该库文件以创建你的程序

gcc -o program program.o libfoo.a
./program 

你也可以使用-l选项来访问函数库,但因其为保存在标准位置,所以你必须使用-L选项来告诉编译器在何处可以找到他,如下所示:

gcc -o program program.o -L. -lfoo

-L.选项告诉编译器在当前目录(.)中查找函数库。-lfoo选项告诉编译器使用名为libfoo.a的函数库或者libfoo.so的共享库。
要查看哪些函数被包含在目标文件、函数库或可执行文件里,你可以使用nm命令。

在这里插入图片描述

###############################################################################

5.共享库。

静态库的缺点是,当你同时运行许多应用程序并且他们都是使用来自同一个函数库的函数时,内存中就会有同一函数的多份副本,而且在程序文件自身中也有多分同样的副本,这将消耗大量宝贵的内存和磁盘空间。
共享库的保存位置与静态库是一样的,但共享库有不同的文件名后缀。
当一个程序使用共享库时,他的链接方式时这样的:程序本身不再包含函数代码,而是引用运行时可访问的共享代码。当编译好的程序被装载到内存中执行时,函数引用被解析并产生对共享库的调用,如果有必要,共享库才被加载到内存中。
通过这种方式,系统可以只保留共享库的一份副本供许多应用程序同时使用,并且在磁盘上也仅保存一份。另一个好处是共享库的更新可以独立于依赖它的应用程序。
对linux系统来说,负责装载共享库并解析客户程序函数引用的程序(动态装载器)是ld.so,也可能是ld-linux.so.2,ld-lsb.so.2或ld-lsb.so.3后面的数字表示主版本号。用于搜索共享库的额外位置可以在文件/etc/ld.so,conf配置,如果修改了这个文件,你需要执行命令ldconfig来处理它
你可以通过运行工具ldd来查看一个程序需要的共享库

ldd program

.so库对应于.DLL文件,他们都是在程序运行时加载,而.a库类似于.LIB文件,他们都包含在可执行程序中。

1.3获得帮助

man命令可用来访问在线手册页。GNU软件和其它一些自由软件还使用名为info的在线文档系统。

man gcc
info gcc
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值