操作系统-进程管理(二)

线程

为什么使用它?

  • 可以并发执行
  • 线程间共享相同的地址空间、资源。(进程不可以)

定义:

  • 进程中的一条执行路径。
    在这里插入图片描述
    TCB:每个线程有自己的PC SP 寄存器。
    在这里插入图片描述
    使用场景:
    线程:比如天气预报复杂计算适用于线程。
    进程:比如浏览器,开启问题网页容易导致整个浏览器崩溃,所以每个网页是一个独立进程,互相不受影响。
  • 数量关系
    • 1对1 DOS系统单进程单线程
    • 早期Unix多进程,每个进程1个线程
    • Windos NT 多进程,每个进程对应多个线程

在这里插入图片描述
对于多线程,每个线程有自己独立的PC,寄存器,栈。共享进程的代码段、数据段、文件、网络等。

进程线程区别

  • 资源组合方面:进程把一组资源组合到一起,包括地址空间(代码段、数据段)、打开文件、网络等。
  • 运行方面:线程是在这个资源平台上的一条执行流程。
  • 进程是分配资源内存,线程是执行单元
  • 线程创建和终止时间短(不用考虑资源的创建和销毁)
  • 线程切换快于进程切换(线程共享同一个页表,进程切换要调用不同的页表,切换页表地址空间不同、cache不同、TLB不同导致开销大)
    在这里插入图片描述

线程的实现

  • 三种实现方式
    • 用户线程:用户空间实现操作系统看不见、由用户线程库进行管理
    • 内核线程:内核中实现(操作系统管理,可看见)
    • 轻量级进程:在内核中实现,支持用户线程。
  • 用户线程与内核线程对应关系
    • 一对一
    • 多对一
    • 多对多
      在这里插入图片描述
      如图,用户线程是由TCB管理,操作系统看不到TCB。
  • 用户线程
    • 用户空间实现的线程机制,不依赖于操作系统内核,由一组用户级的线程库函数来完成线程的管理,包括创建、终止、同步、调度。
      • 用户线程维护由进程完成(通过线程库函数),不需要操作系统内核了解用户线程的存在
      • 每个进程都有自己的私有TCB(线程控制块)列表,用来跟踪记录各个线程状态(PC、栈指针、寄存器),TCB由线程库函数维护。
      • 用户线程切换也由线程库函数完成,无需用户态/内核态转换。速度快。
      • 允许每个进程拥有自定义的线程调度算法。
        在这里插入图片描述
        针对第二点:由于操作系统管理中断,可以更换执行进程。操作系统无法控制用户线程,用户线程无法更换执行线程,所以需要主动交出CPU才能执行其他用户线程。

用户线程就是为了并发,可以创建的数量很多,而且不经过操作系统。

  • 内核线程
    在这里插入图片描述
    TCB放在内核里
    在这里插入图片描述
    针对第二点:线程的创建、终止、切换都要经过用户态到内核态的转化,消耗大。
  • 轻量级进程(LightWeight Process)
    在这里插入图片描述

进程上下文切换

在这里插入图片描述
将每个进程的信息存储到PCB中,切换到哪个进程,去PCB读取当前进程信息,CPU在去执行。
在这里插入图片描述
在这里插入图片描述
系统将PCB放置在一个合适的队列里。(阻塞队列,就绪队列,僵尸队列)

进程创建

  • 创建新进程系统调用:fork/exec
    • fork()把一个进程复制成两个进程
      • parent(Old id)child(new id)
    • exec()用新程序重写当前进程
      • pid没有改变
// A code block
int pid = fork(); // create child process
if(pid == 0){ //child process continue
   //do anything ummap memory ,close net connections...
   exec("program",arg1,arg2,arg3...);
}

fork以后父子进程返回值不同,pid=0是子进程。

  • fork创建个继承的子进程
    • 复制父进程的所有变量和内存
    • 复制父进程的所有CPU寄存器(一个除外PID)
  • fork返回值
    • 子进程返回0
    • 父进程返回子进程id
      在这里插入图片描述

fork以后复制父进程所有信息,此时,父进程和子进程除了pid,其余一样,执行exec以后,子进程的代码数据堆栈就按照exec的参数发生了变化。

  • fork开销
    • 对子进程分配内存
    • 复制父进程的内存和CPU寄存器信息
    • 复制信息,开销大
  • VFork()[virtual Fork]
    • 创建进程时不再创建一个同样的内存镜像
    • 轻量级fork
    • 子进程应该几乎立即调用exec
    • Copy on Write技术(需要写的时候再去复制)

进程控制-加载和执行

在这里插入图片描述
执行exec后,代码执行更换。
在这里插入图片描述
执行exec后,代码段发生变化,PCB信息也发生了变化。

  • exec调用允许一个进程“加载”一个不同的程序,所以新建的进程可以执行父进程的程序,也可以执行不同的程序(不调exec)。
  • 执行exec的时候,进程本身的堆、栈、代码段都会被覆盖。

进程控制-等待和终止

  • wait()系统调用是父进程用来等待子进程结束的,等子进程结束后,在操作系统中回收子进程PCB资源。配合子进程的exit完成对子进程所有资源的回收。
  • 当子进程调用exit,操作系统解锁父进程,通过exit返回的结果找到子进程,如果没有子进程直接返回。
  • 僵尸态:子进程执行完exit,父进程没有执行完wait,没有回收完资源的状态。就是进程调用了exit,但是pcb还没被回收的时候。
  • 如果父进程死亡,子进程的exit后资源的回收工作,交给root进程,就是所有进程的根进程。
    在这里插入图片描述
    如图,在子进程调用完exit以后,parent的wait操作还没执行完的时候,处于僵尸态。fork-》new。调用exec的时候,进程可能出于不同状态,运行状态,exec会去执行新代码,如果新代码需要从磁盘都到内存中,速度慢,这时候进程还可能出于阻塞状态。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值