UNIN体系结构
严格地说,操作系统被定义为控制硬件计算机硬件资源和提供程序运行环境的软件。一般我们把这个软件叫做kernel。
kernel的接口是一层软件,叫做作系统调用。函数库在系统调用的上层,应用可任意使用系统调用和函数库。shell是一个特殊的应用,提供运行其它应用的接口。
登录名
我们登录系统时,输入登录名和密码。系统随即在/etc/passwd中查找用户名。
passwd文件格式:
sar:x:205:105:Stephen Rago:/home/sar:/bin/ksh
登录名:加密的密码:用户ID:组ID:注释字段:家目录:shell程序
Shells
shell是一个命令行解释器,读取用户输入然后执行命令。用户向shell的输入一般来自终端(交互式shell),或有时来自文件(shell脚本)。
文件系统
文件系统是目录和文件的层次结构,起始于根目录"/"。
目录是包含目录项的文件。逻辑上讲,我们可以认为每个目录项包含一个文件名和描述该文件属性的信息结构。文件的属性包括文件类型(普通文件或目录),文件大小,文件所有者,文件权限(是否其它用户可访问此文件)和文件最后修改时间。
文件名
目录中的名字称作文件名。只有两个字符不能出现在文件名中:斜杠“/”和空字符。斜杠分割组成路径名的文件名,空字符结束一个路径名。当一个新的目录被创建时,两个文件名被自动创建:“.”和“…”,前者指向当前目录,后者指向父目录。在根目录,两者相同。
路径名
一个或多个文件的序列,被斜杠分割(可以以一个斜杠开始),组成一个路径名。以斜杠开始的路径名被称作绝对路径名,否则称作相对路径名。相对路径名指向相对于当前目录的文件。文件系统根的名字是一个特殊的绝对路径名,没有文件名部分。
输入和输出
- 文件描述符
文件描述符一般是一个非负整数,kernel用它来标识被进程访问的文件。当打开一个存在的文件或创建一个新的文件,kernel返回一个文件描述符用来读写文件。
标准输入,标准输出和标准错误
按照惯例,一个新程序运行时,shell打开这三个文件描述符。 - 无缓冲I/O
函数open, write, lseek和close提供无缓冲I/O,这些函数都需要文件描述符。 - 标准I/O
标准I/O向无缓冲I/O提供一个缓冲接口。使用标准I/O可以免去选择合适的缓冲区buffer大小。标准I/O还简化了处理行输入。比如函数fgets读一整行数据,相反,函数read读取指定字节数据。
程序和进程
- 程序
程序是在磁盘上一个目录里的可执行文件。内核使用7个exec函数之一将程序读入内存并执行。 - 进程和进程ID
正在执行的程序叫做进程。UNIX系统保证每个进程有一个唯一的标识称作进程ID。进程ID总是一个非负整数。
getpid()返回进程ID。 - 线程和线程ID
同一进程的线程共享相同的地址空间,文件描述符,栈和进程相关属性。每一个线程在自己的栈中执行,尽管任一线程可访问同一进程中其它线程的栈。因为它们可以访问相同内存,各线程需要同步访问来共享内存以避免冲突。
如同进程,线程也被ID标识。线程ID基于进程。一个进程里的线程ID在另一个进程中没有意义。在一个进程中处理线程时,使用线程ID来引用特定的线程。
错误处理
当一个错误出现在一个UNIX系统函数中,通常返回一个负数,errno被设置来表明错误原因。大多数返回指针的函数在错误时返回NULL。
#include <string.h>
char *strerror(int errnum); //传入errno,返回错误信息
void perror(const char *msg); //标准输出中打印错误信息
用户标识
-
用户ID
当登录名被分配时,用户ID被系统管理员分配,不能修改、
root用户ID为0 -
组ID
组用来将一些用户组合在一起,共享一些资源、
在组文件/etc/group中保存着组名和组ID的映射。
getuid()返回用户ID,getgid()返回组ID。
信号
信号是用于通知一个进程某种条件已经发生的技术。进程有3种处理信号的选择:
- 忽略信号
- 默认处理
- 提供一个函数在信号发生时执行(信号捕捉)
时间值
UNIX系统维护着两个不同的时间值:
- 日历时间
这个值记录着UTC时间(1970年1月1日00:00:00)到现在的秒数,用于记录文件最后修改的时间。 - 进程时间
也称作CPU时间,度量进程使用的中央处理资源。进程时间以时钟滴答度量,一般以50,60或100每秒。
UNIX系统为进程维护着3个时间:
- 时钟时间:进程运行花费的时间。它的值依赖于其它运行在系统上的进程。
- 用户CPU时间:用户指令执行的时间
- 系统CPU时间:内核执行的时间