Linux+Kernel+and+Android+休眠与唤醒实现与优化

合集下载

sleep与信号唤醒的问题内核对信号的处理方式udelay

sleep与信号唤醒的问题内核对信号的处理方式udelay

sleep与信号唤醒的问题内核对信号的处理方式udelay/charlesblc/p/6277848.html注意,sleep是会被信号唤醒的。

sleep函数:#includeunsigned int sleep(unsigned int seconds);此函数使调用进程被挂起,直到满足以下条件之一:1)已经过了seconds所指定的墙上时钟时间2)调用进程捕捉到一个信号并从信号处理程序返回注:由于其他系统活动,实际返回时间比所要求的会迟一些,像alarm一样。

sleep的返回值:1)在上述第一种情形中,返回值是02)当由于捕捉到某个信号sleep提前返回时,返回值是未睡够的时间(所要求的时间减去实际休眠时间)内核对信号的处理方式参考 /lina_acm/article/details/51510783内核给一个进程发送软中断信号的方法,是在进程所在的进程表项的信号域设置对应于该信号的位。

这里要补充的是,如果信号发送给一个正在睡眠的进程,那么要看该进程进入睡眠的优先级,如果进程睡眠在可被中断的优先级上,则唤醒进程;否则仅设置进程表中信号域相应的位,而不唤醒进程。

这一点比较重要,因为进程检查是否收到信号的时机是:一个进程在即将从内核态返回到用户态时;或者,在一个进程要进入或离开一个适当的低调度优先级睡眠状态时。

感觉,sleep函数,都是可被中断的吧。

不是很确定。

内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时。

所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。

进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。

处理信号有三种类型:进程接收到信号后退出;进程忽略该信号;进程收到信号后执行用户设定用系统调用signal的函数。

当进程接收到一个它忽略的信号时,进程丢弃该信号,就象没有收到该信号似的继续运行。

如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。

linux进程的睡眠和唤醒

linux进程的睡眠和唤醒

LKD中的讲解休眠(被阻塞)的进程处于一个特殊的不可执行状态。

这点非常重要,否则,没有这种特殊状态的话,调度程序就可能选出一个本不愿意被执行的进程,更糟糕的是,休眠就必须以轮询的方式实现了。

进程休眠有各种原因,但肯定都是为了等待一些事件。

事件可能是一段时间、从文件I/O读更多数据,或者是某个硬件事件。

一个进程还有可能在尝试获得一个已经占用的内核信号量时被迫进入休眠。

休眠的一个常见原因就是文件I/O --如进程对一个文件执行了read()操作,而这需要从磁盘里读取。

还有,进程在获取键盘输入的时候也需要等待。

无论哪种情况,内核的操作都相同:进程把它自己标记成休眠状态,把自己从可执行队列移出,放入等待队列,然后调用schedule()选择和执行一个其他进程。

唤醒的进程刚好相反:进程被设置为可执行状态,然后再从等待队列中移到可执行队列。

休眠有两种相关的进程状态:TASK_INTERRUPTIBLE andTASK_UNINTERRUPTIBLE。

它们的惟一区别是处于TASK_UNINTERRUPTIBLE状态的进程会忽略信号,而处于TASK_INTERRUPTIBLE状态的进程如果收到信号会被唤醒并处理信号(然后再次进入等待睡眠状态)。

两种状态的进程位于同一个等待队列上,等待某些事件,不能够运行。

休眠通过等待队列进行处理。

等待队列是由等待某些事件发生的进程组成的简单链表。

内核用wake_queue_head_t来代表等待队列。

等待队列可以通过DECLARE_W AITQUEUE()静态创建,也可以有init_waitqueue_head()动态创建。

进程把自己放入等待队列中并设置成不可执行状态。

等与等待队列相关的事件发生的时候,队列上的进程会被唤醒。

为了避免产生竞争条件,休眠和唤醒的实现不能有纰漏。

针对休眠,以前曾经使用过一些简单的接口。

但那些接口会带来竞争条件;有可能导致在判断条件变为真后进程却开始了休眠,那样就会使进程无限期地休眠下去。

android的休眠和唤醒

android的休眠和唤醒

android休眠与唤醒驱动流程分析标准linux休眠过程:●power management notifiers are executed with PM_SUSPEND_PREPARE●tasks are frozen●target system sleep state is announced to the platform-handling code●devices are suspended●platform-specific global suspend preparation methods are executed●non-boot CPUs are taken off-line●interrupts are disabled on the remaining (main) CPU●late suspend of devices is carried out (一般有一些BUS driver的动作进行)‏●platform-specific global methods are invoked to put the system to sleep标准linux唤醒过程:●t he main CPU is switched to the appropriate mode, if necessary●early resume of devices is carried out (一般有一些BUS driver的动作进行)‏●interrupts are enabled on the main CPU●non-boot CPUs are enabled●platform-specific global resume preparation methods are invoked●devices are woken up●tasks are thawed●power management notifiers are executed with PM_POST_SUSPEND用户可以通过sys文件系统控制系统进入休眠:查看系统支持的休眠方式:#cat /sys/power/state常见有standby(suspend to RAM)、mem(suspend to RAM)和disk(suspend to disk),只是standby耗电更多,返回到正常工作状态的时间更短。

linux 休眠流程

linux 休眠流程

Linux 休眠流程可以分为以下几个步骤:
1. 用户使用特定的命令将计算机系统进入休眠状态。

2. Linux内核根据用户输入的命令,调用硬件层接口。

3. 在硬件层,根据Linux中断请求,实现系统唤醒或者跳过该中断请求。

4. 休眠事件发生后,系统将进入低功耗状态,周围的硬件设备也会受到影响,如PCI设备电源会断掉。

5. 程序会进行保存,以节省内存,消耗更少电量。

6. 系统运行休眠事件后,内存状态将被保存。

7. Linux内核设定一定的定时器和应答函数,可以跳过或实际处理系统中断。

8. 处理完成后,系统将在一定时间后唤醒,继续运行休眠前的程序。

以上步骤完成后,Linux系统休眠流程就完成了。

android休眠唤醒流程2

android休眠唤醒流程2

android休眠唤醒流程2android系统⼀段时间没有操作,屏幕(screen)将从⾼亮(bright)变为暗淡(dim),如果再过段时间还是没有操作,屏幕(screen)从暗淡(dim)变为关闭(off).这时,系统将进⼊休眠.⽽对于某些需要保持系统唤醒甚⾄屏幕唤醒的应⽤(⽐如视频播放器和⾳乐播放器)来说,就必须要有⼀个机制,使得系统不进⼊休眠状态,设置保持屏幕亮屏状态.wakelock即⽤来实现以上⽬的先上⽹上偷来的⼀副图,说⼀下android系统的整个电源管理流程图接下来对每⼀个模块具体分析:powermanager对应⽂件是android/frameworks/base/core/java/android/os/PowerManager.java在Android中应⽤程序并不是直接同PowerManagerService交互的,⽽是通过PowerManager间接地与PowerManagerService打交道。

