Ubuntu 拦截并监听 power button 的关机消息
system:ubuntu 18.04
platform:rockchip 3399
board:NanoPi M4
前言
物理上的电源按键短按之后,系统直接硬关机了,导致应用程序无法保护现场,就直接宕机了,查阅了大量资料,发现通过使用acpi可以禁止这个关机消息上传,但是看完acpi就放弃了这个想法,至少我在arm平台上没有具体成功实现这个消息的拦截,不然通过这个方式应该很便利,至少在intel上问题不大。
解决方法
google上搜索了很久,加上实践测试,终于找到了解决方案,具体如下所示;
Instead, adding a single line to
/etc/systemd/logind.confwas enough to do the trick:
#HandlePowerKey=poweroff
HandlePowerKey=suspend
Now, pressing the power button causes instant suspend.
修改/etc/systemd/logind.conf文件,找到HandlePowerKey,并且可以使用下面几个参数:
suspend系统会被挂起,如果我的设备终端有屏幕,而且装了相应的桌面,还会进入锁屏界面;ignore电源按键的消息会被忽略,即我按下按键之后什么事情都没有发生;
监听按键
cat /proc/bus/input/devices
得到如下结果:
I: Bus=0019 Vendor=0000 Product=0003 Version=0000
N: Name="Sleep Button"
P: Phys=PNP0C0E/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input0
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=4000 0 0
I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=PNP0C0C/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input1
U: Uniq=
H: Handlers=kbd event1
B: PROP=0
B: EV=3
B: KEY=10000000000000 0
I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input2
U: Uniq=
H: Handlers=kbd event2
B: PROP=0
B: EV=3
B: KEY=10000000000000 0
所以,可能需要监听event1或者event2,可以通过以下的代码直接监听事件的输入信息;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <linux/input.h>
struct input_event event;
int main(int argc, char **argv)
{
char name[64]; /* RATS: Use ok, but could be better */
char buf[256] = { 0, }; /* RATS: Use ok */
unsigned char mask[EV_MAX/8 + 1]; /* RATS: Use ok */
int version;
int fd = 0;
int rc;
int i, j;
char *tmp;
#define test_bit(bit) (mask[(bit)/8] & (1 << ((bit)%8)))
for (i = 0; i < 32; i++) {
sprintf(name, "/dev/input/event%d", i);
if ((fd = open(name, O_RDONLY, 0)) >= 0) {
ioctl(fd, EVIOCGVERSION, &version);
ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
ioctl(fd, EVIOCGBIT(0, sizeof(mask)), mask);
printf("%s\n", name);
printf(" evdev version: %d.%d.%d\n",
version >> 16, (version >> 8) & 0xff, version & 0xff);
printf(" name: %s\n", buf);
printf(" features:");
for (j = 0; j < EV_MAX; j++) {
if (test_bit(j)) {
const char *type = "unknown";
switch(j) {
case EV_KEY: type = "keys/buttons"; break;
case EV_REL: type = "relative"; break;
case EV_ABS: type = "absolute"; break;
case EV_MSC: type = "reserved"; break;
case EV_LED: type = "leds"; break;
case EV_SND: type = "sound"; break;
case EV_REP: type = "repeat"; break;
case EV_FF: type = "feedback"; break;
}
printf(" %s", type);
}
}
printf("\n");
close(fd);
}
}
if (argc > 1) {
sprintf(name, "/dev/input/event%d", atoi(argv[1]));
if ((fd = open(name, O_RDWR, 0)) >= 0) {
printf("%s: open, fd = %d\n", name, fd);
for (i = 0; i < LED_MAX; i++) {
event.time.tv_sec = time(0);
event.time.tv_usec = 0;
event.type = EV_LED;
event.code = i;
event.value = 0;
write(fd, &event, sizeof(event));
}
while ((rc = read(fd, &event, sizeof(event))) > 0) {
printf("%-24.24s.%06lu type 0x%04x; code 0x%04x;"
" value 0x%08x; ",
ctime(&event.time.tv_sec),
event.time.tv_usec,
event.type, event.code, event.value);
switch (event.type) {
case EV_KEY:
if (event.code > BTN_MISC) {
printf("Button %d %s",
event.code & 0xff,
event.value ? "press" : "release");
} else {
printf("Key %d (0x%x) %s",
event.code & 0xff,
event.code & 0xff,
event.value ? "press" : "release");
}
break;
case EV_REL:
switch (event.code) {
case REL_X: tmp = "X"; break;
case REL_Y: tmp = "Y"; break;
case REL_HWHEEL: tmp = "HWHEEL"; break;
case REL_DIAL: tmp = "DIAL"; break;
case REL_WHEEL: tmp = "WHEEL"; break;
case REL_MISC: tmp = "MISC"; break;
default: tmp = "UNKNOWN"; break;
}
printf("Relative %s %d", tmp, event.value);
break;
case EV_ABS:
switch (event.code) {
case ABS_X: tmp = "X"; break;
case ABS_Y: tmp = "Y"; break;
case ABS_Z: tmp = "Z"; break;
case ABS_RX: tmp = "RX"; break;
case ABS_RY: tmp = "RY"; break;
case ABS_RZ: tmp = "RZ"; break;
case ABS_THROTTLE: tmp = "THROTTLE"; break;
case ABS_RUDDER: tmp = "RUDDER"; break;
case ABS_WHEEL: tmp = "WHEEL"; break;
case ABS_GAS: tmp = "GAS"; break;
case ABS_BRAKE: tmp = "BRAKE"; break;
case ABS_HAT0X: tmp = "HAT0X"; break;
case ABS_HAT0Y: tmp = "HAT0Y"; break;
case ABS_HAT1X: tmp = "HAT1X"; break;
case ABS_HAT1Y: tmp = "HAT1Y"; break;
case ABS_HAT2X: tmp = "HAT2X"; break;
case ABS_HAT2Y: tmp = "HAT2Y"; break;
case ABS_HAT3X: tmp = "HAT3X"; break;
case ABS_HAT3Y: tmp = "HAT3Y"; break;
case ABS_PRESSURE: tmp = "PRESSURE"; break;
case ABS_DISTANCE: tmp = "DISTANCE"; break;
case ABS_TILT_X: tmp = "TILT_X"; break;
case ABS_TILT_Y: tmp = "TILT_Y"; break;
case ABS_MISC: tmp = "MISC"; break;
default: tmp = "UNKNOWN"; break;
}
printf("Absolute %s %d", tmp, event.value);
break;
case EV_MSC: printf("Misc"); break;
case EV_LED: printf("Led"); break;
case EV_SND: printf("Snd"); break;
case EV_REP: printf("Rep"); break;
case EV_FF: printf("FF"); break;
break;
}
printf("\n");
}
printf("rc = %d, (%s)\n", rc, strerror(errno));
close(fd);
}
}
return 0;
}
按下电源按键之后,最终实践发现是event2,可以监听到key code以及按键的动作;
...
/dev/input/event2: open, fd = 3
Thu Mar 21 21:38:28 2019.801129 type 0x0001; code 0x0074; value 0x00000001; Key 116 (0x74) press
Thu Mar 21 21:38:28 2019.801129 type 0x0000; code 0x0000; value 0x00000000;
Thu Mar 21 21:38:28 2019.801159 type 0x0001; code 0x0074; value 0x00000000; Key 116 (0x74) release
Thu Mar 21 21:38:28 2019.801159 type 0x0000; code 0x0000; value 0x00000000;
Thu Mar 21 21:38:35 2019.038000 type 0x0001; code 0x0074; value 0x00000001; Key 116 (0x74) press
Thu Mar 21 21:38:35 2019.038000 type 0x0000; code 0x0000; value 0x00000000;
Thu Mar 21 21:38:35 2019.038028 type 0x0001; code 0x0074; value 0x00000000; Key 116 (0x74) release
Thu Mar 21 21:38:35 2019.038028 type 0x0000; code 0x0000; value 0x00000000;
Ubuntu 拦截并监听 power button 的关机消息的更多相关文章
- Andoird 监听开机广播和关机广播
需求:有时候,我们需要自己的程序在开机后自动运行;在关机时,记录一些信息到文件中. 一.开机广播监听Android系统启动完成后会自动发出启动完成广播(android.intent.action.BO ...
- ndroid如何监听开机广播和关机广播
需求描述:有些时候,我们需要我们的程序在开机后能自动运行,在系统即将关闭时,能写入一些记录到指定的文件里. 一.开机广播监听: Android系统启动完成后会发出启动完成广播(android.inte ...
- popstate实现history路由拦截,监听页面返回事件
1.当活动历史记录条目更改时,将触发popstate事件. 如果被激活的历史记录条目是通过对history.pushState()的调用创建的, 或者受到对history.replaceState() ...
- android 监听 USB 拔插广播消息
USBBroadcastReceiver.java package com.example.communication; import android.content.BroadcastReceive ...
- QT中使用Event Filter监听button事件,Release后button不见
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhenyu5211314/article/details/27201043 问题RT,在程序中我使用 ...
- IOS之UI--自定义按钮实现代理监听点击事件
前言: Objective-C提供的按钮监听事件的方法是 不含参数的监听方法 [button实例对象 addTarget:self action:@selector(func) forControlE ...
- 安卓作为udp服务器,PC作为客户端,仅监听
安卓客户端作为udp服务器,监听其他客户端的数据,测试已成功 本次实验所用数据: 安卓作为服务器: 端口:8888 IP:192.168.1.104 电脑作为客户端: 端口:50 ...
- java Gui编程 事件监听机制
1. GUI编程引言 以前的学习当中,我们都使用的是命令交互方式: 例如:在DOS命令行中通过javac java命令启动程序. 软件的交互的方式: 1. 命令交互方式 图书管理系统 ...
- cocos2d-x JS 弹出对话框触摸监听(吞噬点击事件遮挡层)
在游戏中,我们经常会碰到一些弹窗,这些弹窗禁止点透,也就是禁止触摸事件传递到底层,我们称之为遮挡层,这些遮挡层,需要开发遮挡层,我们首先得了解cocos2d-js的触摸传递机制. 根据官方文档,我们可 ...
随机推荐
- K - Two Contests
题目连接:https://atcoder.jp/contests/agc040/tasks/agc040_b 大佬题解:https://blog.csdn.net/duanghaha/article/ ...
- 今天我们来讨论一下CSS3属性中的transition属性;
transition属性是CSS3属性:顾名思义英文为过渡的意思:主要有四个值与其一一对应:分别是property(CSS属性名称),duration过渡的时长,timimg-function转速曲线 ...
- 通过dockerfile制作镜像
Dockerfile是一个用于构建Docker镜像的文本文件,其中包含了创建Docker镜像的全部指令.就是将我们安装环境的每个步骤使用指令的形式存放在一个文件中,最后生成一个需要的环境. Docke ...
- asp.net core webapi Session 跨域
在ajax 请求是也要加相应的东西 $.ajax({ url:url, //加上这句话 xhrFields: { withCredentials: true } success:function(re ...
- Spring Cloud 系列之 Gateway 服务网关(四)
本篇文章为系列文章,未读第一集的同学请猛戳这里: Spring Cloud 系列之 Gateway 服务网关(一) Spring Cloud 系列之 Gateway 服务网关(二) Spring Cl ...
- C# 基础知识系列- 12 任务和多线程
0. 前言 照例一份前言,在介绍任务和多线程之前,先介绍一下异步和同步的概念.我们之间介绍的知识点都是在同步执行,所谓的同步就是一行代码一行代码的执行,就像是我们日常乘坐地铁通过安检通道一样,想象我们 ...
- TensorFlow-keras fit的callbacks参数,定值保存模型
from tensorflow.python.keras.preprocessing.image import load_img,img_to_array from tensorflow.python ...
- ASP.NET Core Razor Pages 初探
最近新建 Asp.net Core MVC 项目的时候不小心选错了个模板,发现了一种新的项目模板.它使用cshtml视图模板,但是没有Controller文件夹.后来才发现这是ASP.NET Core ...
- mysql查询添加
当表结构一样的情况下,insert into 想要插入的表 SELECT * from 查询的表; 此sql语句,适应于 1000万数据插入1000万数据中去,2000万数据的合并 .------ ...
- Windows环境,获取当前线程的ID,GetCurrentThreadId
GetCurrentThreadId 打印格式:0x%08lx 头文件:processthreadsapi.h (include Windows Server 2003, Windows Vista, ...