《深入计算机系统》(第十一章)(第十二章)(第十三章)

                                第三部分:程序间的交互和通信

第十一章   系统级I/O

输入/输出(I/O)是主存(main   memory)和外部设备(磁盘驱动器、终端和网络)之间拷贝数据的过程。

输入操作是从I/O设备拷贝数据到主存,输出则相反。

所有语言的运行时系统都提供执行I/O的较高级别的工具。高级别I/O函数工作良好,没有必要直接使用Unix  I/O.那么为什么还要麻烦地学习Unix  I/O呢?

1、了解Unix  I/O将帮助你理解其他的系统概念

2、有时你除了使用Unix  I/O以外别无选择。

所有的I/O都能以一种统一且一致的方式来执行:打开文件、改变当前文件位置、读写文件、关闭文件

一个文本行就是一个由换行符结尾的ASCII码字符序列。

内核用三种相关的数据结构来表示打开的文件:1、描述符表   2、文件表   3、v-node 表

I/O 重定向:Unix  shell提供了  I/O重定向操作符,允许用户将磁盘文件盒标准输入输出联系起来。

ANSIC定义了一组高级输入输出函数,称为标准I/O库。为程序员们提供了Unix  I/O的较高级别的接口。

相关的流限定:1、输入函数跟在输出函数之后。2、输出函数跟在输入函数之后。

标准I/O库是基于Unix  I/O实现的。

                  第十二章    网络编程

每个网络都是基于客户端-服务器模型的。客户端-服务器模型中的基本操作是事务。

一个客户端-服务器事务由四部分组成:

1、当一个客户端需要服务时,它想服务器发送一个请求。发起一个事物。

2、服务器收到请求后,解释它,并以适当的方式操作它的资源。

3、服务器给客户端发送一个响应,并等待下一个请求。

4、客户端收到响应并处理它。

客户端-服务器是进程,不是上下文中常被称为的机器或主机。一台主机可以同时运行许多不同的客户端和服务器,而且客户端-服务器的事务可以在同一台或不同的主机上。

客户端和服务器通常运行在不同的主机上,并且通过计算机网络的硬件和软件资源来通信。对于一个主机而言,网络又是一种I/O设备。作为数据源和数据接收方。

多个不兼容的局域网可以通过叫做路由器的特殊计算机连接起来,组成一个internet(互联网络)

我们经常使用小写细目的internet描述一般概念,而大写字母的Internet来描述一种特殊的实际应用,也就是所谓的全球IP因特网。

每台因特网主机都运行实现TCP/IP(传输控制协议/互联网络协议)的软件。

TCP/IP实际是一个协议族,其中每个都提供不同的功能。

IP地址是一个32位无符号整数。

因特网客户端和服务器互相通信时使用的是IP地址,然而,很难记,所以因特网定义了域名,以及一种将域名映射到ip地址的机制。

因特网客户端和服务器通过在线连接上发送和接收字节流来通信,从连接一对进程的意义上而言,连接时点对点的。从数据可以同时双向流动的角度来说,它是全双工的。

套接字是连接的端点。每个套接字都有相应的套接字的地址,是由一个因特网地址和一个16位的整数端口组成的,用“地址:端口”来表示。

一个连接是由它两端的套接字地址唯一确定的。这对套接字地址叫做套接字对。

套接字接口是一组用来结合Unix  I/O函数创建网络应用的函数。

从Unix内核的角度来看,套接字就是通信的端点。从Unix程序的角度来看,套接字就是一个有相应描述符的打开文件。

客户端是发起连接请求的主动实体。服务器是等待来自客户端的连接请求的被动实体。

监听描述符是作为客户端连接请求的一个端点。

已连接描述符是客户端和服务器之间已经建立起来了的连接的一个端点。

Web客户端和服务器之间的交互用的是一个基于文本的应用级协议,叫做HTTP(超文本传输协议)HTTP协议是个简单的协议。一个Web客户端(就是浏览器)打开一个到服务器的因特网连接,并且请求某些内容。服务器响应所请求的内容,然后关闭连接,浏览器读取这些内容,并把它显示在屏幕上。

Web服务和常规的文件检索服务(如:FTP)的主要区别是Web内容可以用HTML来编写。

Web服务器以两种不同的方式向客户端提供内容:1、取一个磁盘文件,并将它的内容返回给客户端。磁盘文件称为静态内容,而返回文件给客户端的过程称为服务静态内容。

2、运行一个可执行文件,并将它的输出返回给客户端。运行时可执行文件产生的输出称为动态内容,而运行程序并返回它的输出到客户端的过程称为服务动态内容。

关于服务器如何解释一个URL的后缀,由三点需要理解:

1、确定一个URL指向的是静态内容还是动态内容没有标准的规则。每个服务器对它所管理的文件都有自己的规则。

2、后缀中的最开始的哪个“/”不表示Unix根目录,它表示的是被请求内容类型的主目录。

3、最小的URL后缀是“/”字符,所有服务器将其扩展为某个默认的主页。

HTTP是基于在因特网连接上传送的文本行的

一个HTTP请求的组成是这样的,一个请求行,后面跟零个或更多个请求报头,再跟随一个空的文本行来终止报头列表。

HTTP响应和HTTP请求是相似的。一个HTTP响应的组成是这样的:一个响应行,后面跟随着零个或更多的响应报头,再跟随一个终止报头的空行,再跟随一个响应主体。