此⽂件定义了⼀个powermanager类.主要实现了1,wakelock的申请与释放public WakeLock newWakeLock(int flags, String tag)2,系统延时进⼊休眠public void userActivity(long when, boolean noChangeLights)3,系统强制休眠public void goToSleep(long time)4,屏幕亮度设置public void setBacklightBrightness(int brightness)5,屏幕状态查询public boolean isScreenOn()6,系统重启public void reboot(String reason)细节wakelock的申请与释放{@samplecode*PowerManager pm = (PowerManager)mContext.getSystemService(* Context.POWER_SERVICE);*PowerManager.WakeLock wl = pm.newWakeLock(* PowerManager.SCREEN_DIM_WAKE_LOCK* | PowerManager.ON_AFTER_RELEASE,* TAG);*wl.acquire();* // ...*wl.release();⼀共有如下⼏个flag来进⾏不⼀样的唤醒⽅式.可以根据需要设置Flag Value CPU Screen KeyboardPARTIAL_WAKE_LOCK On* can-off OffSCREEN_DIM_WAKE_LOCK On Dim OffPROXIMITY_SCREEN_OFF_WAKE_LOCK on 距离传感器时关闭 offSCREEN_BRIGHT_WAKE_LOCK On Bright OffFULL_WAKE_LOCK On Bright BrightACQUIRE_CAUSES_WAKEUP 确保wakelock,主要⽤于视频播放器ON_AFTER_RELEASE = 0x20000000 release后倒计时,关闭屏幕...userActivity的作⽤:使系统从其他状态进⼊全部打开状态,⽐如从暗屏(dim)切换到亮屏,并重置倒计时计数器(待续)。

android休眠与唤醒驱动流程分析

android休眠与唤醒驱动流程分析

android休眠与唤醒驱动流程分析标准linux休眠过程:●power management notifiers are executed with PM_SUSPEND_PREPARE●tasks are frozen●target system sleep state is announced to the platform-handling code●devices are suspended●platform-specific global suspend preparation methods are executed●non-boot CPUs are taken off-line●interrupts are disabled on the remaining (main) CPU●late suspend of devices is carried out (一般有一些BUS driver的动作进行)‏●platform-specific global methods are invoked to put the system to sleep标准linux唤醒过程:●t he main CPU is switched to the appropriate mode, if necessary●early resume of devices is carried out (一般有一些BUS driver的动作进行)‏●interrupts are enabled on the main CPU●non-boot CPUs are enabled●platform-specific global resume preparation methods are invoked●devices are woken up●tasks are thawed●power management notifiers are executed with PM_POST_SUSPEND用户可以通过sys文件系统控制系统进入休眠:查看系统支持的休眠方式:#cat /sys/power/state常见有standby(suspend to RAM)、mem(suspend to RAM)和disk(suspend to disk),只是standby耗电更多,返回到正常工作状态的时间更短。

Kernel休眠与唤醒综述

Kernel休眠与唤醒综述

Linux Kernel and Android 休眠与唤醒(中文版) (转)简介休眠/唤醒在嵌入式Linux中是非常重要的部分,嵌入式设备尽可能的进入休眠状态来延长电池的续航时间.这篇文章就详细介绍一下Linux中休眠/唤醒是如何工作的, 还有Android中如何把这部分和Linux的机制联系起来的.版本信息∙Linux Kernel: v2.6.28∙Android: v2.0对于休眠(suspend)的简单介绍在Linux中,休眠主要分三个主要的步骤:1.冻结用户态进程和内核态任务2.调用注册的设备的suspend的回调函数o顺序是按照注册顺序3.休眠核心设备和使CPU进入休眠态冻结进程是内核把进程列表中所有的进程的状态都设置为停止,并且保存下所有进程的上下文. 当这些进程被解冻的时候,他们是不知道自己被冻结过的,只是简单的继续执行.如何让Linux进入休眠呢?用户可以通过读写sys文件/sys /power/state 是实现控制系统进入休眠. 比如命令系统进入休眠. 也可以使用来得到内核支持哪几种休眠方式.Linux Suspend 的流程相关的文件:你可以通过访问Linux内核网站来得到源代码,下面是文件的路径: ∙linux_soruce/kernel/power/main.c∙linux_source/kernel/arch/xxx/mach-xxx/pm.c∙linux_source/driver/base/power/main.c接下来让我们详细的看一下Linux是怎么休眠/唤醒的. Let 's going to see how these happens.用户对于/sys/power/state 的读写会调用到 main.c中的state_store(), 用户可以写入 const char * const pm_state[] 中定义的字符串, 比如"mem", "standby".然后state_store()会调用enter_state(), 它首先会检查一些状态参数,然后同步文件系统. 下面是代码:准备, 冻结进程当进入到suspend_prepare()中以后, 它会给suspend分配一个虚拟终端来输出信息, 然后广播一个系统要进入suspend的Notify, 关闭掉用户态的helper 进程, 然后一次调用suspend_freeze_processes()冻结所有的进程, 这里会保存所有进程当前的状态, 也许有一些进程会拒绝进入冻结状态, 当有这样的进程存在的时候, 会导致冻结失败,此函数就会放弃冻结进程,并且解冻刚才冻结的所有进程.让外设进入休眠现在, 所有的进程(也包括workqueue/kthread) 都已经停止了, 内核态人物有可能在停止的时候握有一些信号量, 所以如果这时候在外设里面去解锁这个信号量有可能会发生死锁, 所以在外设的suspend()函数里面作lock/unlock 锁要非常小心,这里建议设计的时候就不要在suspend()里面等待锁. 而且因为suspend的时候,有一些Log是无法输出的,所以一旦出现问题,非常难调试.然后kernel在这里会尝试释放一些内存.最后会调用suspend_devices_and_enter()来把所有的外设休眠, 在这个函数中, 如果平台注册了suspend_pos(通常是在板级定义中定义和注册), 这里就会调用 suspend_ops->begin(), 然后driver/base/power/main.c 中的device_suspend()->dpm_suspend() 会被调用,他们会依次调用驱动的suspend() 回调来休眠掉所有的设备.当所有的设备休眠以后, suspend_ops->prepare()会被调用, 这个函数通常会作一些准备工作来让板机进入休眠. 接下来Linux,在多核的CPU中的非启动CPU会被关掉, 通过注释看到是避免这些其他的CPU造成race condion,接下来的以后只有一个CPU在运行了.suspend_ops 是板级的电源管理操作, 通常注册在文件arch/xxx/mach-xxx/pm.c 中.接下来, suspend_enter()会被调用, 这个函数会关闭arch irq, 调用device_power_down(), 它会调用suspend_late()函数, 这个函数是系统真正进入休眠最后调用的函数, 通常会在这个函数中作最后的检查. 如果检查没问题, 接下来休眠所有的系统设备和总线, 并且调用 suspend_pos->enter() 来使CPU进入省电状态. 这时候,就已经休眠了.代码的执行也就停在这里了.Resume如果在休眠中系统被中断或者其他事件唤醒, 接下来的代码就会开始执行, 这个唤醒的顺序是和休眠的循序相反的,所以系统设备和总线会首先唤醒,使能系统中断, 使能休眠时候停止掉的非启动CPU, 以及调用suspend_ops->finish(), 而且在suspend_devices_and_enter()函数中也会继续唤醒每个设备,使能虚拟终端, 最后调用 suspend_ops->end().在返回到enter_state()函数中的, 当 suspend_devices_and_enter() 返回以后, 外设已经唤醒了, 但是进程和任务都还是冻结状态, 这里会调用suspend_finish()来解冻这些进程和任务, 而且发出Notify来表示系统已经从suspend状态退出, 唤醒终端.到这里, 所有的休眠和唤醒就已经完毕了, 系统继续运行了.Android 休眠(suspend)在一个打过android补丁的内核中, state_store()函数会走另外一条路,会进入到request_suspend_state()中, 这个文件在earlysuspend.c中. 这些功能都是android系统加的, 后面会对earlysuspend和late resume 进行介绍.涉及到的文件:∙linux_source/kernel/power/main.c∙linux_source/kernel/power/earlysuspend.c∙linux_source/kernel/power/wakelock.c特性介绍Early SuspendEarly suspend 是android 引进的一种机制, 这种机制在上游备受争议,这里不做评论. 这个机制作用在关闭显示的时候, 在这个时候, 一些和显示有关的设备, 比如LCD背光, 比如重力感应器, 触摸屏, 这些设备都会关掉, 但是系统可能还是在运行状态(这时候还有wake lock)进行任务的处理, 例如在扫描SD卡上的文件等. 在嵌入式设备中, 背光是一个很大的电源消耗,所以android会加入这样一种机制.Late ResumeLate Resume 是和suspend 配套的一种机制, 是在内核唤醒完毕开始执行的. 主要就是唤醒在Early Suspend的时候休眠的设备.Wake LockWake Lock 在Android的电源管理系统中扮演一个核心的角色. Wake Lock是一种锁的机制, 只要有人拿着这个锁, 系统就无法进入休眠, 可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的, 超时的锁会在时间过去以后自动解锁. 如果没有锁了或者超时了, 内核就会启动休眠的那套机制来进入休眠.Android Suspend当用户写入mem 或者 standby到 /sys/power/state中的时候, state_store()会被调用, 然后Android会在这里调用 request_suspend_state() 而标准的Linux会在这里进入enter_state()这个函数. 如果请求的是休眠, 那么early_suspend这个workqueue就会被调用,并且进入early_suspend状态.Early Suspend在early_suspend()函数中, 首先会检查现在请求的状态还是否是suspend, 来防止suspend的请求会在这个时候取消掉(因为这个时候用户进程还在运行),如果需要退出, 就简单的退出了. 如果没有, 这个函数就会把early suspend中注册的一系列的回调都调用一次, 然后同步文件系统, 然后放弃掉main_wake_lock, 这个wake lock是一个没有超时的锁,如果这个锁不释放, 那么系统就无法进入休眠.Late Resume当所有的唤醒已经结束以后, 用户进程都已经开始运行了, 唤醒通常会是以下的几种原因:∙来电如果是来电, 那么Modem会通过发送命令给rild来让rild通知WindowManager 有来电响应,这样就会远程调用PowerManagerService来写"on" 到/sys/power/state 来执行late resume的设备, 比如点亮屏幕等.∙用户按键用户按键事件会送到WindowManager中, WindowManager会处理这些按键事件,按键分为几种情况, 如果案件不是唤醒键(能够唤醒系统的按键) 那么WindowManager会主动放弃wakeLock来使系统进入再次休眠, 如果按键是唤醒键,那么WindowManger就会调用PowerManagerService中的接口来执行 Late Resume.∙Late Resume 会依次唤醒前面调用了Early Suspend的设备.Wake Lock我们接下来看一看wake lock的机制是怎么运行和起作用的, 主要关注wakelock.c文件就可以了.wake lock 有加锁和解锁两种状态, 加锁的方式有两种, 一种是永久的锁住, 这样的锁除非显示的放开, 是不会解锁的, 所以这种锁的使用是非常小心的. 第二种是超时锁, 这种锁会锁定系统唤醒一段时间, 如果这个时间过去了, 这个锁会自动解除.锁有两种类型:1.WAKE_LOCK_SUSPEND 这种锁会防止系统进入睡眠2.WAKE_LOCK_IDLE 这种锁不会影响系统的休眠, 作用我不是很清楚.在wake lock中, 会有3个地方让系统直接开始suspend(), 分别是:1.在wake_unlock()中, 如果发现解锁以后没有任何其他的wake lock了,就开始休眠2.在定时器都到时间以后, 定时器的回调函数会查看是否有其他的wakelock, 如果没有, 就在这里让系统进入睡眠.3.在wake_lock() 中, 对一个wake lock加锁以后, 会再次检查一下有没有锁, 我想这里的检查是没有必要的, 更好的方法是使加锁的这个操作原子化, 而不是繁冗的检查. 而且这样的检查也有可能漏掉. Suspend当wake_lock 运行 suspend()以后, 在wakelock.c的suspend()函数会被调用,这个函数首先sync文件系统,然后调用pm_suspend(request_suspend_state),接下来pm_suspend()就会调用enter_state()来进入Linux的休眠流程..Android于标准Linux休眠的区别pm_suspend() 虽然会调用enter_state()来进入标准的Linux休眠流程,但是还是有一些区别:∙当进入冻结进程的时候, android首先会检查有没有wake lock,如果没有, 才会停止这些进程, 因为在开始suspend和冻结进程期间有可能有人申请了 wake lock,如果是这样, 冻结进程会被中断.∙在 suspend_late()中, 会最后检查一次有没有wake lock, 这有可能是某种快速申请wake lock,并且快速释放这个锁的进程导致的,如果有这种情况, 这里会返回错误, 整个suspend就会全部放弃.如果pm_suspend()成功了,LOG的输出可以通过在kernel cmd里面增加"no_console_suspend" 来看到suspend和resume过程中的log输出。

Linux内核与Android的关系

Linux内核与Android的关系

Linux内核与Android的关系对Android感兴趣的朋友都知道,Android系统是建立在Linux内核之上的。

那么Linux内核和Android什么关系?Linux内核是怎样引导起Android呢?本文进行简单的描述。

Android虽然建立在Linux内核之上,但是他对内核进行了一些扩展,增加了一些驱动。

比如Binder,loger等等驱动。

可以拿Android内核代码和其Baseline版本进行对比。

可以看到Android对Linux内核的所有扩展。

熟悉Linux启动的朋友知道,首先Linux引导完成之后,会启动用户态的init进程(pid 为0),这个进程在整个系统运行过程中起着非常重要的作用,如果你对init进程不了解请查相关资料。

init完成系统的初始化工作,然后进入shell,接收用户的输入。

Android启动也没有什么神秘的,就是用自己的init进程替换了Linux内核的init进程,完成自己初始化工作(设备,文件系统等等初始化)。

然后启动自己的虚拟机,程序等等的东西。

Android的init进程的代码位于system/core/init/init.c下面,可以去查看其源码,来了解Android启动详细流程。

Android启动流程的资料网上已经比较多,这里就不赘述了。

可以看到移植Android过程中,调试init非常重要。

因为所有和硬件平台相关的东西都这里初始化,所以init进程有可能需要移植或者配置。

其他的进程都是和硬件无关的,理论上不需要修改就应该能够运行起来。

经过上面的描述可以看出,Android的init进程起着一个承上启下的作用。

承上——自动由Linux内核调用;启下——初始化Android各种设备和资源,然后启动Android相关的进程,直到引导起整个Android系统。

46.Linux电源管理-休眠与唤醒

46.Linux电源管理-休眠与唤醒

46.Linux电源管理-休眠与唤醒1.休眠⽅式在内核中,休眠⽅式有很多种,可以通过下⾯命令查看# cat /sys/power/state//来得到内核⽀持哪⼏种休眠⽅式.常⽤的休眠⽅式有freeze,standby, mem, diskfreeze:冻结I/O设备,将它们置于低功耗状态,使处理器进⼊空闲状态,唤醒最快,耗电⽐其它standby, mem, disk⽅式⾼standby:除了冻结I/O设备外,还会暂停系统,唤醒较快,耗电⽐其它 mem, disk⽅式⾼mem: 将运⾏状态数据存到内存,并关闭外设,进⼊等待模式,唤醒较慢,耗电⽐disk⽅式⾼disk: 将运⾏状态数据存到硬盘,然后关机,唤醒最慢⽰例:# echo standby > /sys/power/state// 命令系统进⼊standby休眠.2.唤醒⽅式当我们休眠时,如果想唤醒,则需要添加中断唤醒源,使得在休眠时,这些中断是设为开启的,当有中断来,则会退出唤醒,常见的中断源有按键,USB等.3.以按键驱动为例(基于内核3.10.14)在内核中,有个input按键⼦系统"gpio-keys"(位于driver/input/keyboard/gpio.keys.c),该平台驱动platform_driver已经在内核中写好了(后⾯会简单分析)我们只需要在内核启动时,注册"gpio-keys"平台设备platform_device,即可实现⼀个按键驱动.3.1⾸先使板卡⽀持input按键⼦系统(基于mips君正X1000的板卡)查看Makefile,找到driver/input/keyboard/gpio.keys.c需要CONFIG_KEYBOARD_GPIO宏⽅式1-修改对应板卡的defconfig⽂件,添加宏:CONFIG_INPUT=y //⽀持input⼦系统(加载driver/input⽂件)CONFIG_INPUT_KEYBOARD=y //⽀持input->keyboards(加载driver/input/keyboard⽂件)CONFIG_KEYBOARD_GPIO=y //⽀持input->keyboards->gpio按键(加载gpio.keys.c)⽅式2-进⼊make menuconfig-> Device Drivers-> Input device support-> [*]Keyboards[*] GPIO Buttons3.2修改好后,接下来写my_button.c⽂件,来注册platform_device#include <linux/platform_device.h>#include <linux/gpio_keys.h>#include <linux/input.h>struct gpio_keys_button __attribute__((weak)) board_buttons[] = {{.gpio = GPIO_PB(31), //按键引脚.code = KEY_POWER, //⽤来定义按键产⽣事件时,要上传什么按键值.desc = "power key", //描述信息,不填的话会默认设置为"gpio-keys".wakeup =1, //设置为唤醒源. debounce_interval =10, //设置按键防抖动时间,也可以不设置.type = EV_KEY,.active_low = 1, //低电平有效},};static struct gpio_keys_platform_data board_button_data = {.buttons = board_buttons,.nbuttons = ARRAY_SIZE(board_buttons),};struct platform_device my_button_device = {.name = "gpio-keys",.id = -1,.num_resources = 0,.dev = {.platform_data = &board_button_data,}};static int __init button_base_init(void){platform_device_register(&my_button_device);return0;}arch_initcall(button_base_init);上⾯的arch_initcall()表⽰:会将button_base_init函数放在内核链接脚本.initcall3.init段中,然后在内核启动时,会去读链接脚本,然后找到button_base_init()函数,并执⾏它.通常,在内核中,platform 设备的初始化(注册)⽤arch_initcall()调⽤⽽驱动的注册则⽤module_init()调⽤,因为module_init()在arch_initcall()之后才调⽤因为在init.h中定义:#define pure_initcall(fn) __define_initcall(fn, 0)#define core_initcall(fn) __define_initcall(fn, 1)#define core_initcall_sync(fn) __define_initcall(fn, 1s)#define postcore_initcall(fn) __define_initcall(fn, 2)#define postcore_initcall_sync(fn) __define_initcall(fn, 2s)#define arch_initcall(fn) __define_initcall(fn, 3) // arch_initcall()优先级为3,⽐module_init()先执⾏#define arch_initcall_sync(fn) __define_initcall(fn, 3s)#define subsys_initcall(fn) __define_initcall(fn, 4)#define subsys_initcall_sync(fn) __define_initcall(fn, 4s)#define fs_initcall(fn) __define_initcall(fn, 5)#define fs_initcall_sync(fn) __define_initcall(fn, 5s)#define rootfs_initcall(fn) __define_initcall(fn, rootfs)#define device_initcall(fn) __define_initcall(fn, 6) //module_init()优先级为6#define device_initcall_sync(fn) __define_initcall(fn, 6s)#define late_initcall(fn) __define_initcall(fn, 7)#define late_initcall_sync(fn) __define_initcall(fn, 7s)... ...#define __initcall(fn) device_initcall(fn)#define module_init(x) __initcall(fn) //module_init 等于 device_initcall3.3然后将my_button.c⽂件添加到Makefile中编译内核后,便实现⼀个简单的按键唤醒休眠了.接下来开始分析platform_driver(位于driver/input/keyboard/gpio.keys.c),看看是如何注册按键和实现唤醒的.4.分析driver/input/keyboard/gpio.keys.c4.1该⽂件⾥有常⽤的函数有static int gpio_keys_probe(struct platform_device *pdev);设置按键和input_dev,注册input-key⼦系统static int gpio_keys_setup_key(struct platform_device *pdev,struct input_dev *input, struct gpio_button_data *bdata,const struct gpio_keys_button *button);设置GPIO,设置input结构体⽀持的按键值,设置中断,设置防抖动机制static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id);按键中断函数,如果是中断源,则通过pm_stay_awake()通知pm⼦系统唤醒,如果有防抖动,则延时并退出,否则通过schedule_work()来调⽤gpio_keys_gpio_work_func()⼀次static void gpio_keys_gpio_timer(unsigned long _data);定时器超时处理函数,⽤来实现防抖动,⾥⾯会通过schedule_work()来调⽤⼀次gpio_keys_gpio_work_func();static void gpio_keys_gpio_work_func(struct work_struct *work);处理gpio事件函数,⽤来上报input事件,并判断按键中断源,如果是的话,则调⽤pm_relax(),通知pm⼦系统唤醒⼯作结束void pm_wakeup_event(struct device *dev, unsigned int msec);通知pm(power manager), 唤醒休眠static int gpio_keys_suspend(struct device *dev);休眠函数,休眠之前会被调⽤static int gpio_keys_resume(struct device *dev);唤醒函数,唤醒之前被调⽤static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);SIMPLE_DEV_PM_OPS宏位于pm.h,它将会定义⼀个dev_pm_ops结构体,⽤来被pm⼦系统调⽤,实现休眠唤醒4.2 ⾸先来看probe函数如下图所⽰,probe函数为gpio_keys_probe()gpio_keys_probe()函数定义如下所⽰:static int gpio_keys_probe(struct platform_device *pdev){struct device *dev = &pdev->dev; //获取平台设备的.devconst struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); //获取my_button.c⽂件的board_button_data成员struct gpio_keys_drvdata *ddata; //按键驱动数据const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); //获取平台总线设备数据if (!pdata) {pdata = gpio_keys_get_devtree_pdata(dev);if (IS_ERR(pdata))return PTR_ERR(pdata);}ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +pdata->nbuttons * sizeof(struct gpio_button_data),GFP_KERNEL); //给平台设备数据分配空间input = input_allocate_device(); //分配input 按键⼦系统if (!ddata || !input) {dev_err(dev, "failed to allocate state\n");error = -ENOMEM;goto fail1;}ddata->pdata = pdata;ddata->input = input;mutex_init(&ddata->disable_lock);platform_set_drvdata(pdev, ddata);//将ddata保存到平台总线设备的私有数据。

你知道Linux进程的睡眠和唤醒操作?

你知道Linux进程的睡眠和唤醒操作?

你知道Linux进程的睡眠和唤醒操作?1 Linux进程的睡眠和唤醒在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在一个运行队列中,一个就绪进程的状态标志位为TASK_RUNNING。

一旦一个运行中的进程时间片用完,Linux 内核的调度器会剥夺这个进程对CPU的控制权,并且从运行队列中选择一个合适的进程投入运行。

当然,一个进程也可以主动释放CPU的控制权。

函数schedule()是一个调度函数,它可以被一个进程主动调用,从而调度其它进程占用CPU。

一旦这个主动放弃CPU的进程被重新调度占用CPU,那么它将从上次停止执行的位置开始执行,也就是说它将从调用schedule()的下一行代码处开始执行。

有时候,进程需要等待直到某个特定的事件发生,例如设备初始化完成、I/O 操作完成或定时器到时等。

在这种情况下,进程则必须从运行队列移出,加入到一个等待队列中,这个时候进程就进入了睡眠状态。

Linux 中的进程睡眠状态有两种:一种是可中断的睡眠状态,其状态标志位TASK_INTERRUPTIBLE;另一种是不可中断的睡眠状态,其状态标志位为TASK_UNINTERRUPTIBLE。

可中断的睡眠状态的进程会睡眠直到某个条件变为真,比如说产生一个硬件中断、释放进程正在等待的系统资源或是传递一个信号都可以是唤醒进程的条件。

不可中断睡眠状态与可中断睡眠状态类似,但是它有一个例外,那就是把信号传递到这种睡眠状态的进程不能改变它的状态,也就是说它不响应信号的唤醒。

不可中断睡眠状态一般较少用到,但在一些特定情况下这种状态还是很有用的,比如说:进程必须等待,不能被中断,直到某个特定的事件发生。

在现代的Linux操作系统中,进程一般都是用调用schedule()的方法进入睡眠状态的,下面的代码演示了如何让正在运行的进程进入睡眠状态。

sleeping_task = current;set_current_state(TASK_INTERRUPTIBLE);schedule();func1();/* Rest of the code ... */在第一个语句中,程序存储了一份进程结构指针sleeping_task,current 是一个宏,它指向正在执行的进程结构。

Android Linux的休眠和唤醒

Android Linux的休眠和唤醒

Android Linux的休眠和唤醒Android下有三种省电方式:Early_suspend::主要是屏幕省电需要。

进入early_suspend后,注册了early_suspend的外设进入休眠,大部分进程都还在运行,CPU处于正常工作状态。

外设可以通过register_early_suspend注册为early_suspend设备。

LPAUDION_MODE:系统进入early_suspend模式之后,通过has_audio_wake_lock判断是否进入LPAUDION_MODE模式,进入LPAUDION_MODE后,音乐正常播放,CPU进入省电模式。

Suspend:系统运行状态保存到内存,CPU进入省电模式,所有外设电源关闭,只有内存保持供电和工作。

跟休眠唤醒相关的文件:/kernel/power/main.c/kernel/power/earlysuspend.c/kernel/power/wakelock.c/kernel/power/suspend.c/drivers/base/power/main.c/arch/arm/plat-samsung/pm.c/arch/arm/mach-s5pv210/arch/arm/plat-s5p/sleep.s/arch/arm/mach-s5pv210/cpuidle.cAndroid linux休眠流程:休眠的入口在/kernel/power/main.c的state_store函数。

State_store函数通过power_attr(state)宏,在sysfs中定义了一个属性。

用户空间可以通过向state写入MEM,就可以使系统进入休眠状态。

也可以通过cat state查看支持哪些休眠方式在state_store函数中,调用request_suspend_state函数请求休眠。

在request_suspend_state 中,如果判断到系统不处于休眠状态,则调用early_suspend。

Linux(Ubuntu)休眠,挂起,待机,关机的命令详细介绍

Linux(Ubuntu)休眠,挂起,待机,关机的命令详细介绍

Linux(Ubuntu)休眠,挂起,待机,关机的命令详细介

这⾥对linux 的⼏个命令整理下,有:休眠,挂起,待机,关机等⼏个命令的区别及如何实现。

休眠是⼀种更加省电的模式,它将内存中的数据保存于硬盘中,所有设备都停⽌⼯作。

当再次使⽤时需按开关机键,机器将会恢复到您的执⾏休眠时的状态,⽽不⽤再次执⾏启动操作系统复杂的过程。

待机(挂起)是将当前处于运⾏状态的数据保存在内存中,机器只对内存供电,⽽硬盘、屏幕和CPU等部件则停⽌供电。

由于数据存储在速度快的内存中,因此进⼊等待状态和唤醒的速度⽐较快。

不过这些数据是保存在内存中,如果断电则会使数据丢失。

⽴刻关机:
sudo halt
sudo init 0
sudo shutdown -h now
sudo shutdown -h 0
定时/延时关机:
sudo shutdown -h 19:30
sudo shutdown -h +30 ##单位为分钟
重启:
sudo reboot
sudo init 6
sudo shutdown -r now
休眠:
sudo pm-hibernate
echo “disk” > /sys/power/state
sudo hibernate-disk
待机(挂起):
sudo pm-suspend
sudo pm-suspend-hybrid
echo “mem” > /sys/power/state
sudo hibernate-ram
感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

android的休眠和唤醒流程

android的休眠和唤醒流程

android的休眠和唤醒流程android休眠唤醒流程:power按键事件上报给android系统,最终由windownmanager接收到,当有按键事件时判断是否需要休眠后唤醒系统,然后调⽤powermanager 系统服务去写/sys/power/state节点.此节点的写函数⾥判断收到的内容,来执⾏android的休眠early_suspend/唤醒late_resume流程.android层:private int setScreenStateLocked(boolean on) 电源管理服务:frameworks/base/services/java/com/android/server/PowerManagerService.javaint err = Power.setScreenState(on);在⽂件frameworks/base/core/java/android/os/Power.java定义79 public static native int setScreenState(boolean on);具体实现在:frameworks/base/core/jni/android_os_Power.cppstatic int setScreenState(JNIEnv *env, jobject clazz, jboolean on);set_screen_state(on); 在⽂件hardware/libhardware_legacy/power/power.c中定义并实现write(g_fds[REQUEST_STATE], buf, len); 写/sys/power/state节点内核层:向节点写内容会调⽤kernel/power/main.c的写函数:static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n)request_suspend_state(state); 调⽤此函数: 具体实现在./kernel/power/earlysuspend.c中state: 为休眠则调⽤early_suspend_work android early_suspen⼯作队列为唤醒则调⽤late_resume_work android late_resume_work⼯作队列drivers/video/samsung/s3cfb_main.c中早已经注册屏幕开关register_early_suspend(&fbdev[i]->early_suspend);所以为休眠则调⽤early_suspend_work中的屏幕休眠函数:s3cfb_early_suspend()backlight_on()---->s3cfb_backlight_on() 在⽂件arch/arm/plat-s5p/dev-fimd-s5p.c中定义 npd->backlight_on = s3cfb_backlight_on;s3cfb_backlight_on中直接操作⽤来控制lcd的gpio关闭屏幕 arch/arm/mach-exynos/setup-fb-s5p.c为唤醒时调⽤late_resume_work中的屏幕唤醒函数:s3cfb_late_resume()backlight_off()---->s3cfb_backlight_off() 在⽂件arch/arm/plat-s5p/dev-fimd-s5p.c中定义 npd->backlight_off =s3cfb_backlight_off;s3cfb_backlight_off中直接操作⽤来控制lcd的gpio使能屏幕执⾏完所有的early_suspend后执⾏解锁main_wake_lock,以便休眠.wake_unlock(&main_wake_lock);mod_timer(&expire_timer, jiffies + has_lock); 在⽂件/kernel/power/wakelock.c中此函数将启⽤expire_timer定时器,定时器内容即expire_wake_locks340 static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);有四种⽅式可以引起休眠①在wake_unlock()中, 如果发现解锁以后没有任何其他的wake lock了, 就开始休眠②在定时器到时间以后, 定时器的回调函数会查看是否有其他的wake lock, 如果没有, 就在这⾥让系统进⼊睡眠③在wake_lock() 中, 对⼀个wake lock加锁以后, 会再次检查⼀下有没有锁, 刚加上锁,为什么要检查,有⽤吗④按power键,调⽤earlysuspend.使系统或应⽤程序释放锁.从⽽调⽤上述三个函数进⼊休眠if(has_lock ==0)queue_work(suspend_work_queue,&suspend_work); 由DECLARE_WORK(suspend_work, suspend);知道,队列中的内容即suspend 函数.suspend(); kernel/power/wakelock.cpm_suspend(requested_suspend_state);enter_state(state); kernel/power/suspend.csuspend_devices_and_enter(state);suspend_enter(state);suspend_ops->enter(state); -->调⽤平台相关的休眠函数,定义在中arch/arm/plat-samsung/pm.c:379:static const struct platform_suspend_ops s3c_pm_ops 即s3c_pm_enter s3c_pm_arch_stop_clocks() --> 休眠时执⾏的的最后⼀个函数.系统停在此处,等待中断或rtc等唤醒源唤醒.从此处开始唤醒流程enable_nonboot_cpus();suspend_test_start(); ---------->kernel已经被唤醒,当按键或中断来临后可以执⾏中断函数,上报唤醒事件.对于外部中断来说,上报power按键事件.pm_restore_gfp_mask(); kernel/power/suspend.center_state(state);pm_suspend(suspend_state_t state);suspend(); kernel/power/wakelock.c。

