APUE这本书实在是干而松散,不自己消化消化确实看不下去。这篇文章简单总结一下前两章,Unix基础与标准。
基础介绍
操作系统在狭义上单指一种控制硬件单元,为程序提供运行环境的软件,称为内核(Kernel)。内核的接口称为系统调用(System call)。
广义上,操作系统包括内核以及一些软件,这些软件包括了公用函数库、shell和系统实用程序(system utility)以及一些应用程序。
其中,公用函数库就是建立在系统调用的基础上的一些函数。应用程序既可以使用系统调用也可以使用公用函数库。shell是一个特殊的应用程序,为运行其它程序提供了一个接口。
登录
用户键入用户名与口令,系统在口令文件中读取相关信息并进行相应操作。口令文件通常是/etc/passwd,其中每行记录一个登录项。登录项由7个以冒号分隔的字段组成,依次是:
1 | 登录名:加密口令:UID:GID:注释:起始目录:shell程序 |
目前所有系统都将加密口令移到另一个文件中,但这里先略过。
登录后,通常进入到shell程序,shell是一个命令行解释器,它读取用户输入然后执行命令。
文件和目录
文件系统
UNIX文件系统是目录和文件的一种层次结构,所有东西的起点是根(root)目录,其名称是/。
我们总听说UNIX中一切皆文件,对于目录也是适用的。实际上目录是一个包含目录项的文件,逻辑上可以认为每个目录项都包含一个文件名与文件属性信息。
文件名
目录中的各项拥有一个文件名(filename)。只有斜线/和空字符不能出现在文件名中。因为斜线用来分隔路径名和文件名而空字符表示路径结束。
但习惯上最好还是使用字母、数字、.、-、_作为文件名,这可以避免很多麻烦。
新的目录会创建两个文件名.、..,.指向当前目录,..指向上级目录。在根目录中都指向根目录。
路径名
由/分隔的一个或多个文件名组成的序列构成一个路径名,以/开头的称为绝对路径,以文件名开头称为相对路径。相对路径名指向相对于当前目录的文件。
工作目录
每个进程有一个工作目录,所有相对路径名从工作目录开始解释,进程可以使用chdir来更改工作目录。
起始目录
登录时的工作目录为起始目录,记录在口令文件中。
输入与输出
文件描述符
文件描述符通常是一个小的非负整数,内核用以标识一个特定的进程正在访问的文件。当内核打开一个现有文件或创建一个新文件时,它都返回一个文件描述符。在读写文件时,可以使用这个文件描述符。
标准输入、标准输出和标准错误
惯例上,每当运行一个新程序时,所有shell都为其打开3个文件描述符,分别为标准输入、标准输出、标准错误。如果不做特殊处理,它们都链接终端。
大多数shell提供一种方法,使其中任何一个都能重定向至某个文件。
缓冲
不带缓冲的I/O直接向文件中写入,而带缓冲的I/O在缓冲区满后才写入文件。
程序和进程
程序是存储在磁盘上的可执行文件。内核使用exec函数将程序读入内存,并执行程序。
程序的执行实例被称为进程。UNIX系统确保每个进程都有一个唯一的数字标识符,称为PID,PID总是一个非负整数。
系统主要使用三个函数控制进程:fork、exec、waitpid。
通常一个进程只有一个控制线程——某一时刻执行的一组机器指令。但某些情况下可以拥有多个线程。一个进程内的所有线程共享同一地址空间、文件描述符、栈以及进程相关属性。因为它们能访问同一存储区,所以各线程在访问共享数据时需要采取同步措施以避免不一致性。
线程也用ID标识,称为TID。TID只在进程内起作用,对其它进程没有意义。
出错处理
当UNIX系统函数出错时通常返回一个负值,且整型变量errno通常被设置为具有特定信息的值。文件<errno.h>中定义了errno及可以赋予它的常量。这些常量都以字母E开头。对于errno有两条规则:
- 只有出错时才改变它的值。
- 任何程序都不会将它的值设为0。
两个函数可以用于打印出错消息,分别是:
1 |
|
用户标识
UID
UID是一个数值,向系统标识各个不同的用户。系统管理员在确定一个用户的登录名的同时,确定其UID。用户不能更改其UID。
UID为0的用户为root用户。root用户拥有系统的自由支配权。
GID
GID是一个标识用户所在组的ID,也是由系统管理员在创建用户时分配的。组文件将组名映射为数值的GID,通常是/etc/group。
SGID
SGID是附属组ID,UNIX允许一个用户同时属于多至16个其它的组。这些信息也存在组文件中。
信号
信号用于通知进程发生了某种情况。进程有3种处理信号的方式:
- 忽略信号。
- 按系统默认方式处理。
- 提供一个函数,信号发生时调用该函数,称为捕捉信号。
时间值
日历时间:从1970年1月1日00:00:00以来经过的秒数时间值,使用time_t保存。
进程时间:被称为CPU时间,用以度量进程使用的中央处理器资源。进程时间以时钟tick计算。当一个进程创建时,系统维护3个进程时间值:
- 时钟时间,进程消耗的总时间。
- 用户CPU时间,进程执行用户指令所用的时间。
- 系统CPU时间,进程执行内核程序所用的时间。
其中用户CPU时间与系统CPU时间之和称为CPU时间。
系统调用与库函数
系统调用是内核提供的良好定义、数量有限、直接进入内核的入口点。从应用角度考虑,可以将系统调用看做C函数。通用库函数通常调用一个或多个系统调用,其中一个关键区别在于,我们可以在需要的时候替换库函数,但无法替换系统调用。另一方面,系统调用通常提供简单而单一的功能,而库函数则更加复杂。