HTTP POST请求中的参数是在请求主体中而不是URL中传递的。

服务器如何将其他信息传递给子进程:CGI定义了大量的其他环境变量,一个CGI程序在它运行时,可以设置这些环境变量。

子进程将它的输出发送到哪里:一个CGI程序将它动态内容发送到标准输出。

                                        第十三章   并发编程

如果逻辑控制流在时间上重叠,那么它们就是并发的,这种一般现象,称为并发性,出现在计算机许多不同的层面中。

目前为止,我们主要将并发性看做是一种内核用来运行多个应用程序的策略。但是并发性不仅仅局限于内核,它可以在应用程序中扮演重要角色。

应用级并行在其他情况下也有用:

1、在多处理器上进行并行计算2、访问慢速I/O设备  3、与人交互  4、通过推迟工作以减少执行时间  5、服务多个网络客户端。

使用应用级并发的应用程序称为并发程序。现代操作系统提供了一种基本的构造并发程序的方法:1、进程(构造并发程序最简单的方法) 2、I/O多路复用 3、线程

关于进程的优劣:对于父、子进程间共享状态信息,进程是一个非常清晰的模型;共享文件表,但是不共享用户地址空间。有独立的进程地址空间既是优点也是缺点,优点:一个进程不可能不小心覆盖另一个进程的虚拟存储器,这就消除了许多令人迷惑的错误。缺点:独立的地址空间使得进程共享状态信息变得更加困难,为了共享信息它们必须使用显示的IPC机制。基于进程设计的另一个缺点是,它们往往比较慢,因为进程控制和IPC的开销很高。

I/O多线路技术可以用作并发事件驱动程序的基础,在事件驱动中流是作为某种事件的结果前进的。

I/O多线路复用技术的优劣:

优点:1、它比基于进程的设计给了程序员更多的对程序行为的控制。

   2、一个基于I/O多路复用的事件驱动器是运行在单一进程上下文中,因此每个逻辑流都能访问该进程的全部地址空间

缺点是编码复杂。

一个线程就是运行在一个进程上下文中的一个逻辑流。

在任何一个时间点上,线程是可结合的或者是分离的。一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程收回之前它是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。

从程序员的角度来看,线程很有吸引力的一个方面就是多个线程很容易共享相同的程序变量。然而这种共享很棘手的,为了编写正确的多线程程序,我们必须对所谓的共享以及它是如何工作的有很清楚的了解。

线程存储器模型:一组并发线程运行在一个进程的上下文中,每个线程都有它自己独立的线程上下文,包括现场呢过ID、栈、栈指针、程序计数器、条件代码和通用目的的寄存器值。每个线程和其他线程一起共享进程上下文的剩余部分。这包括整个用户虚拟地址空间,它是由只读文本(代码)、读/写数据、堆以及所有的共享库代码和数据区域组成的。线程也共享同样的打开文件的集合。

从实际操作的角度来说,让一个线程去读或写另一个线程呢过的寄存器值是不可能的。另一方面,任何线程都可以访问共享虚拟存储器的任意位置。如果某个线程修改了一个存储器位置,那么其他每个线程最终都能在它读这个位置时发现这个变化。因此寄存器是不共享的,而虚拟存储器总是共享的。

各自独立的线程栈的存储器模型不是那么整齐清楚的。这些栈被保存在虚拟地址空间的栈区域中,并且通常它们相应的线程独立第访问。说是通常不是总是,因为不同的线程栈是不对其他线程设防的。所以,如果一个线程不知何故得到一个指向其他线程栈的指针,那么它就可以读这个栈的任何部分。

将变量映射到存储器。多线程的C程序中的变量根据它们存储类型被映射到虚拟存储器。1、全局变量。定义在函数之外的变量  2、本地自动变量。  3、本地静态变量

进度图:一个进度图将n个并发线程的执行模型化为一条n维笛卡尔空间中的轨迹。

一个进度图将指令执行模型化为一个从一种状态到另一种状态的转换。一个转换被表示为一条从一个点到相邻点的有向边,合法的转换时向右或者向上。两个指令不能再同一时刻完成——对角线转换时不允许的,程序觉不会反响运行,所以向下或向左的运行时不合法的。

进度图给了我们一种较好的方法,将在单处理器上的并发程序执行可视化。不过它的确也有局限性,特别是对于在多处理器上的并发执行,多处理器的工作方式是进度图不能解释的。

信号量提供对共享变量的互斥访问、调度对共享资源的访问。

有一类重要的线程安全函数,叫做可重入函数,其特点在于它们具有这样一种属性:当它们被多个线程调用时,不会引起任何共享数据。

竞争:当一个程序的正确性依赖于一个线程要在另一个程序到达y点之前到达它的控制流中的x点时。就会发生竞争。

死锁:信号量引入了一种潜在的令人厌恶的运行时错误,叫做死锁,它指的是一组线程被阻塞了,等待一个永远也不会为真的条件。进程图对于理解死锁是一个无价的工具。

程序员应该总是检查系统级函数返回的错误代码。有许多细微方式导致错误的出现,只有使用内核能够提供给我们的状态信息才能理解为什么有这样的错误。











































发布了49 篇原创文章 · 获赞 3 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章