Chinaunix首页 | 论坛 | 博客
  • 博客访问: 285868
  • 博文数量: 38
  • 博客积分: 706
  • 博客等级: 上士
  • 技术积分: 390
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-05 09:09
文章分类

全部博文(38)

文章存档

2013年(23)

2012年(15)

我的朋友

分类:

2013-01-05 23:32:38

严格意义上,操作系统也是一种软件,它控制计算机硬件资源,提供程序运行环境;我们称此为内核(kernel),其相对较小,位于软件运行环境的中心。

内核的接口被成为系统调用(system call)。

公用函数库构建在系统调用接口之上。

应用程序既可使用公用函数库,也可以直接使用系统调用。而 shell 是一种特殊的应用程序,为运行其他应用程序提供了一个接口。

登录

用户登录系统时,系统在口令文件(通常是 /etc/passwd)中查看登录名。

口令文件中的登录项由7个以冒号分隔的字段组成,分别是:登录名、加密口令、数值用户 ID 、数值组 ID、注释字段、起始目录(/home/xxx)以及shell程序(/bin/xxsh)。

当然,也有系统将加密口令移到另一个文件中,并提供相应的访问函数。

shell

用户登录后,系统会启动一个 shell 程序,使用户可以键入命令。shell 是一个命令行解释器,读取输入,然后执行命令。用户可以用终端(交互式 shell),或通过文件(shell 脚本)进行输入。

系统常见的 shell 有:Bourne shell(/bin/sh)、Bourne-again shell(/bin/bash)、C shell(/bin/csh)、Korn shell(/bin/ksh)、Tenex C shell(/bin/tcsh)。其中,Bourne-again shell 是 GUN shell ,所有 Linux 系统都提供这种 shell ,其被设计成遵循 POSIX 。

系统从口令文件中相应用户登录项的最后一个字段(shell 程序)中了解到为该用户执行的 shell 。

文件系统

UNIX文件系统是目录和文件组成的层次结构,目录的起点为(root),其名字是字符 /目录(directory)是一个包含许多目录项的文件,每个目录项都包含一个文件名,同时还包含说明该文件属性的信息。

文件属性是指文件类型(普通股文件还是目录)、文件大小、文件所有者、文件权限以及文件最后的修改时间等。stat 和 fstat 函数返回包含所有文件属性的信息结构。不过,目录项的逻辑视图和实际存放在磁盘的方式是不同的,文件系统的大多数实现并不在目录项中存放属性。

文件名中不能出现的字符有斜线(/)和空操作符(null)两个;其中斜线用来分隔构成路径名的文件名,空操作符用来终止一个路径名。而好的习惯是,只使用印刷字符的一个子集作为文件名字符;可以有效减少在 shell 由于使用了特殊字符而必须使用引号机制来引用文件名的麻烦。

目录中有两个文件名会被自动创建: . (称为)和 .. (称为点-点)。其中 . 指当前目录, .. 指父目录;而根目录中, .. 和 .相同。

路径名是一个或多个以斜线分隔的文件名序列;以斜线开头的路径名为绝对路径名(absolute pathname),否则称为相对路径名(relative pathname)。

每个进程都有一个工作目录(working directory),也称为当前工作目录(current working directory)。相对路径名都从工作目录开始解析,可以用 chdir 函数更改其工作目录。登录时,工作目录设置为起始目录(home directory),系统在登录时从口令文件中用户的相应登录项中获取。

输入输出

文件描述符(file descriptor)是一个很小的非负整数,内核用来标识特定进程正在访问的文件。

系统运行一个新程序时, shell 都为其打开三个文件描述符:标准输入(standard input)、标准输出(standard output)和标准出错(standard error)。如果没有特殊处理,三个描述符都链向终端。STDIN_FILENOSTDOUT_FILENO 定义在头文件中,它们指定着标准输入和标准输出的文件描述符。

函数 openreadwritelseekclose 提供了不用缓冲的 I/O ,这些函数在头文件中声明。

标准 I/O 函数提供了一种对不用缓冲 I/O 函数的带缓冲的接口。使用这类函数,无需担心如何选择最佳的缓冲区大小;并且简化了对输入行的处理。标准 I/O 函数中,printf 函数在头文件中声明,而EOF(文件结束符)、stdin(标准输入常量)、stdout(标准输出常量)等常量也在此头文件中定义。

程序和进程

程序(program)是存放在磁盘、处于某个目录中的可执行文件;使用6个 exec 函数中的一个将程序读入存储器,并使其执行。

程序的执行实例被称为进程(process)。每个进程都有一个唯一的数字标识符,称为进程 ID(process ID);可以调用 getpid 函数得到进程ID。有三个用于进程控制的主要函数:fork、exec、waitpid

