20145308 《信息安全系统设计基础》第13周学习总结
20145308 《信息安全系统设计基础》第13周学习总结
教材学习内容总结
视频学习
- 接口:指明模块要做什么
- 实现:指明模块如何完成接口
- 函数签名:函数名、参数个数、返回值
- 万能函数
- 并发:程序级并发(进程)、函数级并发(线程)
第12章 并发编程
- 构造并发程序的方法
- 进程:每个逻辑控制流都是一个进程,由内核来调度和维护,有独立的虚拟地址,使用某种显式的进程间通信机制
- I/O多路复用:应用程序在一个进程的上下文中显式地调度他们自己的逻辑流,共享地址空间
- 线程:运行在单一进程上下文中的逻辑流,由内核进行调度,共享单一虚拟地址
12.1 基于进程的并发编程
- 构造并发服务器:父进程中接受客户端连接请求,然后创建一个新的子进程来为每个新用户端提供服务
12.1.1 基于进程的并发服务器
- 因为通常服务器会运行很长时间,所以需要一个SIGCHLD处理程序,来回收僵死进程。因为当SIGCHLD执行时,信号是阻塞的,而UNIX信号是不排队的,所以SIGCHLD必须准备好回收多个僵死进程。另外注意,循环中的父进程和子进程关闭各自需要关闭的描述符。
12.1.2 关于进程的优劣
- 进程能够共享文件表,但不共享用户地址空间
12.2 基于I/O多路复用的并发编程
- I/O多路复用技术。基本思想是,使用select函数,要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序
12.2.1 基于I/O多路复用的并发时间驱动服务器
- I/O多路复用可以用做并发事件驱动程序的基础,在事件驱动程序中,流是因为某种事件而前进的,一般概念是把逻辑流模型化为状态机。一个状态机就是一组状态、输入事件和转移。
- 并发事件驱动程序中echo服务器中逻辑流的状态机
12.2.2 I/O多路复用技术的优劣
- 优点:给了程序员更多的对程序行为的控制、流之间共享数据容易
- 缺点:编码复杂
12.3 基于线程的并发编程
- 线程:运行在进程上下文中的逻辑流
- 线程由内核自动调度,每个线程都有它自己的线程上下文
12.3.1 线程执行模型
- 每个进程开始生命周期时都是单一线程,这个线程称为主线程
- 在某一时刻,主线程创建一个对等线程,从在此刻开始,两个线程就并发地运行
- 和一个进程相关的线程组成一个对等(线程)池,独立于其他线程创建的线程
- 对等(线程)池党的重要概念:一个线程可以杀死它的任何对等线程,或者等待它的任意对等线程终止
- 每个对等线程都能读写相同的共享数据
12.3.2 Posix线程
- Posix线程(Pthreads)是在C程序中处理线程的一个标准接口
- 允许程序创建、杀死和回收线程,与对等线程安全地共享数据,还可以通知对等线程系统状态的变化
12.3.3 创建线程
- 通过调用
pthread_create
函数来创建其他线程 - 新线程可以通过
pthread_self
函数来获得它自己的线程ID
12.3.4 终止线程
-
有以下四种方式终止线程:
当顶层的线程例程返回时,线程会隐式终止; 线程调用`pthread_exit`函数,线程会显示终止;如果主线程调用`pthread_exit`,它会等到所有其他对等线程终止,然后再终止主线程和整个线程,返回值为`thread_return`; 某个对等线程调用`exit`函数,则函数终止进程和所有与该进程相关的线程; 另一个对等线程调用以当前ID为参数的函数`ptherad_cancel`来终止当前线程
12.3.5 回收已终止线程的资源
pthread_join
函数会终止,直到线程tid终止。和wait
不同,该函数只能回收指定id的线程,不能回收任意线程
12.3.6 分离线程
- 一个可结合的线程能够被其他线程回收其资源和杀死,在被其他线程回收之前,它的存储其资源是没有被释放的
- 相反,一个分离的线程是不能被其他线程回收或杀死的。它的存储器资源是在它终止时系统自动释放的
12.3.7 初始化线程
pthread_once
函数允许初始化与线程例程相关的状态
12.3.8 一个基于线程的并发服务器
12.4 多线程程序中的共享变量
12.4.1 线程存储器模型
- 每个线程都有它自己独自的线程上下文,包括线程ID、栈、栈指针、程序计数器、条件码和通用目的寄存器值
- 每个线程和其他线程一起共享进程上下文的剩余部分
- 寄存器是从不共享的,而虚拟存储器总是共享的
12.4.2 将变量映射到存储器
- 线程化的c程序中变量根据它们的存储器类型被映射到虚拟存储器:全局变量,本地自动变量(不共享),本地静态变量
- 全局变量:定义在函数之外的变量。虚拟存储器的读/写区域只包含每个全局变量的一个实例,任何线程都可以引用
- 本地自动变量:定义在函数内部但没有static属性的变量
- 本地静态变量:定义在函数内部并有static属性的变量
12.4.3 共享变量
- 共享:当且仅当它的一个实例被一个以上的线程引用
12.5 用信号量同步线程
12.5.1 进度图
- 进度图
- 不安全区:两个临界区的交集形成的状态安全区域
12.5.2 信号量
- 信号量:是用信号量解决同步问题,信号量s是具有非负整数值的全局变量,有两种特殊的操作来处理(P和V)
- P(s):如果s非零,那么P将s减1,并且立即返回。如果s为0,那么就挂起这个线程,直到s变为非零
- V(s):V操作将s加1
12.5.3 使用信号量来实现互斥
- 二元信号量:用P和V操作将相应的临界区包围起来的方式来保护共享变量的信号量
- 互斥锁:以提供互斥为目的的二元信号量
12.5.4 利用信号量来调度共享资源
- 生产者——消费者问题:必须保证对缓冲区的访问是互斥的;还需要调度对缓冲区的访问,即,如果缓冲区是满的(没有空的槽位),那么生产者必须等待直到有一个空的槽位为止,如果缓冲区是空的(即没有可取的项目),那么消费者必须等待直到有一个项目变为可用
- 读者——写者问题:修改对象的线程叫做写者;只读对象的线程叫做读者。写着必须拥有对对象的独占访问,而读者可以和无限多个其他读者共享对象。读者——写者问题基本分为两类:第一类,读者优先,要求不要让读者等待,除非已经把使用对象的权限赋予了一个写者。换句话说,读者不会因为有一个写者等待而等待;第二类,写者优先,要求一定能写者准备好可以写,它就会尽可能地完成它的写操作。同第一类问题不同,在一个写者后到达的读者必须等待,即使这个写者也是在等待
12.5.5 综合:基于预线程化的并发服务器
- 使用预线程化技术的并发服务器:服务器是由一个主线程和一组工作组线程构成的。主线程不断地接受来自客户端的连接请求,并将得到的连接描述符放在一个有限缓冲区中。每一个工作组线程反复地从共享缓冲区中取出描述符,为客户端服务,然后等待下一个描述符
12.6 使用线程提高并行性
12.7 其他并发问题
12.7.1 线程安全
- 四种不安全函数
- 不保护共享变量的函数
- 保持跨越多个调用状态的函数
- 返回指向静态变量的指针的函数
- 调用线程不安全函数的函数
12.7.2 可重入性
- 可重入函数:可重入函数是线程安全函数的一个真子集,它不访问任何共享数据。可重入安全函数通常比不可重入函数更有效,因为它们不需要任何同步原语。
12.7.3 在线程化的程序中使用已存在的库函数
12.7.4 竞争
- 竞争:当程序员错误地假设逻辑流该如何调度时,就会发生竞争。为了消除竞争,通常我们会动态地分配内存空间。
12.7.5 死锁
- 死锁:当一个流等待一个永远不会发生的事件时,就会发生死锁
第11章 网络编程
11.1 客户端——服务器编程模型
- 每个网络应用都是基于客户端-服务器模型
11.2 网络
- 以太网段:包括一些电缆和集线器
- 桥接以太网:使用一些电缆和网桥,多个以太网连接成的较大局域网
- internet互联网络:多个不兼容的局域网通过路由器连接
- 协议消除了不同网络之间的差异
11.3 全球IP因特网
- 每台因特网主机上都运行实现TCP/IP协议
11.3.1 Ip地址
- 网络字节顺序:大端字节法
11.3.2 因特网域名
gethostbyname
和gethostbyaddr
函数,从DNS库中检索任意主机条目
11.3.3 因特网连接
- 因特网客户端和服务器通过在连接上发送和接收字节流来通信
11.4 套接字接口
- 套接字接口:一组函数,与Unix I/O函数结合起来,用以创建网络应用
11.4.1 套接字地址结构
- 从Unix程序的角度来看,套接字就是一个有相应描述符的打开文件
11.4.2 socket函数
- 服务器和客户端使用
socket
函数创建套接字描述符
11.4.3 connect函数
- 客户端调用
connect
函数来建立和服务器的连接
11.4.4 open_clientfd函数
11.4.5 bind函数
- 服务器用来和客户端建立连接
bind
函数将my_addr
中的服务器套接字地址和套接字描述符sockfd
连接起来
11.4.6 listen函数
- 将
sockfd
从一个主动套接字转化为一个监听套接字
11.4.7 open_listenfd函数
11.4.8 accept函数
- 服务器等待来自客户端的请求
11.4.9 echo客户端和服务器的示例
11.5 web服务器
11.5.1 web基础
- web客户端与服务器交互用基于文本的应用级自协议HTTP
11.5.2 web内容
- 服务静态内容:读取磁盘内容返回客户端
- 服务动态内容:运行可执行文件并输出结果
11.5.3 HTTP事务
- 1.HTTP请求
- 2.HTTP响应
11.5.4 服务动态内容
11.6 综合:TINY Web服务器
本周代码托管截图
https://git.oschina.net/yg1022/CSAPP2E.git
其他
- 本周学习了11、12两章的内容,11章是网络编程的内容,但是和老师课程的内容有一些不一样,学习时主要注意了不同的部分。12章学习了并发编程,主要学习了三种方法,减少程序的运行时间。本周内容还是有些多的,希望自己下周能早点开始完成任务
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/2 | 25/30 | 学习Linux指令 |
第二周 | 50/50 | 1/3 | 25/55 | Linux系统下的开发环境 |
第三周 | 20/70 | 1/4 | 25/80 | 信息的表示和处理 |
第五周 | 20/90 | 1/5 | 30/110 | 程序的机器级表示 |
第六周 | 20/110 | 1/6 | 30/140 | 处理器体系结构 |
第七周 | 20/130 | 1/7 | 30/170 | 存储器层次结构 |
第八周 | 0/130 | 2/9 | 10/180 | 期中复习 |
第九周 | 48/178 | 2/11 | 10/190 | 系统级I/O、错误处理 |
第十周 | 539/717 | 2/13 | 10/200 | 系统调用学习 |
第十一周 | 429/1146 | 2/15 | 10/210 | 异常控制流 |
第十二周 | 20/1166 | 3/18 | 10/220 | 第九、十、十一周代码 |
第四周 | 1174/2340 | 1/19 | 10/230 | 网络编程、并发编程 |