如何知道系统是否刚从睡眠中醒来?

时间:2015-08-19 00:51:32

标签: c++ linux qt

我有一个在Linux上运行的Qt应用程序。

用户可以使用此应用程序将系统切换到mem sleep。

切换到mem睡眠是微不足道的,但是在用户空间中捕获唤醒事件不是。

我目前的解决方案是使用无限循环来捕获mem睡眠,这样当系统唤醒时,我的应用程序总是从可预测的点继续。

这是我的代码:

void MainWindow::memSleep()
{   
    int fd;
    fd = ::open("/sys/power/state", O_RDWR);// see update 1)
    QTime start=QTime::currentTime();
    write(fd,"mem",3); // command that triggers mem sleep
    while(1){
        usleep(5000);  // delay 5ms
        const QTime &end=QTime::currentTime();// check system clock
        if(start.msecsTo(end)>5*2){// if time gap is more than 10ms
            break;         // it means this thread was frozen for more
        }                  // than 5ms, indicating a wake up after a sleep
        start=end;
    }
    :: close(fd);          // the end of this function marks a wake up event
}

我将此方法描述为对this question的评论,并指出这不是一个好的解决方案,我同意。

问题:是否有可用于捕获唤醒事件的C API?

更新

1)什么是mem sleep?

  

https://www.kernel.org/doc/Documentation/power/states.txt

     

内核最多支持四种系统睡眠状态,尽管有三种   它们依赖于平台支持代码来实现低级细节   对于每个州。

     

状态由可以读取或写入的字符串表示    / sys / power / state 文件。这些字符串可能是“mem”,“待机”,“冻结”和   “disk”,其中最后一个始终表示休眠(Suspend-To-Disk)和   其余的含义取决于relative_sleep_states命令   行参数。

2)为什么我想赶上唤醒事件?

因为唤醒后需要重置某些硬件。系统唤醒后,硬件输入设备会产生错误的输入事件,因此必须在睡眠前(简单)禁用,并在唤醒后启用(此问题)。

这应该/可以由内核中的驱动程序处理,我可以访问或修复硬件,我的团队可以做但是没有时间去做。(为什么我,一个应用程序开发人员,需要在用户空间中修复它)

3)约束

这是嵌入式linux,内核2.6.37,arch:arm,march:omap2,distro:arago。它不像PC发行版那样方便添加包,也没有ACPI。内核2.6.37中的mem sleep支持并不成熟。

3 个答案:

答案 0 :(得分:1)

PCI设备的Linux设备驱动程序可以选择性地处理 suspend resume ,这可能是内核分别在系统暂停之前调用,并且在恢复之后从暂停。 PCI入口点位于struct pci_driver

您可以编写并安装一个简单的设备驱动程序,它只会感知 resume 操作,并为任何感兴趣的进程提供指示。最简单的可能是支持文件 read(),只要感测到 resume ,它就会返回一个字节。该程序只需要打开设备并让线程卡住读取单个字符。只要读取成功,系统就会恢复。

更重要的是,如果您的应用程序正在处理的设备具有设备驱动程序,则应更新驱动程序以对 resume 做出适当的反应。

答案 1 :(得分:0)

检查pm-utils哪些可以勾选/etc/pm/sleep.d 在钩子中,您可以向您的应用程序发送信号,例如通过杀戮或任何IPC。

您也可以让pm-utils暂停计算机,IMO与不同配置的兼容性更高。

编辑:

我不熟悉arago但pm-utils附带arch和ubuntu。 另请注意,在使用systemd的较新系统上,pm-utils已废弃,您应该将挂钩放在systemd上。

参考:systemd power events

答案 2 :(得分:0)

当系统从睡眠状态唤醒时,它应该生成ACPI事件,因此acpid应该让您检测并处理:通过/etc/acpi/events脚本,连接到/var/run/acpid.socket,或者使用acpi_listen。 (acpi_listen应该是一种简单的方法来测试它是否有用。)