Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >进程冻结

进程冻结

作者头像
233333
发布于 2023-03-08 06:48:15
发布于 2023-03-08 06:48:15
1.4K00
代码可运行
举报
运行总次数:0
代码可运行

1 什么是进程冻结

进程冻结技术(freezing of tasks)是指在系统hibernate或者suspend的时候,将用户进程和部分内核线程置于“可控”的暂停状态。

为什么需要冻结技术

假设没有冻结技术,进程可以在任意可调度的点暂停,而且直到cpu_down才会暂停并迁移。这会给系统带来很多问题:

(1)有可能破坏文件系统。在系统创建hibernate image到cpu down之间,如果有进程还在修改文件系统的内容,这将会导致系统恢复之后无法完全恢复文件系统;

(2)有可能导致创建hibernation image失败。创建hibernation image需要足够的内存空间,但是在这期间如果还有进程在申请内存,就可能导致创建失败;

(3)有可能干扰设备的suspend和resume。在cpu down之前,device suspend期间,如果进程还在访问设备,尤其是访问竞争资源,就有可能引起设备suspend异常;

(4)有可能导致进程感知系统休眠。系统休眠的理想状态是所有任务对休眠过程无感知,睡醒之后全部自动恢复工作,但是有些进程,比如某个进程需要所有cpu online才能正常工作,如果进程不冻结,那么在休眠过程中将会工作异常。

3 代码实现框架

冻结的对象是内核中可以被调度执行的实体,包括用户进程、内核线程和work_queue。用户进程默认是可以被冻结的,借用信号处理机制实现;内核线程和work_queue默认是不能被冻结的,少数内核线程和work_queue在创建时指定了freezable标志,这些任务需要对freeze状态进行判断,当系统进入freezing时,主动暂停运行。

kernel threads可以通过调用kthread_freezable_should_stop来判断freezing状态,并主动调用__refrigerator进入冻结;work_queue通过判断max_active属性,如果max_active=0,则不能入队新的work,所有work延后执行。

标记系统freeze状态的有三个重要的全局变量:pm_freezing、system_freezing_cnt和pm_nosig_freezing,如果全为0,表示系统未进入冻结;system_freezing_cnt>0表示系统进入冻结,pm_freezing=true表示冻结用户进程,pm_nosig_freezing=true表示冻结内核线程和workqueue。它们会在freeze_processes和freeze_kernel_threads中置位,在thaw_processes和thaw_kernel_threads中清零。

fake_signal_wake_up函数巧妙的利用了信号处理机制,只设置任务的TIF_SIGPENDING位,但不传递任何信号,然后唤醒任务;这样任务在返回用户态时会进入信号处理流程,检查系统的freeze状态,并做相应处理。

任务主动调用try_to_freeze的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static inline bool try_to_freeze_unsafe(void)
{
    if (likely(!freezing(current))) //检查系统是否处于freezing状态
        return false;
    return __refrigerator(false); //主动进入冻结
}

static inline bool freezing(struct task_struct *p)
{
    if (likely(!atomic_read(&system_freezing_cnt))) //系统总体进入freezing
        return false;
    return freezing_slow_path(p);
}

bool freezing_slow_path(struct task_struct *p)
{
    if (p->flags & PF_NOFREEZE)  //当前进程是否允许冻结
        return false;

    if (pm_nosig_freezing || cgroup_freezing(p))  //系统冻结kernel threads
        return true;

    if (pm_freezing && !(p->flags & PF_KTHREAD)) //系统冻结用户进程
        return true;

    return false;
}

进入冻结状态直到恢复的主要函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
...
    for (;;) {
        set_current_state(TASK_UNINTERRUPTIBLE);  //设置进程为UNINTERRUPTIBLE状态

        spin_lock_irq(&freezer_lock);
        current->flags |= PF_FROZEN;  //设置已冻结状态
        if (!freezing(current) ||
            (check_kthr_stop && kthread_should_stop())) //判断系统是否还处于冻结
            current->flags &= ~PF_FROZEN;  //如果系统已解冻,则取消冻结状态
        spin_unlock_irq(&freezer_lock);

        if (!(current->flags & PF_FROZEN))  //如果已取消冻结,跳出循环,恢复执行
            break;
        was_frozen = true;
        schedule();
    }
