Linux第十二讲:线程概念与控制
Linux第十二讲:线程概念与控制
- 1.什么是线程 -- 感性理解线程
- 2.什么是线程 -- 理性理解线程
- 2.1什么是页表
- 2.1.1页框
- 2.1.2页表
- 2.1.3什么是线程
- 2.1.4两级页表的地址转换
- 2.1.5缺页异常
- 2.1.6线程的优点
- 2.1.7线程的缺点
- 3.Linux进程 VS 线程
- 4.Linux线程控制
- 4.1创建线程
- 4.2LWP -- 轻量级进程
- 4.3pthread库
- 4.4线程等待
- 4.5线程终止
- 4.6多线程的创建
- 4.7线程ID
- 4.8通过源码深入理解线程
- 4.9线程栈
- 5.线程的封装
- 5.1传入对象的仿函数实现
- 6.线性局部存储
- 6.1线程命名
1.什么是线程 – 感性理解线程
2.什么是线程 – 理性理解线程
要理解线程,我们首先来了解一下页表
2.1什么是页表
2.1.1页框
2.1.2页表
页表的本质是一个结构体,一个进程一个页目录表,指向多个页表,页表里面记录了页表项和页内偏移(前20位和后12位),当需要访问物理地址时,需要先拿到虚拟地址,访问页表,实现虚拟地址到物理地址的转化,一个进程中,需要多次访问页表操作,而进行转换的过程,是通过MMU来完成的
二级页表,页目录中有1024个unsigned int类型数据保存地址,每个页表中也是1024个unsigned int类型数据保存地址
所以说,当我们拿到虚拟地址之后,假如虚拟地址为32位,那么通过前20位可以找到对应的页框,也就是拿到虚拟页号,每个页框是4KB,那么通过页框号*4KB + 页内偏移(低12位),就可以找到内存中的页框的物理地址了,通过内存物理地址,可以计算出磁盘中的地址(磁道等内容),就可以进行操作了
2.1.3什么是线程
2.1.4两级页表的地址转换
2.1.5缺页异常
2.1.6线程的优点
2.1.7线程的缺点
3.Linux进程 VS 线程
4.Linux线程控制
4.1创建线程
4.2LWP – 轻量级进程
4.3pthread库
所以说,任何一门语言,只要是在Linux环境下运行,提供的创建线程的方法的底层都是对Linux提供的创建轻量级进程的方法,也就是pthread库的封装:
4.4线程等待
线程创建好之后,新进程要被主进程等待,否则就会出现类似僵尸进程的问题,会导致内存泄漏
然而,线程的返回值并不可以只是int类型的,可以是多种类型的:
4.5线程终止
4.6多线程的创建
之前所学的都是单线程的创建,下面我们来看一下多线程的创建:
4.7线程ID
那么线程ID到底是什么呢?:
4.8通过源码深入理解线程
4.9线程栈
Linux下,将线程和进程都统一到了task_struct(名称相同,但是不同的方法创建,创建出的task_struct中的内容不同), 但是对待线程和进程的stack还是有区别的:
1.对于进程来说,通过fork进行创建时,实际上是复制父进程的stack空间地址,然后写时拷贝与动态增长,如果扩充超过上限报段溢出错误。进程栈是唯一可以访问未映射页而不一定发生段错误 – 超出扩容上线才报
2.对于主进程的子线程而言,栈不是向下生长的,而是提前就固定好的,一旦用尽就会报错。在使用pthread_create时,会调用mmap调用为线程分配栈空间。
线程有自己独立的栈空间,但是同一进程的不同线程,仍然可以访问到不是自己的栈空间,需要注意。
5.线程的封装
假如我们想通过这种方式,直接实现线程的创建、分离、暂停、回收操作,该如何进行封装呢?:
其实很简单,只需要在类中掉哦应那个函数接口即可:
但是这里有一个问题:
pthread_create接口中的传参和函数调用该怎么实现呢?:
5.1传入对象的仿函数实现
如果我们想让传入的参数是类,该怎么实现:
6.线性局部存储
还有一个小点我们要了解以下,那就是线性局部存储