标准linux休眠和唤醒机制分析

标准linux休眠和唤醒机制分析

标准linux休眠和唤醒机制分析说明:1. Based on linux2.6.32, only for mem(SDR)2. 有兴趣请先参考阅读:电源管理方案APM和ACPI比较.docLinux系统的休眠与唤醒简介.doc3. 本文先研究标准linux的休眠与唤醒,android对这部分的增改在另一篇文章中讨论4. 基于手上的一个项目来讨论,这里只讨论共性的地方虽然linux支持三种省电模式:standby、suspend to ram、suspend to disk,但是在使用电池供电的手持设备上,几乎所有的方案都只支持STR模式(也有同时支持standby模式的),因为STD模式需要有交换分区的支持,但是像手机类的嵌入式设备,他们普遍使用nand 来存储数据和代码,而且其上使用的文件系统yaffs一般都没有划分交换分区,所以手机类设备上的linux都没有支持STD省电模式。

一、项目power相关的配置目前我手上的项目的linux电源管理方案配置如下,.config文件的截图,当然也可以通过make menuconfig使用图形化来配置:## CPU Power Management## CONFIG_CPU_IDLE is not set## Power management options#CONFIG_PM=y# CONFIG_PM_DEBUG is not setCONFIG_PM_SLEEP=yCONFIG_SUSPEND=yCONFIG_SUSPEND_FREEZER=yCONFIG_HAS_WAKELOCK=yCONFIG_HAS_EARLYSUSPEND=yCONFIG_WAKELOCK=yCONFIG_WAKELOCK_STAT=yCONFIG_USER_WAKELOCK=yCONFIG_EARLYSUSPEND=y# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set# CONFIG_CONSOLE_EARLYSUSPEND is not setCONFIG_FB_EARLYSUSPEND=y# CONFIG_APM_EMULATION is not set# CONFIG_PM_RUNTIME is not setCONFIG_ARCH_SUSPEND_POSSIBLE=yCONFIG_NET=y上面的配置对应下图中的下半部分图形化配置。