......
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
深入理解Linux电源管理
程磊,某手机大厂系统开发工程师,阅码场荣誉总编辑,最大的爱好是钻研Linux内核基本原理。
Linux阅码场
2022/09/28
7.2K0
深入理解Linux电源管理
万字整理 | 深入理解工作队列
伟林,中年码农,从事过电信、手机、安全、芯片等行业,目前依旧从事Linux方向开发工作,个人爱好Linux相关知识分享,个人微博CSDN pwl999,欢迎大家关注! 1.1 worker_pool 1.1.1 normal worker_pool 1.1.2 unbound worker_pool 1.2 worker 1.2.1 worker处理work 1.2.2 worker_pool动态管理worker 1.2.3 cpu hotplug处理 1.3 workqueue 1.3.1 系统workq
刘盼
2022/08/26
1.9K0
万字整理 | 深入理解工作队列
workqueue
在之前的softirq中提到过,内核在中断的bottom half引入了softirq, tasklet, workqueue。 而softirq和tasklet只能用在中断上下文中,而且不可以睡眠。所以内核引入了workqueue,工作队列运行在进程上下文,同时可以睡眠。在以前版本的内核中workqueue的代码比较简单。在linux2.6.30代码量在1000行左右,而在linux3.18代码量在5000行左右。其中巨大的变化就是引入了Concurrency Managed Workqueue (cmwq)概念。不过本篇先学习以前版本的workqueue,因为它简单。在了解了简单版本的存在问题之后在学习cmwq就有更好的认识。
DragonKingZhu
2020/03/24
1.2K0
郭健: currency Managed Workqueue(CMWQ)概述
一种新的机制出现的原因往往是为了解决实际的问题,虽然linux kernel中已经提供了workqueue的机制,那么为何还要引入cmwq呢?也就是说:旧的workqueue机制存在什么样的问题?在新的cmwq又是如何解决这些问题的呢?它接口是如何呈现的呢(驱动工程师最关心这个了)?如何兼容旧的驱动呢?本文希望可以解开这些谜题。
Linux阅码场
2019/10/08
1.3K0
郭健: currency Managed Workqueue(CMWQ)概述
Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)【转】
Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在include/linux/sched.h文件中。
233333
2018/09/14
2.5K0
Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)【转】
Linux下2号进程的kthreadd--Linux进程的管理与调度(七)
内核初始化rest_init函数中,由进程 0 (swapper 进程)创建了两个process
233333
2018/09/14
2.5K0
深入理解Linux内核之内核线程(上)
在linux系统中, 我们接触最多的莫过于用户空间的任务,像用户线程或用户进程,因为他们太活跃了,也太耀眼了以至于我们感受不到内核线程的存在,但是内核线程却在背后默默地付出着,如内存回收,脏页回写,处理大量的软中断等,如果没有内核线程那么linux世界是那么的可怕!本文力求与完整介绍完内核线程的整个生命周期,如内核线程的创建、调度等等,当然本文还是主要从内存管理和进程调度两个维度来解析,且不会涉及到具体的内核线程如kswapd的实现,最后我们会以一个简单的内核模块来说明如何在驱动代码中来创建使用内核线程。
用户7244416
2021/08/06
2.6K0
Linux 进程管理
在内核层面,每个进程都是由task_struct 描述的,这个结构体非常大,可以粗略看下各主要内容:
一只小虾米
2023/03/09
10.3K0
Linux 进程管理
休眠与唤醒机制
当我们休眠时,如果想唤醒,则需要添加中断唤醒源,使得在休眠时,这些中断是设为开启的,当有中断来,则会退出唤醒,常见的中断源有按键,USB等。
开源519
2020/08/20
5.2K0
【Android休眠】之Android休眠机制
休眠,简而言之就是设备在不需要工作的时候把一些部件、外设关掉(掉电或让它进入低功耗模式)。
233333
2020/01/02
4.8K0
Linux唤醒抢占----Linux进程的管理与调度(二十三)
当在try_to_wake_up/wake_up_process和wake_up_new_task中唤醒进程时, 内核使用全局check_preempt_curr看看是否进程可以抢占当前进程可以抢占当前运行的进程. 请注意该过程不涉及核心调度器.
233333
2018/12/07
4.2K0
内核线程的创建和运行
通过 ps 命令可以看到红色方框标出的都是父进程为2号进程的内核线程,2号进程即蓝色方框标出的进程 kthreadd,1号进程是绿色方框标出的进程 init,它们的父进程号都是0。
刘盼
2021/07/05
1.9K2
内核线程的创建和运行
原来进程是这么创建的
大家好,我是程栩,一个专注于性能的大厂程序员,分享包括但不限于计算机体系结构、性能优化、云原生的知识。
程栩的性能优化笔记
2023/11/01
4400
原来进程是这么创建的
浅谈Linux dirty data配置
结合www.kernel.org给出的官方解释以及centos7代码的理解先对dirty相关内核参数做一个概述:
cdh
2020/05/25
4.1K0
Linux进程退出详解(do_exit)--Linux进程的管理与调度(十四)
exit是c语言的库函数,他最终调用_exit。在此之前,先清洗标准输出的缓存,调用用atexit注册的函数等, 在c语言的main函数中调用return就等价于调用exit。
233333
2018/10/09
6.5K0
Linux驱动实践:中断处理中的【工作队列】 workqueue 是什么鬼?
大家好,我是道哥,今天我为大伙儿解说的技术知识点是:【中断处理中的下半部分机制-工作队列】。
IOT物联网小镇
2021/12/28
2.1K0
Linux驱动实践:中断处理中的【工作队列】 workqueue 是什么鬼?
Linux电源管理-Suspend/Resume流程
根据上一节linux电源管理-概述可知,linux电源管理存在的几种方式,如何查看这几种方式,以及最后的如何睡眠唤醒等。
DragonKingZhu
2020/03/24
8.8K0
Linux电源管理-Suspend/Resume流程
Linux下进程的创建过程分析(_do_fork do_fork详解)--Linux进程的管理与调度(八)
Unix标准的复制进程的系统调用时fork(即分叉),但是Linux,BSD等操作系统并不止实现这一个,确切的说linux实现了三个,fork,vfork,clone(确切说vfork创造出来的是轻量级进程,也叫线程,是共享资源的进程)
233333
2018/10/09
2.8K0
Linux下进程的创建过程分析(_do_fork do_fork详解)--Linux进程的管理与调度(八)
Linux0号进程,1号进程,2号进程
本节我们将从linux启动的第一个进程说起,以及后面第一个进程是如何启动1号进程,然后启动2号进程。然后系统中所有的进程关系图做个简单的介绍
DragonKingZhu
2020/03/24
7.3K1
do_fork实现--下
昨天在do_fork实现–上中学习了do_fork创建的前半段,今天我们接着继续分析copy_Process函数
DragonKingZhu
2020/03/24
1.6K0
do_fork实现--下
相关推荐
深入理解Linux电源管理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档