引出
- 每一个进程有自己的地址空间,进程的独立性通过地址空间和页表实现的
- 创建一个进程的代价很高,有pCB,页表,地址空间
现在创建进程时只创建pcb,不创建页表和地址空间- 主pcb和新创建的pcb共享地址空间,这四个进程指向同一个地址空间和页表,执行的代码全是一样的
- 进程看待自己的资源是通过地址空间结合页表看的
- 父子进程通过if else划分,此时通过函数将地址空间每个区拆成四份
- 什么是线程:只占用地址空间一部分代码,使用一部分页表的执行流就叫 线程
- 对于Linux线程理解:
- 只创建pcb,将这个pcb指向父进程地址空间,将进程部分代码数据地址空间页表都分给他,只执行进程一部分
在进程内部运行的执行流,在进程地址空间内部,线程执行粒度细(因为调用的代码少,数据少),调度成本低,地址空间和页表不用切换
线程是cpu执行基本单位,因为cpu只看线程
这些是在Linux下实现的原理,因为Linux没有为线程创建对应的数据结构
线程是在进程内部运行的
为了描述线程,线程有一个tcb
Linux认为没有进程线程,只有执行流,Linux中不存在真正的进程线程,Linux的线程是用进程的pcb模拟的,tcb和pcb是一样的,是有tcb,只不过是复用了,
所以Linux下的进程<=其它os下的进程,所以Linux下的进程叫轻量级进程,就是线程
win是实现了,就需要设计多进程和多线程的接口
以前,cpu看到的所有task就是一个进程,现在taskstruct就变成了一个执行流
新进程定义:内核视角,承担分配系统资源的基本实体。是向系统申请资源的基本单位
以前的进程,内部只有一个执行流的进程
叫单执行流进程
内部有多个执行流叫多执行流进程
字符串常量不可被修改,是怎样被加载的
只读属性是在页表处处理的
UK区分指向当前代码是内核还是用户的
io密集型,大部分代码是需要进行io,不同线程访问不同io资源,资源未就绪多线程可以同时等待
计算密集型,
健壮性,多线程很多资源共享,线程之间的隔离性不好
信号屏蔽字,屏蔽某个信号
线程有独立的栈
线程有自己的寄存器
线程概念
- 创建一个进程就会在内核中创建一个相应的PCB,
PCB中的内存指针指向进程虚拟地址空间;- 创建一个线程相当于又在内核中创建一个PCB,
线程中的内存指针也指向进程虚拟地址空间;- 两者的内存指针指向的是同一个进程虚拟地址空间;
- 将进程称为主线程,里面包含的线程称为工作线程,
一个进程中有且只有一个主线程
两者的PCB不同
- 线程在内核中也是一块PCB,也会被挂到内核的双向链表中;
线程是操作系统调度的最小单位(或称为基本单位);- 一个进程有多个线程,操作系统在分配资源的时候不是给线程分配,而是给进程分配;
进程是操作系统分配资源的基本单位
进程号与线程号
- pid:线程号,用于标识不同的线程,一个线程对应一个线程号;
- tgid:线程组号,用于标识不同的线程组,一个线程组号对应一个或者一堆线程
- 对于主线程,pid = tgid;
- 对于工作线程,同一个线程组中的tgid相等,表示同一个进程中不同的线程;
- 之前一直说的进程号其实是tgid;
在内核角度应站在进程角度看待pid,在C标准库中应站在线程角度看pid;
因为在内核角度中没有线程概念的,线程的概念是C库中的概念,所以称pid为进程号这句话是对的
线程标识符
因为主线程和工作线程都指向同一进程虚拟地址空间,如何区分各自线程的在同一地址空间的操作位置,就需要线程独有的空间解决;
线程标识符是线程独有空间的首地址
每创建一个线程,就会在共享区创建一个独属于线程的空间
线程的独有和共享:
线程间独有内容,在该空间中有
- 线程号(LWP)
- 栈(与主线程栈不同)
- errno(系统错误码)
- 信号屏蔽字(位图)
- 用于线程切换的一组寄存器,
切换时需要程序计数器和上下文信息- 调度优先级
线程间共享内容
- 文件描述符表,就是fd_array数组,
主线程打开一个文件,工作线程也可以访问其内容- 信号的处理方式
对于每个进程和进程中的线程都是一样的- 当前的工作目录
当前进程在哪一个工作的目录启动的- 用户id和用户组id
谁启动的线程,该用户属于哪一个用户组
线程优缺点
并行 | 多个进程(执行流)在同一时刻,使用不同的CPU继续运算 |
---|---|
并发 | 多个进程(执行流)在同一时刻,有且只有一个执行流拥有CPU进行运算 |
在进程中存在着一个主线程,线程又称之为执行流,所以可以将上述的进程改成执行流 |
优点:
- 创建一个新线程的代价小于新进程
- 线程切换代价小于进程切换
- 线程占用资源更少
- 能充分利用多处理器的可执行数量
就是说多线程可以并发运行- 对于CPU
- 等待慢速IO操作结束的同时,程序可执行其它运行任务
- 计算密集型应用,将一个大型任务拆分成子任务完成
- IO密集型应用,大量数据输入输出,线程可以同时等待不同的IO操作
缺点:
- 如果一个进程中的多个线程在频繁的继续切换,则程序的运行效率有肯降低,性能损失在了频繁的线程切换中;
所以一个进程中的线程不是越多越好,进程的执行效率一定随着线程数量的增加,性能呈正太分布的- 缺乏访问控制,进程是访问控制的基本粒度;
多个线程在访问同一变量时,可能让程序结果的二义性- 健壮性降低
一个线程的崩溃会引发整个进程崩溃,线程之间缺乏保护- 编程难度提高
多进程和多线程的区别
多进程:一个程序在运行时会创建多个进程(例如守护进程,bash)
多线程:一个进程中有多个线程
多进程程序,一个进程崩溃不会影响其它进程;多线程程序,一个线程崩溃整个进程就会崩溃