1 UNIX基础知识
1.1 UNIX体系结构
操作系统可定义为一种软件,它控制计算机硬件资源,提供程序运行环境,通常将这种软件称为内核(kernel)。UNIX操作系统的体系结构如下图所示,其中内核的接口被称为系统调用(system call图中阴影部分),公共函数库构建在系统调用接口之上,应用程序可调用公共函数库,也可以直接使用系统调用。shell是一种特殊的应用程序,为运行其他应用程序提供一个接口。
1.2 登录
(1) 登录名
用户在登录UNIX时,先键入登录名,然后键入口令。系统在其口令接口(Redhat 2.6.32-431.el6.x86_64在/etc/passwd下)中查看登录名。如下:
口令文件中的登录项是由7个以冒号分隔的字段组成,依次是:登录名、加密口令、数字用户ID、数字组ID、字段注释、起始目录以及shell程序。
(2)shell
用户登录后,系统通常先显示一些系统信息,然后用户可通过shell程序键入命令。shell是一个命令行解释器,可读取用户输入,然后执行命令。shell的用户输入通常来自于终端(交互式shell),有时则来自于文件(称为shell脚本)。UNIX系统中shell有多种,用得比较多的是Bash shell。
1.3 文件和目录
(1)文件系统
UNIX文件系统是目录和文件的一种层次结构,所有东西的起点是称为根(root)目录。这个目录的名称是一个符号“/“。
目录(directory)是一个包含目录项的文件。在逻辑上,可以认为每个目录项都包含一个文件名,同时还包含说明该文件属性的信息。文件属性是指文件类型、文件大小、文件所有者、文件权限以及文件最后的修改时间。
(2)文件名
目录中的各个名字称为文件名(filename)。只有斜线(/)和空字符这两个字符不能出现在文件名中。斜线用来分隔构成路径名和各文件名,空字符则用来终止一个路径名。
创建目录时会自动创建两个文件名:.(称为点)和..(称为点点)。点指向当前目录,点点指向父目录。在最高层目录中,点和点点相同。
(3)路径名
由斜线分隔的一个或多个文件名组成的序列(也可以是斜线开头)构成路径名,以斜线开头的路径名称为绝对路径名,否则称为相对路径名。相对路径名指向相对于当前目录的文件。文件系统根的名字(/)是一个特殊的绝对路径名,它不包含文件名。
(4)工作目录
每个进程都有一个工作目录,有时称为当前工作目录,所有相对路径名都从工作目录开始解释。
(5)起始目录
登录时,工作目录设置为起始目录,起始目录可从口令文件中相应用户的登陆项中取得。
1.4 输入和输出
(1)文件描述符
文件描述符(file descriptor)通常是一个小的非负整数,内核用以标识一个特定进程正在访问的文件。当内核打开一个现存文件或创建一个新的文件时,它都返回一个文件描述符,在读、写文件时,可以使用这个文件描述符。
(2)标准输入、标准输出和标准错误
每当运行一个新程序时,所有的shell都为其打开3个文件描述符,即:标准输入(standard input)、标准输出(standard output)以及标准错误(standard error)。如果不做处理,这三个描述符都链接向终端。可使用重定向方法到某个文件中。例如:
ls > file.list 执行ls命令,其标准输出重定向到名为file.list的文件。
(3)不带缓冲的I/O
函数open、read、write、lseek以及close提供了不带缓冲的I/O。这些函数都使用文件描述符。
(4)标准I/O
标准I/O函数为那些不带缓冲的I/O函数提供了一个带缓冲的接口,使用标准I/O函数无需担心如何选取最佳的缓冲区的大小。另外,使用标准I/O简化了对输入行的处理。
1.5 程序和进程
(1)程序
程序(program)是一个存储在磁盘上某个目录中的可执行文件,内核使用exec函数(7个exec函数之一),将程序读入内存,并执行程序。
(2)进程和进程ID
程序的执行实体被称为进程(process)。每一个进程都有一个唯一的数字标识符,称为进程ID(process ID)。进程ID总是一个非负整数。
(3)进程控制
有3个用于进程控制的主要函数:fork、exec和waitpid。
(4)线程和线程ID
通常,一个进程只有一个控制线程—某一时刻执行的一组机器指令,但也可以多个线程作用于线程的不同部分。一个进程内的所有线程共享同一地址空间、文件描述符、栈以及与进程相关的属性。线程也有线程ID标识,但线程ID只在它所属的进程内起作用。
1.6 出错处理
当UNIX系统出错时,通常会返回一个负值,而且整型变量errno通常被设置为具有特定信息的值。文件
1.7 用户标识
(1)用户ID
口令文件登录项中的用户ID(user ID)是一个数值。它向系统标识各个不同的用户。用户不能更改其用户ID,通常每个用户有一个唯一的用户ID。
用户ID为0的用户为根用户(root)或超级用户,在口令文件中,登录名为root,称这种用户的特权为超级用户特权。
(2)组ID
口令文件登录项也包括用户的组ID(group ID),它是一个数值,组ID也是由系统管理员在指定用户登录名时分配的。一般来说,在口令文件中有多个登录项具有相同的组ID。组被用于将若干用户集合到项目或部门中去。组文件将组名映射为数值的组ID,组文件通常是/etc/group。
(3)附属组ID
除了在口令文件中对一个登录名指定一个组ID外,大多数UNIX版本还允许一个用户属于另一些组。
1.8 信号
信号(signal)用于通知进程发生了某种情况。进程有以下三种处理信号的方式:
(1)忽略信号。有些信号表示硬件异常。例如,除以0或访问进程地址空间以外的存储单元。
(2)按系统默认的方式处理。对于除数为0,系统默认方式是终止该进程。
(3)提供一个函数,信号发生时调用该函数,这被称为捕捉该信号。通过提供自编的函数,我们就知道了什么时候产生了什么信号。并按期望的方式处理它。
1.9 时间值
历史上,UNIX系统使用过两种不同的时间值。
(1)日历时间。该值是自协调世界时(Coordinated Universal Time,UTC)1970年1月1日00:00:00这个特定时间以来所经过的秒数累计值(早期的手册称UTC为格林尼治时间),这些时间可用于记录文件最近一次修改的时间等。
(2)进程时间,也被称为CPU时间。用以度量进程使用的中央处理器资源。进程时间以时钟滴答计算。每秒钟曾经取为50、60或100个时钟滴答。
系统基本数据类型clock_t保存这种时间值。
当度量一个进程的执行时间时,UNIX系统为一个进程维护了3个进程时间值:时钟时间、用户CPU时间、系统CPU时间。时钟时间又称为墙上时钟时间(wall clock time),它是进程运行的时间总量,其值系统中同时运行的进程数有关。用户CPU时间是执行用户指令所有的时间量。系统CPU时间是为该进程执行内核程序所经历的时间。例如:每当一个进程执行一个系统服务时,如read或write,在内核内执行该服务所花费的时间就计入该进程的系统CPU时间,用户CPU时间和系统CPU时间之和常称为CPU时间。
1.10 系统调用和库函数
所有的操作系统都提供多种服务的入口点,由此程序向内核请求服务。各种版本的UNIX实现都提供良好定义、数量有限、直接进入内核的入口点,这些入口点称为系统调用(system call)。
UNIX所使用的技术是为每个系统调用在标准C库中设置一个具有同样名字的函数。用户进程用标准C调用序列来调用这些函数,然后方式又用系统所要求的技术调用相应的内核服务。从应用角度考虑,可将系统调用视为C函数。
应用程序既可以调用系统调用也可以调用库函数,很多库函数则会调用系统调用。如下图所示:
系统调用和库函数之间的另外一个区别是:系统调用提供了一种最小接口,而库函数通常提供比较复杂的功能。