1.1 引言
1.2 UNIX 体系结构
从严格意义上来说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。
通常将这种软件称为内核。
内核的接口被称为系统调用。
公用函数库构建在系统调用接口之上。
应用程序既可以使用公用函数库,也可以使用系统调用。
shell是一个特殊的应用程序,为运行其他应用程序提供了一个接口。
广义上来说,操作系统包括内核和一些其他软件(系统应用程序,shell,公用函数库等)。
Linux是GNU操作系统使用的内核。
1.3 登录
1. 登录名
在/etc/passwd口令文件中可以查看登录名。
依次是:登录名,加密口令,数字用户ID,数字组ID,注释字段,其实目录,shell程序。
2. shell
shell是一个命令行解释器,它读取用户输入,然后执行命令。
1.4 文件和目录
1. 文件系统
UNIX文件系统是目录和文件的一种层次结构,所有东西的起点是根目录,这个目录的名称是一个字符\。
目录是一个包含目录项的文件。
在逻辑上,可以认为每个目录项都包含一个文件名,同时还包含说明该文件属性的信息(具体实现并非如此)。
2. 文件名
创建新目录时,会自动创建两个文件名:.(称为点),..(称为点点)。
点指向当前目录,点点指向父目录。
在最高层次的根目录中,点点与点相同。
3. 路径名
相对路径名,绝对路径名。
#include <apue.h>
#include <dirent.h>
int
main(int argc, char *argv[])
{
DIR *dp;
struct dirent *dirp;
if(argc != 2)
err_quit(" ");
if((dp = opendir(argv[1])) == NULL)
err_sys(" ");
while((dirp = readdir(dp)) != NULL)
printf("%s\n", dirp->d_name);
closedir(dp);
exit(0);
}
4. 工作目录
所有相对路径名都是从工作目录开始解释的。
5. 起始目录
1.5 输入和输出
1. 文件描述符
文件描述符通常是一个小的非负整数,内核用以标记一个特定进程正在访问的文件。
2.标准输入,标准输出和标准错误
每当运行一个新程序时,所有shell都为其打开3个文件描述符。
如果不做特殊处理,则这三个描述符都链接向终端。
3. 不带缓冲I/O
函数open,read,write,lseek以及close提供不带缓冲的I/O。
COPY FROM : m.yisu.com/zixun/19489…
首先要明白不带缓冲的概念:所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用,不是函数库的调用。系统内核对磁盘的读写都会提供一个块缓冲(在有些地方也被称为内核高速缓存),当用write函数对其写数据时,直接调用系统调用,将数据写入到块缓冲进行排队,当块缓冲达到一定的量时,才会把数据写入磁盘。因此所谓的不带缓冲的I/O是指进程不提供缓冲功能(但内核还是提供缓冲的)。每调用一次write或read函数,直接系统调用。
而带缓冲的I/O是指进程对输入输出流进行了改进,提供了一个流缓冲,当用fwrite函数网磁盘写数据时,先把数据写入流缓冲区中,当达到一定条件,比如流缓冲区满了,或刷新流缓冲,这时候才会把数据一次送往内核提供的块缓冲,再经块缓冲写入磁盘。(双重缓冲)
因此,带缓冲的I/O在往磁盘写入相同的数据量时,会比不带缓冲的I/O调用系统调用的次数要少。
4. 标准I/O
标准I/O函数为那些不带缓冲的I/O函数提供了一个带缓冲的接口。
最熟悉的标准I/O函数是printf。
1.6 程序和进程
1. 程序
程序是一个存储在磁盘上某个目录中的可执行文件。
内核使用exec函数,将程序读入内存,并执行程序。
2. 进程和进程ID
pid_t getpid();
3. 进程控制
fork,exec,waitpid
4. 线程和线程ID
这里APUE有误吗?书上写的线程会共享栈,存疑。
COPY FROM:www.nowcoder.com/questionTer…
线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。
1.7 出错处理
当UNIX系统函数出错时,通常会返回一个负值,而且整型变量errno通常被设置为具有特定信息的值。
C标准定义了两个函数,他们用来打印出错信息。
#include <string.h>
char *strerror(int errnum);
将errnum映射为一个出错消息字符串,并返回此串的指针。
#include <stdio.h>
void perror(const char *msg);
它首先输出由msg指向的字符串,然后是一个冒号,一个空格,接着是对应于errno值的出错消息,最后是一个换行符。
出错恢复
出错分为两类:致命性和非致命性。
对于致命性,无法执行恢复动作。
对于非致命性:妥善处理。
对于资源相关的非致命性错误的典型恢复操作是延迟一段时间,然后重试。
1.8 用户标识
1. 用户ID
ID为0的是超级用户,根用户。
2. 组ID
/etc/group
3. 附属组ID
每个用户属于最多16个其他的组
1.9 信号
信号用于通知进程发送了某种情况。
进程有以下3中处理信号的方法:
- 忽略。
- 按系统默认方式处理。
- 提供一个函数,信号发生时调用该函数,这被称为捕捉该函数。
1.10 时间值
- 日历时间
time_t
- 进程时间
clock_t
当度量一个进程的执行时间时,UNIX系统为一个进程维护了3个进程时间值:
- 时钟时间
- 用户CPU时间
- 系统CPU时间
1.11 系统调用与库函数
所有的操作系统都提供多种服务的入口点,由此程序向内核请求服务。 各种版本的UNIX实现都提供良好定义的,数量有限,直接进入内核的入口点,这些入口点被称为系统调用。
系统调用接口总是在《UNIX程序员手册》的第二部分中说明,由C语言定义的,与具体系统如何调用一个系统调用的实现技术无关。
UNIX是为每个系统调用在标准C库中设置一个同样名字的函数。
用户进程用标准C调用序列来调用这些函数,然后,函数又用系统所要求的技术调用相应的内核服务。
《UNIX程序员手册》第三部分定义了程序员可以使用的通用库函数。虽然这些函数可能会调用一个或多个内核的系统调用,但是他们并不是内核的入口点。
从实现者角度来看,系统调用和库函数之间有根本的差别,但从用户角度来看,其区别并不重要。
在本书中,系统调用和库函数都是以C函数形式出现,两者都为应用程序提供服务。
习题
COPY FROM github.com/Tianpingan/…
1. 在系统上验证,除根目录外,目录 . 和目录 .. 是不同的
用指令ls -ai就能列出.和..的inode。
2. 分析1.6.2.c的输出,说明进程 ID 为 852 和 853 的进程发生了什么情况
在执行这两次程序的间隙中,系统产生了ID为852和853的其他进程,所以第二次运行进程ID为854。
3. 在1.7.c中, perror 的参数是用 ISO C 的属性 const 定义的,而 strerror 的整形参数没有用此属性定义,为什么?
下面是两个函数的定义:
#include <string.h>
char *strerror(int errnum);
#include <stdio.h>
void perror(const char *msg);
strerror 传递的参数为 int 类型,将会在对应的函数内复制一份,因此不会修改原来参数的值
perror 传递的参数为 const char * 类型,传递的是对应的地址,如果不使用 const 限定的话,那么如果在函数内修改了值,函数外的变量值也会变化。
COPY FROM : bbs.csdn.net/topics/1048…
const char *的作用:定义的字符串不能被改变,但是指针可以改变 指针内容不能改变
1 指向变量的指针变量:
出身: int * point;
遭遇: 两人都另有新欢
心声: 你可以变心,我也可以爱别人,很公平。
2 指向常量的指针变量:
出身: const int * point;
遭遇: 抛弃对方
心声: 说过多少回了,我们之间已经结束了,你别再缠着我了,告诉你,我已经有了新的女朋友了
3 指向变量的指针常量:
出身: int * const point;
遭遇: 被对方抛弃
心声: 你怎么可以这样呢,你知道我的心里永远只有你一个,你怎么可以爱上别人呢
4 指向常量的指针常量:
出身: const int * const point;
遭遇: 两情相悦,天长地久
心声: 你是我的唯一,我是你的永远,钻石恒久远,怎即我俩情
怎么判断:主要是看const的位置来确定,如果在" * "画一条竖线,const在竖线左边即所指的目标为常量,如果在竖线右边即指针本身是常量,两边都有就意味着都是常量.
4. 若日历时间存放在带符号的 32 位整型数中,那么到哪一年它将溢出?可以用什么办法扩展溢出浮点数?采用的策略是否与现有的应用相兼容?
32 位整型数的最大值为 2147483647 ,大概为 68.09626 年。通过查询可知,最大可表示到 2038-01-19 11:14:07
使用 IEEE754 编码扩展(double),与现有的应用不一定兼容。
5. 若进程时间存放在带符号的 32 位整型数中,而且每秒为 100 时钟滴答,那么经过多少天后该时间值将会溢出?