linux进程休眠原理

linux进程休眠原理

linux进程休眠原理Linux进程的休眠原理是指进程暂时挂起运行,等待一些条件满足后再继续执行。

这种机制在操作系统中非常重要,因为它可以提高系统的效率和性能。

在Linux系统中,进程可以通过调用系统调用sleep(或usleep(来主动进入休眠状态。

这些系统调用会暂停进程的执行一段指定的时间,使其进入睡眠状态。

当指定的时间到达时,进程会被重新唤醒,继续执行。

除了使用系统调用来实现主动进入休眠状态外,进程还可以被操作系统内核强制休眠。

比如,当进程等待一些事件发生时(比如等待用户输入),操作系统会将其挂起并置为休眠状态,直到事件发生后再唤醒它。

Linux进程的休眠原理是基于进程调度和时间片轮转算法的。

在Linux系统中,每个进程都有一个优先级和时间片。

当一个进程进入休眠状态时,操作系统会将其从可执行队列中移出,并选择一个新的进程来执行。

当休眠的进程等待的条件满足后,操作系统会将其重新加入可执行队列,继续执行。

进程的休眠状态是通过操作系统内核的调度器来实现的。

调度器负责根据调度策略和优先级,选择要执行的进程。

当一个进程进入休眠状态时,调度器会将其状态设置为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE,表示进程可以被中断或不可中断。

当一个进程被置为可中断的休眠状态时,它可以通过信号来被唤醒。

信号是操作系统向进程发送的一种通知,用于通知进程一些事件发生了。

当进程收到特定的信号后,它会从休眠状态被唤醒,继续执行。

当一个进程被置为不可中断的休眠状态时,它不能被任何信号唤醒。

这种状态通常用于进程等待一些特定资源,比如硬件设备。

只有当该设备就绪时,进程才能被唤醒,继续执行。

总结起来,Linux进程的休眠原理是通过调度器和进程状态的设置来实现的。

当一个进程进入休眠状态时,操作系统会将其从可执行队列中移出,选择一个新的进程执行。

当进程等待的条件满足后,它会被重新唤醒,继续执行。

休眠状态可以通过系统调用或操作系统内核强制实现,并可以被信号唤醒或不可中断地等待一些资源。

Androidlinux的休眠和唤醒

Androidlinux的休眠和唤醒

Androidlinux的休眠和唤醒写了很多内容,突然发布文章的时候保存失败。

郁闷凭借记忆只重写如下总结:1. Early suspend/ late resume 是android 添加的机制,用户关闭LCD, TS, Sensors等为了省电。

可称之为浅度休眠2. Linux的Suspend/resume 仍然有效,可称之为深度休眠3. echo mem > sys/power/state 会触发early suspend,echo on > sys/power/state 会触发late resume,cat sys/power/state 会显示当前支持的休眠状态,有mem, on, standby选项,但针对android 则只有mem, 同时无条件支持on4. LCD, TS, Sensors等设备会注册early suspend 和late resume 回调函数,用于early suspend/late resume时逐个执行。

5. User space 通过操作sys/power/wake_lock, sys/power/wake_unlock 可以向kernel申请一个wake lock;cat sys/power/wake_lock 或wake_unlock 只是显示User Space 申请的wake lock, kernel 申请的wake lock显示不出来6. cat proc/wakelocks 可以显示所有的wake lock的信息7. Early suspend/Late resume中有一个关键wake lock是main_wake_lock, 执行early suspend后会unlock main_wake_lock;执行late resume之前会lock main_wake_lock.8. 当任何一个wake lock被unlock时,会检测是否有其他wake lock处于locked状态?如果没有则系统进入linux 常规suspend9. 一般而言android系统是否休眠,是由user space发起的,而kernel space 是不能主动进入休眠的;当android系统需要进入休眠时,user space 执行echo mem > sys/power/state;强迫kernel 进入early suspend状态,如果还没有任何wake lock被locked,则进入linux 常规suspend.10. 如果android系统没有进入深度休眠,则user space发起echo on> sys/power/state, 则系统马上执行late resume, 唤醒LCD,TS,sensor等;如果已经进入深度休眠,则另外处理11. kernel会依次同步文件系统,执行各设备注册的suspend, 执行system core 的suspend disble bus和irq等,然后进入深度休眠后会在suspend_enter@kernel/kernel/power/suspend.c中的 suspend_ops->enter(state) 系统挂起,直到有硬件的操作唤醒;一旦被唤醒则依次执行system core resume, device resume 等,最后还会执行late resume.12. User space 向kernel申请wake lock时, 写入sys/power/wake_lock 的buf格式为<wakelock名称> [延时的纳秒数];但是User space 没有这么使用,android在java层自己实现了计数wake lock和记次wake lock.13. Early suspend/late resume 针对LCD,TS等设备来说,所起的作用与suspend/resume是一样的。

Linux休眠原理与实现

Linux休眠原理与实现

Linux休眠原理与实现Linux 休眠原理与实现 (2010-03-05 17:04)1.介绍Linux 休眠提供了一种类似于Windows 的休眠方式,使用户能够通过休眠操作,保存系统当前的内存数据到硬盘,即s w a p 分区中。

当计算机重新启动后,系统重新装载保存的内存数据,包括进程数据,寄存器数值等,并恢复到关机前的状态。

由于不需要重新装载文档,应用程序也不用重新打开,因此休眠启动方式要比正常的启动过程快得多。

2.Linux 休眠原理要实现操作系统的休眠,首先要理解linux 的内存管理机制。

标准L i n u x 的分页是三级页表结构:页目录、中间页目录和页。

i 3 8 6 采用的是两级页表结构:页目录和页,不支持中间页目录。

4 G 的线性地址空间,只有一个页目录,它最多有1024 个目录项,每个目录项又含有1024 个页面项,每个页面有4 K 字节。

分页机制通过把线性地址空间中的页,重新定位到物理地址空间来进行管理,因为每个页面的整个4K 字节作为一个单位进行映射,并且每个页面都对齐4K 字节的边界,因此,线性地址的低12 位经过分页机制直接地作为物理地址的低1 2 位使用。

下图所示是x86 下线性地址映射为物理地址的过程:休眠过程可以分为两个阶段, 一是SUSPEND 阶段, 二是R E S U M E 阶段, R E S U M E 过程是S U S P E N D 的逆过程。

S U S P E N D 阶段保存进程数据到硬盘中, 并关机;RESUME 阶段, 从硬盘中读取保存的进程数据, 并恢复到关机前的原始状态。

休眠需要解决的问题中,最重要的部分是内存数据的保存和如何恢复保存的内存数据。

我们可以很容易获取内存页面数据,SUSPEND 的过程中,主要任务就是要保存这些需要保存的页面,但是,作为存储页面地址的页表也需要保存下来,因为页表仅仅是一个中间转换作用的链表, 所以,可以在S U S P E N D 的过程中, 临时建立, 然后将内存页面地址记录在页表中。

【Android休眠】之Android休眠机制

【Android休眠】之Android休眠机制

【Android休眠】之Android休眠机制一、休眠概述休眠,简而言之就是设备在不需要工作的时候把一些部件、外设关掉(掉电或让它进入低功耗模式)。

为什么要休眠呢?一言以蔽之:省电。

休眠分主动休眠和被动休眠。

主动休眠:比如我电脑不用了,就通过设置让系统进入休眠模式;被动休眠:系统检测到自己闲的慌,为了节约故,自己就休眠去了。

废话不叙。

二、Android休眠休眠是内核的核心工作,而Android是基于Linux内核的,所以Android休眠和内核有着千丝万缕的联系;由于Android的特殊应用场景:移动设备,所以Android休眠和内核又有着特别的需求。

1、联系:Android设备停止使用,系统没有什么事情可做,进入休眠状态的功能最终是由内核去实现的;每一类硬件都有自己的驱动,具体的驱动决定怎么进入休眠以及处于何种层次的休眠。

比如:对于platform_device,就按照platform_driver定义的规则,在suspend 调用的时候,去做上面提到的事情:struct platform_driver {int (*probe)(struct platform_device *);int (*remove)(struct platform_device *);void (*shutdown)(struct platform_device *);int (*suspend)(struct platform_device *, pm_message_t state);int (*resume)(struct platform_device *);struct device_driver driver;const struct platform_device_id *id_table;};2、Android的特别需求:比如对于自己的电脑,不用让它休眠好了;但是对于我们形影不离的手机,在休眠的时候还要睁一只眼:来电了要通知你,QQ啊微信啊什么的由信息了也要通知你,所以Android在Linux内核休眠机制之上,提出了“Opportunistic Suspend”。

linux 睡眠函数

linux 睡眠函数

linux 睡眠函数
Linux睡眠函数是操作系统提供的一种机制,可以让系统进入低功耗状态,从而节省能源和延长电池续航时间。

在 Linux 系统中,有多种睡眠模式可供选择,如 Suspend、Hibernate 等。

Suspend 模式是一种较为常见的睡眠模式,它会将所有正在运行的程序挂起,并将系统进入睡眠状态。

在这种模式下,系统的内存和CPU 都会被关闭,但是 RAM 中的数据仍然会被保存。

当用户再次唤醒系统时,系统会从 RAM 中恢复数据,并重新运行之前挂起的程序。

Hibernate 模式是一种更加节能的睡眠模式,它会将 RAM 中的数据保存到硬盘上,并将系统完全关闭。

当用户再次启动系统时,系统会从硬盘上读取之前保存的数据,并恢复上次的状态。

除了 Suspend 和 Hibernate 模式,还有一些较为特殊的睡眠模式,如 Standby、Deep Sleep 等。

这些模式都有各自的特点和适用场景,用户可以根据需要灵活选择。

总的来说,睡眠功能是 Linux 系统中非常重要的一个功能,可以帮助用户节省能源,延长电池续航时间,提高系统性能和稳定性。

因此,学习和了解 Linux 睡眠函数是非常有益的。

- 1 -。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux Kernel and Android 休眠与唤醒(中文版)四月 18th, 2010 0 Comments/1664 hitsTable of Contents∙简介∙国际化∙版本信息∙对于休眠(suspend)的简单介绍∙Linux Suspend 的流程o相关的文件:o准备, 冻结进程o让外设进入休眠o Resume∙Android 休眠(suspend)o涉及到的文件:o特性介绍▪Early Suspend▪Late Resume▪Wake Locko Android Suspendo Early Suspendo Late Resumeo Wake Locko Suspendo Android于标准Linux休眠的区别简介休眠/唤醒在嵌入式Linux中是非常重要的部分,嵌入式设备尽可能的进入休眠状态来延长电池的续航时间.这篇文章就详细介绍一下Linux中休眠/唤醒是如何工作的, 还有Android中如何把这部分和Linux的机制联系起来的.国际化∙English Version: link∙中文版: link作者: zhangjiejing <kzjeef#> Date: 2010-04-07,版本信息∙Linux Kernel: v2.6.28∙Android: v2.0对于休眠(suspend)的简单介绍在Linux中,休眠主要分三个主要的步骤:1.冻结用户态进程和内核态任务2.调用注册的设备的suspend的回调函数o顺序是按照注册顺序3.休眠核心设备和使CPU进入休眠态冻结进程是内核把进程列表中所有的进程的状态都设置为停止,并且保存下所有进程的上下文. 当这些进程被解冻的时候,他们是不知道自己被冻结过的,只是简单的继续执行.如何让Linux进入休眠呢?用户可以通过读写sys文件/sys /power/state 是实现控制系统进入休眠. 比如命令系统进入休眠. 也可以使用来得到内核支持哪几种休眠方式.Linux Suspend 的流程相关的文件:你可以通过访问Linux内核网站来得到源代码,下面是文件的路径: ∙linux_soruce/kernel/power/main.c∙linux_source/kernel/arch/xxx/mach-xxx/pm.c∙linux_source/driver/base/power/main.c接下来让我们详细的看一下Linux是怎么休眠/唤醒的. Let 's going to see how these happens.用户对于/sys/power/state 的读写会调用到 main.c中的state_store(), 用户可以写入 const char * const pm_state[] 中定义的字符串, 比如"mem", "standby".然后state_store()会调用enter_state(), 它首先会检查一些状态参数,然后同步文件系统. 下面是代码:准备, 冻结进程当进入到suspend_prepare()中以后, 它会给suspend分配一个虚拟终端来输出信息, 然后广播一个系统要进入suspend的Notify, 关闭掉用户态的helper 进程, 然后一次调用suspend_freeze_processes()冻结所有的进程, 这里会保存所有进程当前的状态, 也许有一些进程会拒绝进入冻结状态, 当有这样的进程存在的时候, 会导致冻结失败,此函数就会放弃冻结进程,并且解冻刚才冻结的所有进程.让外设进入休眠现在, 所有的进程(也包括workqueue/kthread) 都已经停止了, 内核态人物有可能在停止的时候握有一些信号量, 所以如果这时候在外设里面去解锁这个信号量有可能会发生死锁, 所以在外设的suspend()函数里面作lock/unlock锁要非常小心,这里建议设计的时候就不要在suspend()里面等待锁. 而且因为suspend的时候,有一些Log是无法输出的,所以一旦出现问题,非常难调试.然后kernel在这里会尝试释放一些内存.最后会调用suspend_devices_and_enter()来把所有的外设休眠, 在这个函数中, 如果平台注册了suspend_pos(通常是在板级定义中定义和注册), 这里就会调用 suspend_ops->begin(), 然后driver/base/power/main.c 中的device_suspend()->dpm_suspend() 会被调用,他们会依次调用驱动的suspend() 回调来休眠掉所有的设备.当所有的设备休眠以后, suspend_ops->prepare()会被调用, 这个函数通常会作一些准备工作来让板机进入休眠. 接下来Linux,在多核的CPU中的非启动CPU会被关掉, 通过注释看到是避免这些其他的CPU造成race condion,接下来的以后只有一个CPU在运行了.suspend_ops 是板级的电源管理操作, 通常注册在文件arch/xxx/mach-xxx/pm.c 中.接下来, suspend_enter()会被调用, 这个函数会关闭arch irq, 调用device_power_down(), 它会调用suspend_late()函数, 这个函数是系统真正进入休眠最后调用的函数, 通常会在这个函数中作最后的检查. 如果检查没问题, 接下来休眠所有的系统设备和总线, 并且调用 suspend_pos->enter() 来使CPU进入省电状态. 这时候,就已经休眠了.代码的执行也就停在这里了.Resume如果在休眠中系统被中断或者其他事件唤醒, 接下来的代码就会开始执行, 这个唤醒的顺序是和休眠的循序相反的,所以系统设备和总线会首先唤醒,使能系统中断, 使能休眠时候停止掉的非启动CPU, 以及调用suspend_ops->finish(), 而且在suspend_devices_and_enter()函数中也会继续唤醒每个设备,使能虚拟终端, 最后调用 suspend_ops->end().在返回到enter_state()函数中的, 当 suspend_devices_and_enter() 返回以后, 外设已经唤醒了, 但是进程和任务都还是冻结状态, 这里会调用suspend_finish()来解冻这些进程和任务, 而且发出Notify来表示系统已经从suspend状态退出, 唤醒终端.到这里, 所有的休眠和唤醒就已经完毕了, 系统继续运行了.Android 休眠(suspend)在一个打过android补丁的内核中, state_store()函数会走另外一条路,会进入到request_suspend_state()中, 这个文件在earlysuspend.c中. 这些功能都是android系统加的, 后面会对earlysuspend和late resume 进行介绍.涉及到的文件:∙linux_source/kernel/power/main.c∙linux_source/kernel/power/earlysuspend.c∙linux_source/kernel/power/wakelock.c特性介绍Early SuspendEarly suspend 是android 引进的一种机制, 这种机制在上游备受争议,这里不做评论. 这个机制作用在关闭显示的时候, 在这个时候, 一些和显示有关的设备, 比如LCD背光, 比如重力感应器, 触摸屏, 这些设备都会关掉, 但是系统可能还是在运行状态(这时候还有wake lock)进行任务的处理, 例如在扫描SD卡上的文件等. 在嵌入式设备中, 背光是一个很大的电源消耗,所以android会加入这样一种机制.Late ResumeLate Resume 是和suspend 配套的一种机制, 是在内核唤醒完毕开始执行的. 主要就是唤醒在Early Suspend的时候休眠的设备.Wake LockWake Lock 在Android的电源管理系统中扮演一个核心的角色. Wake Lock是一种锁的机制, 只要有人拿着这个锁, 系统就无法进入休眠, 可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的, 超时的锁会在时间过去以后自动解锁. 如果没有锁了或者超时了, 内核就会启动休眠的那套机制来进入休眠.Android Suspend当用户写入mem 或者 standby到 /sys/power/state中的时候, state_store()会被调用, 然后Android会在这里调用 request_suspend_state() 而标准的Linux会在这里进入enter_state()这个函数. 如果请求的是休眠, 那么early_suspend这个workqueue就会被调用,并且进入early_suspend状态.Early Suspend在early_suspend()函数中, 首先会检查现在请求的状态还是否是suspend, 来防止suspend的请求会在这个时候取消掉(因为这个时候用户进程还在运行),如果需要退出, 就简单的退出了. 如果没有, 这个函数就会把early suspend中注册的一系列的回调都调用一次, 然后同步文件系统, 然后放弃掉main_wake_lock, 这个wake lock是一个没有超时的锁,如果这个锁不释放, 那么系统就无法进入休眠.Late Resume当所有的唤醒已经结束以后, 用户进程都已经开始运行了, 唤醒通常会是以下的几种原因:∙来电如果是来电, 那么Modem会通过发送命令给rild来让rild通知WindowManager 有来电响应,这样就会远程调用PowerManagerService来写"on" 到/sys/power/state 来执行late resume的设备, 比如点亮屏幕等.∙用户按键用户按键事件会送到WindowManager中, WindowManager会处理这些按键事件,按键分为几种情况, 如果案件不是唤醒键(能够唤醒系统的按键) 那么WindowManager会主动放弃wakeLock来使系统进入再次休眠, 如果按键是唤醒键,那么WindowManger就会调用PowerManagerService中的接口来执行 Late Resume.∙Late Resume 会依次唤醒前面调用了Early Suspend的设备.Wake Lock我们接下来看一看wake lock的机制是怎么运行和起作用的, 主要关注wakelock.c文件就可以了.wake lock 有加锁和解锁两种状态, 加锁的方式有两种, 一种是永久的锁住, 这样的锁除非显示的放开, 是不会解锁的, 所以这种锁的使用是非常小心的. 第二种是超时锁, 这种锁会锁定系统唤醒一段时间, 如果这个时间过去了, 这个锁会自动解除.锁有两种类型:1.WAKE_LOCK_SUSPEND 这种锁会防止系统进入睡眠2.WAKE_LOCK_IDLE 这种锁不会影响系统的休眠, 作用我不是很清楚.在wake lock中, 会有3个地方让系统直接开始suspend(), 分别是:1.在wake_unlock()中, 如果发现解锁以后没有任何其他的wake lock了,就开始休眠2.在定时器都到时间以后, 定时器的回调函数会查看是否有其他的wakelock, 如果没有, 就在这里让系统进入睡眠.3.在wake_lock() 中, 对一个wake lock加锁以后, 会再次检查一下有没有锁, 我想这里的检查是没有必要的, 更好的方法是使加锁的这个操作原子化, 而不是繁冗的检查. 而且这样的检查也有可能漏掉. Suspend当wake_lock 运行 suspend()以后, 在wakelock.c的suspend()函数会被调用,这个函数首先sync文件系统,然后调用pm_suspend(request_suspend_state),接下来pm_suspend()就会调用enter_state()来进入Linux的休眠流程..Android于标准Linux休眠的区别pm_suspend() 虽然会调用enter_state()来进入标准的Linux休眠流程,但是还是有一些区别:∙当进入冻结进程的时候, android首先会检查有没有wake lock,如果没有, 才会停止这些进程, 因为在开始suspend和冻结进程期间有可能有人申请了 wake lock,如果是这样, 冻结进程会被中断.∙在suspend_late()中, 会最后检查一次有没有wake lock, 这有可能是某种快速申请wake lock,并且快速释放这个锁的进程导致的,如果有这种情况, 这里会返回错误, 整个suspend就会全部放弃.如果pm_suspend()成功了,LOG的输出可以通过在kernel cmd里面增加 "no_console_suspend" 来看到suspend和resume过程中的log输出。

相关文档
最新文档