欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 进程与线程:03 用户级线程

进程与线程:03 用户级线程

2025/4/22 10:10:24 来源:https://blog.csdn.net/weixin_44399845/article/details/147404329  浏览:    关键词:进程与线程:03 用户级线程

多进程与操作系统基础

上一个内容我们讲了多进程图像,强调多进程图像是操作系统最核心的图像。我们还通过Windows任务管理器,实际观察了操作系统里的进程。

  • 进程是操作系统的核心内容,管理好多个进程,就能管理好操作系统和CPU。
  • 上节课提到操作系统支持多进程图像的四个方面:
    • 组织方式:操作系统通过状态(如就绪态、阻塞态等)和队列(就绪态队列、阻塞队列等)来组织进程,涉及简单数据结构知识,此部分不做详细讲解。
    • 进程切换:多进程的切换非常关键,是重点内容。
    • 进程分离:在内存管理部分详细展开如何让进程之间地址空间不相互影响 。
    • 进程合作:在进程同步章节详细讲解操作系统如何让多个进程合作。

线程概念的引出

本次课重点探讨操作系统如何实现多个进程的切换。然而,讲进程切换却提到线程,这是因为线程的切换是进程切换的重要组成部分。
在这里插入图片描述

  • 多进程图像回顾:一个进程执行一系列指令,执行时可能因启动I/O(如磁盘操作)而执行不下去,需要切换。这里引发思考:能否只切换指令序列,而不切换资源(如映射表) ?
  • 线程概念形成:实际上,将资源和指令执行分开,只切换指令序列是可行的。这样切换速度更快,因为只需切换程序计数器(PC)和一些寄存器,无需切换映射表等资源。这种在一个资源下启动多个轻巧的指令序列,且可来回切换的方式,就是线程。线程保留了并发优点,同时避免了进程切换的高代价,其实质是映射表不变而PC指针变化。
    在这里插入图片描述

线程实用性的示例——网页浏览器

以网页浏览器为例说明线程的实用性。
在这里插入图片描述

  • 浏览器显示过程:打开斯坦福网站时,网页数据包含文本、图片等。若所有操作按顺序执行,先下载文本,再显示文本,最后显示图片,会出现一段时间屏幕空白,用户体验差。
  • 多线程实现方式:实际浏览器是通过多线程实现的:
    • 一个线程从服务器接收数据。
    • 一个线程显示文本。
    • 一个线程处理图片(如解压缩)。
    • 一个线程显示图片。
  • 线程共享资源优势:这些线程共享资源,比如接收的数据放在缓冲区,显示文本和图片的线程都从该缓冲区读取数据。若采用进程方式,因进程地址空间分离,数据传递会很麻烦,所以采用线程方式更合适。

线程切换实现示例

WebExplorer应用程序为例,展示线程切换的实现:
在这里插入图片描述

  • 程序基本结构:程序申请共享缓冲区,创建多个线程,每个线程执行一个函数。如GetData函数负责从网站下载数据(建立Socket连接,下载数据包并放入缓冲区),Show函数从缓冲区取出内容显示到显示器上。
  • 线程交替执行关键:核心是实现线程交替执行,这需要用到Yield函数。当GetData函数下载一部分数据后,调用Yield函数暂停当前线程执行,操作系统保存当前线程状态(如PC值、寄存器值等),然后从线程就绪队列中选取另一个线程(如Show线程),恢复其状态并让其执行。Show线程执行完相关操作后,也调用Yield函数,将执行权交回操作系统,操作系统再选取其他就绪线程执行,如此循环实现线程交替执行。

线程切换原理深入分析

  • CreateYieldCreate用于制造第一次切换时的状态,Yield是线程切换的核心。
    在这里插入图片描述
    在这里插入图片描述

    能切换就需清楚切换时的状态,比如Yield操作就是程序计数器(PC)从一个地址跳到另一个地址,如从100跳到300 。

  • 栈的变化:开始是一个栈,存在问题。后来发展为两个栈(对应两个线程),每个线程有自己的栈和线程控制块(TCB)。Yield切换时要先切换栈,例如Yield函数中先将当前栈指针(esp)保存到当前TCB中,然后将esp设置为下一个线程TCB中的esp值,实现栈的切换。
    在这里插入图片描述

  • ThreadCreate核心ThreadCreate函数的核心是创建两个TCB、两个栈,并将切换的PC值存于栈中。具体实现为申请TCB和栈的内存空间,将函数入口地址(如100)存入栈中,并将栈指针与TCB关联。
    在这里插入图片描述

综合示例与用户级线程特点

  • 综合示例:将所有相关函数组合在一起,WebExplorer函数(类似main函数)中创建线程(调用ThreadCreate),并通过while(1)Yield()不断进行线程切换;GetData函数在下载数据过程中调用Yield实现线程切换;ThreadCreate函数负责申请栈和TCB等操作;Yield函数负责保存现场、切换栈等操作。还提到编译相关命令,如gcc -o explorer get.c yield.c...gcc get.c... -lthread
    在这里插入图片描述

  • 用户级线程特点:强调Yield是用户程序,说明这是用户级线程。用户级线程切换控制权在用户程序手中,在用户态执行。若进程中的某个线程进入内核并阻塞(如GetData函数中连接URL发起请求后等待网卡I/O ,导致进程阻塞),其他线程仍可通过Yield进行切换执行,实现并发效果。但用户级线程也有局限性,如线程长时间执行不主动调用Yield,会导致其他线程无法执行,后续会讲解内核级线程来解决此类问题。
    在这里插入图片描述

**此处可插入对应图片,展示相关代码结构、线程切换流程、栈与TCB关系等内容,帮助理解** 。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词