热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

操作系统中阻塞与挂起状态的区别及sleep()函数的实现机制分析

在操作系统中,阻塞状态与挂起状态有着显著的区别。阻塞状态通常是指进程因等待某一事件(如I/O操作完成)而暂时停止执行,而挂起状态则是指进程被系统暂时移出内存,以释放资源或降低系统负载。此外,本文还深入分析了`sleep()`函数的实现机制,探讨了其在不同操作系统中的具体实现方式及其对进程调度的影响。通过这些分析,读者可以更好地理解操作系统如何管理进程的不同状态以及`sleep()`函数在其中的作用。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xpy870663266/article/details/78164506

博客原文



阻塞 VS 挂起

内核的sleep()函数是在挂起原语的基础上利用定时器实现的。

阻塞与挂起都是进程的状态,但他们有一些相似之处,也有一些区别,下面先对他们进行概述,再进行比较

阻塞:正在执行的进程由于发生某时间(如I/O请求、申请缓冲区失败等)暂时无法继续执行。此时引起进程调度,OS把处理机分配给另一个就绪进程,而让受阻进程处于暂停状态,一般将这种状态称为阻塞状态。

挂起:由于系统和用户的需要引入了挂起的操作,进程被挂起意味着该进程处于静止状态。如果进程正在执行,它将暂停执行,若原本处于就绪状态,则该进程此时暂不接受调度。

共同点:
1. 进程都暂停执行
2. 进程都释放CPU,即两个过程都会涉及上下文切换

不同点:
1. 对系统资源占用不同:虽然都释放了CPU,但阻塞的进程仍处于内存中,而挂起的进程通过“对换”技术被换出到外存(磁盘)中。
2. 发生时机不同:阻塞一般在进程等待资源(IO资源、信号量等)时发生;而挂起是由于用户和系统的需要,例如,终端用户需要暂停程序研究其执行情况或对其进行修改、OS为了提高内存利用率需要将暂时不能运行的进程(处于就绪或阻塞队列的进程)调出到磁盘
3. 恢复时机不同:阻塞要在等待的资源得到满足(例如获得了锁)后,才会进入就绪状态,等待被调度而执行;被挂起的进程由将其挂起的对象(如用户、系统)在时机符合时(调试结束、被调度进程选中需要重新执行)将其主动激活


sleep()

之所以将sleep一起讨论,是因为sleep是一个很常见的系统调用,在很多编程语言中,也有对应的函数,所以一起讨论可以明白sleep的过程与阻塞和挂起在底层的效果又有哪些区别。

sleep():进程、线程或任务(Linux中不区分进程与线程,都称为task)可以sleep,这会导致它们暂停执行一段时间,直到等待的时间结束才恢复执行或在这段时间内被中断。


OS中sleep()的实现

sleep()在OS中的实现的大概流程:
- 挂起进程(或线程)并修改其运行状态
- 用sleep()提供的参数来设置一个定时器。
- 当时间结束,定时器会触发,内核收到中断后修改进程(或线程)的运行状态。例如线程会被标志为就绪而进入就绪队列等待调度。

PS:关于第二点在这里要介绍一些背景知识:可变定时器(variable timer)一般在硬件层面是通过一个固定的时钟和计数器来实现的,每经过一个时钟周期将计数器递减,当计数器的值为0时产生中断。内核注册一个定时器后可以在一段时间后收到中断。

在Linux下,sleep()的实现流程大概如下:

