2017-2018-1 20155214 《信息安全系统设计基础》 第8周学习总结
2017-2018-1 20155214 《信息安全系统设计基础》
第8周学习总结
教材学习内容总结
- 掌握三种并发的方式:进程、线程、I/O多路复用
- 掌握线程控制及相关系统调用
- 掌握线程同步互斥及相关系统调用
教材学习中的问题和解决过程
I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流. 发明它的原因,是尽量多的提高服务器的吞吐能力。
- 通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
Pthread是一种标准化模型,它用来把一个程序分成一组能够同时执行的任务。
什么场合会使用Pthread即线程?
1、 在返回前阻塞的IO任务能够使用一个线程处理IO,同时继续执行其他处理任务。
2、 在有一个或多个任务受不确定性事件,比如网络通信的可获得性影响的场合,能够使用线程处理这些异步事件同时继续执行正常的处理。
3、 如果某些程序功能比其他的功能更重要,可以使用线程以保证所有功能都出现,但那些时间密集型的功能具有更高的优先级。
从以上三点可以归纳位:在检查程序中潜在的并行性,也就是说找出能够同时执行任务时使用Pthread。但是以上已经介绍了Linux进程模型已经提供了执行多个进程的能力,已经可以进行并行或并发编程。可是线程能够让你对多个任务的控制程度更好,。使用资源更少,因为一个单一的资源,如全局变量,可以由多个线程共享。而且,在拥有多个处理器的系统上,多线程应用会比用多个
Linux线程实现方法
目前线程用两种方法实现:
(1)用户态线程:
用户线程是一个精细的软件工具,允许多线程的程序运行时不需要特定的内核支持。如果一个进程中的某一个线程调用了一个阻塞的系统调用,该进程就会被阻塞,当然该进程中的其他所有线程也同时被阻塞,因此UNIX使用了异步I/O机制。这种机制主要的缺点在于在一个进程中的多个线程的调度中无法发挥多处理器的优势(如上述的阻塞情况)。
其优点包括:
1、某些线程操作的系统消耗大大减少。比如,对属于同一个进程的线程之间进行调度切换时不需要调用系统调用,因此将减少额外的消耗,往往一个进程可以启动上千个线程也没有什么问题。
2、 用户态线程的实现方式可以被定制或修改以适应特殊应用的要求。这对于多媒体实时过程等尤其有用。另外,用户态线程可以比核心态线程实现方法的默认情况支持更多的线程。
(2)核心态线程
这种线程的实现方法允许不同进程中的线程按照同一相对优先调度方法进行调度。这有利于发挥多处理器的并发优势。目前线程主要的实现方法是用户态线程。有几个研究项目已经实现了一些核心态线程的形式。其中比较著名的是MACH分布式操作系统。通过允许用户代码对内核线程调度的参与,该系统将用户态和核心态两种线程实现方法的优点结合了起来。通过提供这样一个两级调度机制,内核在保留了对处理器时间分配的控制的同时,也使一个进程可以充分利用多处理器的优势。
四、Linux对超线程技术支持
超线程技术是Intel 公司的创新设计,藉由在一颗实体处理器中放入二个逻辑处理单元,让多 线程软件可在系统平台上平行处理多项任务,并提升处理器执行资源的使用率。使用这项技术,处理器的资源利用率可获得提升,大大增加处理的传输量。 超线程使得单个的处理器可以伪装成操作系统看来二个或更多的多个处理器。Linux内核在2.4.17发布中开始包含对Intel P4处理器的超线程(Hyperthreading)的支持(2.4最初的发布版本中不支持它)。Linux是第一个把超线程特性引入市场的操作系统,尽管早在一年前Intel就发布了兼容的处理器。它包括了以下增强技术:
-
128 字节锁对齐。
-
螺旋等待循环优化 。
-
基于非执行的延迟循环 。
-
检测支持超线程的处理器,并启动逻辑处理器,如同该机器是SMP(多处理器构架) 。
-
MTRR 和微码更新(Microcode Update)驱动程序中的串行化,因为它们影响共享状态 。
-
在逻辑处理器上的调度发生之前,当系统空闲时对物理处理器上的调度进行优先级排序时,对调度程序进行优化 。
-
偏移用户堆栈以避免 64K 混叠 。
代码调试中的问题和解决过程
- 问题1:线程如何实现互斥?
- 问题1解决方案:
互斥锁
- 互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁( lock )和解锁( unlock )。
互斥锁的操作流程如下:
1)在访问共享资源后临界区域前,对互斥锁进行加锁。
2)在访问完成后释放互斥锁导上的锁。
3)对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。
- 线程互斥实例
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex; //互斥锁
// 打印机
void printer(char *str)
{
pthread_mutex_lock(&mutex); //上锁
while(*str!='\0')
{
putchar(*str);
fflush(stdout);
str++;
sleep(1);
}
printf("\n");
pthread_mutex_unlock(&mutex); //解锁
}
// 线程一
void *thread_fun_1(void *arg)
{
char *str = "hello";
printer(str); //打印
}
// 线程二
void *thread_fun_2(void *arg)
{
char *str = "world";
printer(str); //打印
}
int main(void)
{
pthread_t tid1, tid2;
pthread_mutex_init(&mutex, NULL); //初始化互斥锁
// 创建 2 个线程
pthread_create(&tid1, NULL, thread_fun_1, NULL);
pthread_create(&tid2, NULL, thread_fun_2, NULL);
// 等待线程结束,回收其资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&mutex); //销毁互斥锁
return 0;
}
- 测试用例结果截图
代码托管
结对及互评
本周结对学习情况
- [20155216](博客链接)
- 结对照片
- 结对学习内容