通常一个进程只有一个控制线程(thread),而同一时间只执行一组机器指令。多线程能充分利用多处理器系统的并发性。在一个进程内,所有线程共享同一地址空间、文件描述符、栈以及与进程相关的属性。线程也用 ID 标识,但线程 ID 只在所属的进程内起作用。

出错处理

当 UNIX 函数出错时,尝尝返回一个负值;而整形变量 errno 通常被设置为含有附加信息的值,其中头文件中定义了符号 errno 以及可以赋予它的各种常量(常以字符 E 开头)。而返回指向对象指针的大多数函数,出错时返回一个 null 指针。

在支持线程的环境中,多个线程共享进程地址空间,每个线程都有属于自己的局部 errno ,以避免线程间的互相干扰。

函数不会(也不应当)将 errno 设置为 0;而如果没有出错,则其指不会被一个线程清除,此时返回值无意义。

strerror 函数可以将 errno 值映射为一个出错信息字符串,并返回此字符串的指针。perror 函数基于errno的当前值,在标准出错上产生一条出错信息。

出错可以分为致命性非致命性的两类。对于致命性错误,无法执行恢复动作,只能打印出错信息或者写入日志;对于非致命性错误,有时候可以妥善处理。与资源先关的非致命性出错包括,ENGAIN、ENFILE、ENOBUFS、ENOLCK、ENOSPC、ENOSR、EWOULDBLOCK。

用户标识

用户 ID(user ID)是系统标识各个不同的用户的数值。用户 ID 为 0 的用户为(root)或超级用户(superuser)。

用户的组 ID(group ID)是系统标识不同用户组的数值。组文件将组名映射为组 ID,通常是 /ect/group。

对于磁盘上的每个文件,文件系统都存放该文件所有者的用户 ID 和组 ID。

口令文件包含了登录名和用户 ID 之间的映射关系,而组文件包含了组名和组 ID 之间的映射关系。

调用 getuid 函数和 getgid 函数可以返回用户 ID 和组 ID。

除了在口令文件中登录名指定一个组 ID 外,大多数 UNIX 系统还允许用户属于多至16个另外的组。

用户登录时,系统读组文件,寻找列有该用户作为成员的前16个记录项就可以得到该用户的附加组 ID(supplementary group ID)。

信号

信号(signal)是通知进程已发生某种情况的一种技术。

进程处理信号有三种选择:(1)忽略信号;(2)按系统默认方式处理;(3)提供一个函数,信号发生时调用该函数,这个过程称为捕捉信号

终端键盘上有两种产生信号的方法,分别称为中断键(interrupt key,通常是 Delete 键或 Ctrl+C)和退出键(quit key,通常是 Ctrl+\),被用来中断当前运行的进程。

调用 kill 函数,也可以产生信号,但是向一个进程发送信号时,登录用户必须是该进程的所有者或者是超级用户。

时间值

UNIX 系统一直使用两种不同的时间值:

  • 日历时间。该值是自1970年1月1日00:00:00以来国际标准时间(UTC)所经过的秒数累计值,主要用来记录文件最近一次的修改时间等。系统基本数据类型 time_t 用于保存这种时间值。
  • 进程时间,也被称为 CPU 时间。该值用来度量进程所使用的CPU资源,以时间滴答计算,每秒钟为50、60或100个滴答。系统基本数据类型 clock_t 用于保存这种时间值。运用 sysconf 函数可以得到每秒时钟滴答数。

当度量一个进程的执行时间时,UNIX 系统使用三个进程时间值:

  • 时钟时间,又称为墙上时钟时间(wall clock time),是进程运行的时间总量,其值与系统同时运行的进程数有关。
  • 用户 CPU 时间,执行用户指令所用的时间。
  • 系统 CPU 时间,为该进程执行内核程序所经历的时间。

其中,用户 CPU 时间和系统 CPU 时间之和为 CPU 时间。

要取得进程的时钟时间、用户时间和系统时间,需要执行命令 time,其参数是需要进行度量执行时间的命令。

系统调用

操作系统提供的服务入口,以便于程序向内核请求服务,这些入口点被称为系统调用

UNIX 为每个系统调用在标准 C 库中设置一个具有相同名字的函数;用户进程用标准 C 调用序列来调用这些函数,函数用系统所要求的技术调用相应的内核服务。从应用角度考虑,可以将系统调用视为 C 函数。在这一点上将,系统调用和库函数有着一定的重叠。

但那是库函数中有很多通用函数,虽然这些函数可能调用一个或多个系统调用实现,但是并不是内核的入口点。由此可见,系统调用通常提供一种最小接口,而库函数通常提供较复杂的功能。

从实现上可以看出,必要时我们可以替换库函数,但是无法替换系统调用。

阅读(1507) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~