#include
#include
#include
#include ///时钟编程 alarm()
void wakeUp()
{printf("please wakeup!!/n");
}int main(void)
{printf("you have 4 s sleep!/n");signal(SIGALRM,wakeUp);alarm(4);//将进程挂起pause();printf("good morning!/n");return EXIT_SUCCESS;}

  • 综上所述,内核的sleep()函数是在挂起原语的基础上利用定时器实现的。

    调用以下哪些方法可以使运行状态的线程进入阻塞状态?( )A.start( ),yield( ),sleep( ),join( )和wait( )B.start( ),yield( ),sleep( ),join( ),wait( )和stop( )C.yield( ),sleep( ),join( )和wait( )D.yield( ),sleep( ),join( ),wait( )和stop( )参考答案
    正确答案:C
    解析:运行状态的进程如果调用了yield( )方法、sleep( )方法、
    join( )方法或wait( )方法,或者申请对象锁未果、有更高优先级线程进入调度等,
    都可进入阻塞状态。阻塞状态的进程在获取到足够的资源后
    ,也可以转入到可运行状态。

    编程语言中sleep()的实现

    首先希望大家都了解用户线程和内核线程的概念。编程语言中的线程(用户线程)与内核线程是有着一定的映射关系的。下面以Java为例,解释一下用户线程与内核线程的映射关系,不过多涉及实现细节。想要了解用户线程和内核线程的关系模型,见 线程的三种实现模型

    Java线程API通常使用宿主系统的线程库来实现,也就是说,在Windows中,Java线程使用Win32 API来实现,而在Linux和Unix系统中使用Pthread。而且,JVM规范并没有指明Java线程如何被映射到底层的OS,而是让特定的JVM实现来决定。例如,在Window XP中采用一对一模型,而对于Solaris系统,刚开始采用多对一模型,从Solaris 9开始采用多对多模型。

    看到这里大家应该明白了,用户线程的sleep()正是利用内核提供的sleep()来实现的,没有内核的支持,用户线程也只能忙等直到规定的时间结束。

    参考资料:

    1. 《计算机操作系统(第四版)》,汤子瀛等著

    2. 《操作系统概念(第七版)》,Silberschatz等著,郑扣根译

    3. Quora 问答

    4. http://blog.csdn.net/freezgw1985/article/details/5631922

    5. https://en.wikipedia.org/wiki/Sleep_(system_call)

    6. http://man7.org/linux/man-pages/man3/sleep.3.html

    7. http://man7.org/linux/man-pages/man2/nanosleep.2.html

    8. http://man7.org/linux/man-pages/man2/alarm.2.html


推荐阅读
  • 本文深入探讨了IO复用技术的原理与实现,重点分析了其在解决C10K问题中的关键作用。IO复用技术允许单个进程同时管理多个IO对象,如文件、套接字和管道等,通过系统调用如`select`、`poll`和`epoll`,高效地处理大量并发连接。文章详细介绍了这些技术的工作机制,并结合实际案例,展示了它们在高并发场景下的应用效果。 ... [详细]
  • JVM参数设置与命令行工具详解
    JVM参数配置与命令行工具的深入解析旨在优化系统性能,通过合理设置JVM参数,确保在高吞吐量的前提下,有效减少垃圾回收(GC)的频率,进而降低系统停顿时间,提升服务的稳定性和响应速度。此外,本文还将详细介绍常用的JVM命令行工具,帮助开发者更好地监控和调优JVM运行状态。 ... [详细]
  • 在 Linux 系统中,`/proc` 目录实现了一种特殊的文件系统,称为 proc 文件系统。与传统的文件系统不同,proc 文件系统主要用于提供内核和进程信息的动态视图,通过文件和目录的形式呈现。这些信息包括系统状态、进程细节以及各种内核参数,为系统管理员和开发者提供了强大的诊断和调试工具。此外,proc 文件系统还支持实时读取和修改某些内核参数,增强了系统的灵活性和可配置性。 ... [详细]
  • DHCP三层交换机设置方式全局模式和接口模式设置方式和命令resetsave回车输入yreboot输入n输入y重启后就恢复默认设置了默认用户名密码adminAdmin@huawei ... [详细]
  • 掌握DSP必备的56个核心问题,我已经将其收藏以备不时之需! ... [详细]
  • 深入RTOS实践,面对原子操作提问竟感困惑
    在实时操作系统(RTOS)的实践中,尽管已经积累了丰富的经验,但在面对原子操作的具体问题时,仍感到困惑。本文将深入探讨RTOS中的原子操作机制,分析其在多任务环境下的重要性和实现方式,并结合实际案例解析常见的问题及解决方案,帮助读者更好地理解和应用这一关键技术。 ... [详细]
  • 深入解析 Unity URP/SRP 渲染管线:匠心打造的全面指南
    本文深入探讨了Unity中的URP、SRP和HDRP渲染管线,详细解析了它们之间的关系及各自的特点。首先介绍了SRP的基本概念及其在Unity渲染架构中的作用,随后重点阐述了URP和HDRP的设计理念与应用场景。文章还分析了SRP诞生的背景,解释了为何Unity需要引入这一灵活的渲染框架,以满足不同项目的需求。通过对比URP和HDRP,读者可以更好地理解如何选择合适的渲染管线,以优化项目的性能和视觉效果。 ... [详细]
  • python 对象锁_Python学习之进程和线程
    Python学习之进程和线程Python学习目录在Mac下使用Python3Python学习之数据类型Python学习之函数Python学习之高级特性Python学习之函数式编程P ... [详细]
  • 这是一份详细 & 清晰的计算机网络基础 学习指南
    前言计算机网络基础该是程序猿需掌握的知识,但往往会被忽略今天,我将献上一份详细&清晰的计算机网络基础学习指南,涵盖TCPUDP协议、Http协议、Socket等,希望你们会喜欢。目 ... [详细]
  • 在处理大规模并发请求时,传统的多线程或多进程模型往往无法有效解决性能瓶颈问题。尽管它们在处理小规模任务时能提升效率,但在高并发场景下,系统资源的过度消耗和上下文切换的开销会显著降低整体性能。相比之下,Python 的 `asyncio` 模块通过协程提供了一种轻量级且高效的并发解决方案。本文将深入解析 `asyncio` 模块的原理及其在实际应用中的优化技巧,帮助开发者更好地利用协程技术提升程序性能。 ... [详细]
  • 点云技术初探(三):PCL基础知识与学习路径指南本文首先介绍了点云库(PCL)的基本概念,PCL是一个在前人点云研究成果基础上发展而来的大型跨平台开源C++编程库,旨在为点云数据处理提供全面的支持。文章详细阐述了PCL的核心功能及其在三维数据处理、特征提取、分割与配准等方面的应用,并为初学者提供了系统的学习路径和资源推荐,帮助读者快速掌握PCL的使用方法。 ... [详细]
  • Linux多线程(2)
    线程的知识点太多,太重要,所以分成三部分进行总结学习线程安全多个线程并发同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作,并且没有锁保护的情况下,会出现该问题。 ... [详细]
  • github:https:github.comfroghuiyolandaIO模型和多线程模型实现多线程设计的几个考虑在我们的设计中,mainre ... [详细]
  • 编译lib手动编译cmake编译gtest测试程序断言和caseFixture使用gmock编译gmock测试程序参考GtestGithub使用gtest(gmock)方便我们编写 ... [详细]
  •  在使用PHP多年之后,我对PHP的优势和劣势已经非常清楚,与后起之秀Golang相比,两者已经不在一个重量级。 PHP更像是70kg级别的选手,脚本语言,极速开发,部署方便,性能 ... [详细]
author-avatar
秋日里的一抹阳光_797
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有