第一章 UNIX基础知识
1.2UNIX体系结构
UNIX体系结构如下图,系统内核接口被称为系统调用,公用函数库构建在系统调用接口之上,应用软件可以使用公用函数库,也可以使用系统调用。shell是一个特殊的应用程序,它为运行其他应用程序提供了一个接口。
1.3登录
1.登录名
用户输入登录名及口令之后,系统在/etc/passwd文件中查看登录名,口令文件中的登录项是由7个以冒号分隔的字段组成,它们是:登录名、加密口令、数值用户ID(205)、数值组ID(105)、注释字段、起始目录(/home/sar)以及shell程序(/bin/ksh)。
目前所有新系统的加密口令已转移到另一个文件中。
2.shell
shell是一个命令解释器,它读取用户输入,然后招待命令。用户可以通过两种方式向shell输入:1、常用终端(交互式shell,比如我们在redhat linux9 里点击左下角那个大图标,开启的一个终端),2、文件(也被称为脚本,可以在脚本中预先编辑输入一系列shell命令,完成特定工作,类似于windows中的批处理文件)。
1.4文件和目录
1.文件系统
UNIX文件系统是目录和文件组成的一种层次结构,目录起点称为根(root),其名字是一个字符/。目录是一个包含许多目录项的文件,在逻辑上可以认为每个目录项都包含一个文件名,同时还包含说明该文件属性(文件类型、文件大小、文件所以有者、文件权限、最后修改时间……可以用stat和fstat函数查看这些属性,它们返回的是包含所有文件属性的一个信息结构)的信息。
第五章 标准I/O库。
2.文件名
l 不能出现在文件名中的字符只有两个:/和空操作符null。
l 创建新目录时会自动他那两个文件名: . 和 .. 分别指当前目录和父目录。最高层次中二者相同。
3.路径名
l 没有什么特别的,记住路径名分为绝对路径名和相对路径名就行了。
4.工作目录
l 每个进程都有一个工作目录,有时称其为当前工作目录,所有相对路径名都从工作目录开始解释
5.起始目录
l 登录时,工作目录设置为起始目录
1.5输入和输出
1.文件描述符
通常是一个小的非负整数,内核用它标识一个特定进程正在访问的文件。内核打开或创建一个新文件时,它返回一个文件描述台湾省,读、写文件时都会用到它。
2.标准输入、输出和出错
按惯例,每运行一个新程序时,所有shell都为其打开三个描述符:标准输入、输出和出错。若没有做特殊处理,则三个描述符都链向终端。当然大多数shell都提供一种方法,使其中任何一个或所以有这三个描述符都能重新定向到某个文件,如:
ls > file.list
则标准输出重定向到file.list文件上。
3.不带缓冲的I/O
函数open read write lseek close提供了不带缓冲的I/O,这使得输入和输出可以及时到达。
4.标准I/O(带缓冲的I/O)
使用标准I/O函数可以无需担心如何选取最佳的缓冲区大小 ,因为库函数已经帮我们设置好了。它的另一个优点是简化了对输入行的处理,如标准I/O函数fgets函数读一完整的行,而不带缓冲的I/O函数read则读指定的字节数。
1.6程序和进程
1.程序
指存放于磁盘上、牌某个目录中的一个可招待文件,使用6个exec函数中的任意一个,将程序读入存储器,并使其执行。
2.进程和进程ID
程序执行实例被称为进程,每一个进程都拥有一个唯一的数字标识符,称为进程ID,进程ID一非负整数。
3.进程控制
用于控制进程的函数主要有三个:fork(创建一个新进程)、exec(执行程序)、waitpid(暂时停止目前进程的执行,直到有信号来到或子进程结束)。
4.线程和线程ID
通常,一个进程拥有至少一个线程,在一个进程内的所以有线程共享同一地址空间、文件描述符、栈以及与进程相关的属性。
与进程相同,纯种也用ID标识,但是,线程ID只在它所属进程内起作用。
控制线程的函数与控制进程的函数类似,但另有一套。
1.7出错处理
1.获得出错信息
UNIX函数出错时,通常返回一个负值。另外,还可以通过整型变量errno来获得出错信息。如对于open出错时,有大约15种不同的errno值表示各种出错信息(文件不存在,权限问题等)。
注:在多线程环境中,多个线程共享地址空间,每个线程都有属于它自己的局部errno以免干扰另外一个线程。
errno有两个应该知道的规则。第一、如果没有出错,则其值不会被一个例程清除;第二、任一函数都不会将errno设为0,在<errno.h>中定义的所以有常量都不为0。
2.出错恢复
可将在<errno.h>中定义的各种出错分成致命性的和非致命性两类。对于致命性的错误,无法招待恢复动作,最多只能在用户屏幕上打印一条出错消息或写入日志中,然后程序终止;对于非致命性的出错,本质上是暂时的,例如资源短缺,一般恢复动作是延迟一些时间再试。
另外,应用程序开发者可以决定他们的程序哪些程序出错是可以恢复的。如果使用一种从错误中恢复的合理策略,那么由于避免了应用程序的异常终止,就能改善应用程序的健壮性。
1.8用户标识
包括用户ID、组ID、附加组ID,略
1.9信号
是通知进程已发生某种情况的一种技术。进程处理信号有三种选择:
1、 忽略该信号,由于一些异常产生的后果不确定,所以不推荐你不用这种方式
2、 按系统默认方式处理
3、 提供一个函数,信号发生时则调用该函数,这种方式被称为捕捉信号。
很多情况可以产生信号,可以用中断键(interrupt key)和退出键(quit key),另外就是调用名为kill的函数,在一个进程中调用此函数,就可以向另一个进程发送一个信号:当向一个进程发送信号时,我们必须是该进程的所以有者或超级用户。
1.10时间值
UNIX使用两种不同的时间值:日历时间、进程时间
其中,进程时间分为三种:
时钟时间,又称为wall clock time,是进程运行的起止时间差。
用户CPU时间,指执行用户指令所用的时间
系统CPU时间,指为该进程执行内核程序所经历的时间
用户/系统CPU时间这种常被称为CUP时间
1.21系统调用和库函数
所有的操作系统都提供多种服务的入口点,程序由此高内核请求服务,UNIX所使用的技术是为每个系统调用在标准C库中设置一个具有同样名字的函数。但库函数和系统调用二者区别甚大:
1、 库函数会调用一个或多个内核的系统调用,但它们并不是内核的入口点。
2、 库函数和系统调用都以C函数的形式出现,但必要是我们可以替换库函数,但不能替换系统调用。例如对于库函数malloc我们如果不喜欢其操作方式,则可以定义自己的malloc函数。
3、 系统调用通常提供一种最小的接口,而库函数通常提供比较复杂的功能。考虑UNIX下获得当前时间,系统调用只会返回国际标准时间1970年1月1日零点以来所经过的秒数,但库函数则可以利用这个信息转换成多种我们需要的信息。
下图可以较为充分说明库函数和系统调用的区别: