V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
XGHeaven
V2EX  ›  Linux

对于操作系统来说,进程未响应的本质是什么?如何检测进程未响应?

  •  
  •   XGHeaven ·
    XGHeaven · 2018-05-31 10:50:07 +08:00 · 7582 次点击
    这是一个创建于 2393 天前的主题,其中的信息可能已经有所发展或是发生改变。

    感觉进程未响应的时候就像是死循环了一样,但是如果一个进程死循环的话,操作系统并没有认为他未响应。 那么什么情况下会被认为是未响应,以及未响应的本质是啥?未响应的时候是否还占用 CPU 资源?

    感觉一切有 UI 的都会出现未响应的情况,比如 Windows,macOS,Android。IOS 似乎没有见到过。 但是没有 UI 的,比如说 CentOS 几乎没有出现过进程未响应的情况。

    很好神奇这是为啥。

    22 条回复    2018-06-01 02:00:58 +08:00
    raysonx
        1
    raysonx  
       2018-05-31 10:57:13 +08:00   ❤️ 2
    以 Windows 来讲,每当用户操作窗口上的一个按钮或菜单,会产生一个事件( Event )。操作系统会把事件投递到应用程序的事件队列里。如果这个事件过了很久还没有被应用程序处理,那系统就会提示“未响应”。
    我不太了解其他系统下的机制,不过应该也差不多。
    应用程序未响应的原因很多,也许像你说的在占用 CPU,也可能是在等待 I/O 或者锁。
    raysonx
        2
    raysonx  
       2018-05-31 10:58:54 +08:00
    纠正一个名词,Windows 编程里面通常把这个事件叫做消息( Message )
    gam2046
        3
    gam2046  
       2018-05-31 11:00:31 +08:00
    个人理解是对于有限资源竞争过程中造成的死锁。

    吃饭需要两个筷子,结果 A 程序拿到了一根筷子,B 程序也拿到了一根筷子。A/B 都不愿意释放自己手中的筷子,互相等待对方释放资源(筷子),以便于自己继续运行,最终因为谁都不释放资源造成程序死锁

    同样吃饭需要两个筷子,A 程序功能拿到 2 个筷子,开始吃饭。此时 B 程序也要吃饭,发现没筷子了,系统告诉 B,让他等等,A 吃饭了,B 再去吃。但是 A 吃着吃着,出意外了(饭撒了一地,或者去上厕所去了),导致长时间没有释放资源(筷子)。但是 B 并不知道,于是傻傻的等待,用户就会认为 B 程序挂了。
    paparika
        4
    paparika  
       2018-05-31 12:17:58 +08:00
    android 有一个主线程,专门刷新 UI,如果你的程序阻塞主线程太久,就会弹出对话框提示
    wohenyingyu03
        5
    wohenyingyu03  
       2018-05-31 13:36:01 +08:00
    就是操作系统调用了你的程序等结果,你却迟迟不 return。命令行就不会未响应了。
    carlclone
        6
    carlclone  
       2018-05-31 13:41:05 +08:00 via Android
    我的理解是阻塞了或者死锁了,毕竟有的未响应能缓过来的
    zhjits
        7
    zhjits  
       2018-05-31 13:48:20 +08:00
    对操作系统来说就是事件处理程序没有在指定时间内完成。一般指的是 UI 主线程卡住导致 redraw 事件在数秒内无法完成。
    lastpass
        8
    lastpass  
       2018-05-31 13:56:22 +08:00 via Android   ❤️ 1
    我就说一个。plsql 天天未响应。💔
    Pyjamas
        9
    Pyjamas  
       2018-05-31 14:00:01 +08:00
    某个进程未响应,应该是指这个进程没有在指定时间内完成某个 task。
    我觉得流程大概是这样的
    1. 进程需要某个资源,发一条消息说我需要 xxx 资源,然后阻塞自己,把自己放到阻塞队列里,并设置一个 deadline
    2. 如果 deadline 已经过了,该进程还没拿到自己需要的资源,然后它应该会重新回到就绪队列里,执行 deadline 过期的处理代码,我觉得这段代码就是拿来显示[未响应]这些东西的

    阻塞队列里的进程应该也算是占用 CPU 的,因为 CPU 会定时 check 队列中的进程有没有过期。当然等你看到[未响应]三个字的时候,该进程应该已经回到就绪队列并执行 deadline 过期的代码了,就跟正常进程一样占用 CPU 时间的吧

    其实不知道对不对
    IvanLi127
        10
    IvanLi127  
       2018-05-31 14:37:48 +08:00 via Android
    不处理用户操作了,就给你挂个未响应的牌子
    redsonic
        11
    redsonic  
       2018-05-31 14:52:51 +08:00
    其实 UI 上提示的未响应和操作系统进程的状态没有关系。UI 提示的那个未响应来源自窗口管理器,依据交互的窗口(主线程?)是否响应键盘\鼠标\触屏来判断。内核无俗谓未响应状态,如果按常人理解,都是资源问题,参考 1、2,3 楼。
    vegito2002
        12
    vegito2002  
       2018-05-31 14:54:31 +08:00
    1L 讲的比较到位, 更深一层的愿意, 阻塞的可能性比较大.
    死锁的话, 一般除非是自己随便找的乱七八糟的程序, 否则发生的可能性应该不至于那么高: 实践当中碰到的"未响应"还是很频繁的.
    jedihy
        13
    jedihy  
       2018-05-31 15:01:30 +08:00 via iPhone
    UI 线程阻塞了,界面刷新不了,就这么简单
    nicevar
        14
    nicevar  
       2018-05-31 15:21:40 +08:00
    本质就是干其他的活去了,没空搭理你
    通常 GUI 程序有一个线程专门负责刷新 UI 的,为了能及时响应用户的操作,你就不能在这个线程里面干一些耗时的事,否则长时间没有给用户反馈,就是假死现象了
    CentOS 照样会出现的,任何系统都会出现,只要程序代码写得不合理
    verrickt
        15
    verrickt  
       2018-05-31 15:30:14 +08:00
    其实所有的 GUI 编程中,都存在类似 1L 所说的消息循环的概念。在 Win32 中,体现为
    ``` cpp
    while((bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    {
    if (bRet == -1)
    {
    // handle the error and possibly exit
    }
    else
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }
    ```

    GetMessage 由 Win32 的 Windows 的窗口子系统将外部事件转换为消息,发给获得焦点的进程。
    进程在得到消息后,使用 TranslateMessage 翻译消息,最后调用 Dispatch 将消息发送给对应的窗口(Windows 里一个进程可以创建许多窗口),在窗口中也有这样的消息循环,根据不同的消息执行不同的操作,这样就完成对外部事件的响应。
    认为一个进程如果在 5 秒钟之内没有处理消息,Windows 就认为它失去响应了

    > If a message has not been retrieved within 5 seconds, the DWM declares the window to be hung.

    https://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows
    https://msdn.microsoft.com/en-us/library/windows/desktop/dd744765(v=vs.85).aspx
    janus77
        16
    janus77  
       2018-05-31 15:32:00 +08:00
    简单来说就是用户的一个操作(比如点击 输入 触摸等任何一个操作)都会触发一段代码,如果这段代码跑挂了就会挂了。
    实际上是程序抛出异常。至于什么情况下这个异常严重到需要 crash,这就是 GUI 平台自己定义的了
    比如说手机 APP,因为渲染有帧数限制,等待超过一定时间,系统会强制 crash 掉
    比如桌面 exe,可能内存泄漏,可能死循环 死锁之类的,这也就是异常。但是要到了影响用户界面感知的情况下,才会被定义为「未响应」
    milllky
        17
    milllky  
       2018-05-31 16:31:55 +08:00
    程序未响应是 GUI 未响应,和死不死循环没有关系,操作系统也不知道,这是窗口管理器报的。
    打个比方,如果你用 LINUX 下的文本编辑器,需要有 GUI,如 GEDIT。打开一个超级大的文件,基本上就会出现“程序未响应”状态。但未响应并不是说,程序“死”了,只是因为程序在读取文件上花费了大量的时间,导致 CPU 没有让渡给 UI 刷新。更没有时间响应 UI 事件。如果你等的时间足够长,最后程序还是会恢复正常的。
    同样的,如果用 VIM 打开一个超大文件,也会使进程“卡住”。但你绝对看不到“程序未响应”的提示框,因为程序未响应是窗口管理器报的,没有 GUI 的程序自然不归窗口管理器管。
    milllky
        18
    milllky  
       2018-05-31 16:34:13 +08:00
    当然,也不排除一些程序确实因为实现原因,导致“未响应”
    liuxu
        19
    liuxu  
       2018-05-31 17:36:02 +08:00
    未响应只是表面上是程序和你没有正常交互,本质是由于某些原因导致原本可以正常响应外部输入的代码没能执行返回给你信息。
    未响应的程序会不会占用 CPU 在于它为什么会未响应,如果它是在等待 io,或被挂起,它就不占用 CPU。如果是因为执行繁忙导致未响应,那就会占用 CPU。
    最常见的非 UI 未响应也很常见,例如 ssh 连接网络不稳的服务器时,会因为网络等待导致未响应(输入一半命令卡死)。
    iwtbauh
        20
    iwtbauh  
       2018-05-31 18:49:39 +08:00 via Android
    楼上的全错了

    判断程序未响应的不是操作系统,操作系统根本不关心进程 UI 是否响应,而是一个用户程序,这类程序我们叫做“窗口管理器”
    dosmlp
        21
    dosmlp  
       2018-05-31 20:12:32 +08:00
    进程本来就是死循环,操作系统本质也是死循环,这个没法检测,只不过死循环如果把 ui 线程卡了会让用户感觉卡了一样
    tempdban
        22
    tempdban  
       2018-06-01 02:00:58 +08:00 via Android
    @dosmlp 哭了,我们架构的死循环检测就被你说没了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4144 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 83ms · UTC 05:29 · PVG 13:29 · LAX 21:29 · JFK 00:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.