- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在开发一个 Linux 内核模块 (LKM),它分析我笔记本电脑的电池参数并在每个给定时间间隔内写入内核日志文件 (/var/log/kern.log)。使用日志文件中的数据,我将绘制实时图表。
您可能会想我为什么要做这些事情。这是我的学术的一部分是对它的回答。另外,我觉得这很有趣。
我对这项任务的整个分析一直很简单,直到最近。我遵循的步骤是:
有了这两个 LKM,我误以为我的任务很简单,因为唯一遗漏的任务是组合这两个 LKM 并将所需的参数数据写入日志文件。
我结合了两个 LKM 的代码并制作了一个 LKM,并将其插入我的 Ubuntu 14.04 64 位操作系统内核中。系统瞬间卡住了,吓了我一跳。我当时一头雾水。
在此之后,我减少了电池分析器 LKM 和定时器 LKM 的代码,这些代码对于我想要的输出来说是最少需要运行的。我发现简化的代码运行起来很舒服。
后来我将分析电池参数的代码迁移到一个函数并将其导出(使用 EXPORT_SYMBOL(<function_name>)
,从计时器方法调用。我非常确定这肯定会运行,因为两个 LKM 都运行良好.
我想通过以下 LKM 代码和视频向您展示我的机器中发生的真实情况。
bat_stat_analyzer.c - LKM 获取电池参数并写入内核日志文件。
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/power_supply.h>
static int result = 0;
static struct power_supply *psy;
static void bat_stat(void);
EXPORT_SYMBOL(bat_stat);
static void bat_stat(void) {
union power_supply_propval value;
int charge_status, voltage_now, current_now, capacity;
psy = power_supply_get_by_name("BAT1");
result = psy->get_property(psy,POWER_SUPPLY_PROP_STATUS, &value);
charge_status = (!result) ? value.intval : -1;
result = psy->get_property(psy,POWER_SUPPLY_PROP_VOLTAGE_NOW, &value);
voltage_now = (!result) ? value.intval : -1;
result = psy->get_property(psy,POWER_SUPPLY_PROP_CURRENT_NOW, &value);
current_now = (!result) ? value.intval : -1;
result = psy->get_property(psy,POWER_SUPPLY_PROP_CAPACITY, &value);
capacity = (!result) ? value.intval : -1;
printk(KERN_INFO "%s:%d,%d,%d,%d\n",
__func__, charge_status, voltage_now, current_now, capacity);
}
static int __init bat_stat_init(void) /* Constructor */
{
bat_stat();
return 0;
}
static void __exit bat_stat_exit(void) /* Destructor */
{
printk(KERN_INFO "Good bye\n");
}
module_init(bat_stat_init);
module_exit(bat_stat_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sriram Kumar <sriramhearing_at_gmail_dot_com>");
MODULE_DESCRIPTION("First Battery Analyzer");
bat_stat_repeater.c - 重复调用函数的 LKM
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/hrtimer.h>
static unsigned long period_ms;
static unsigned long period_ns;
static ktime_t ktime_period_ns;
static struct hrtimer my_hrtimer;
extern int bat_stat(void);
//~ static void bat_stat_repeat(unsigned long data)
static enum hrtimer_restart bat_stat_repeat(struct hrtimer *timer)
{
unsigned long tjnow;
ktime_t kt_now;
bat_stat();
printk(KERN_INFO "Repeating...\n");
tjnow = jiffies;
kt_now = hrtimer_cb_get_time(&my_hrtimer);
hrtimer_forward(&my_hrtimer, kt_now, ktime_period_ns);
return HRTIMER_RESTART;
}
static int __init bat_stat_init(void)
{
struct timespec tp_hr_res;
period_ms = 1000;
hrtimer_get_res(CLOCK_MONOTONIC, &tp_hr_res);
hrtimer_init(&my_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
my_hrtimer.function = &bat_stat_repeat;
period_ns = period_ms*( (unsigned long)1E6L );
ktime_period_ns = ktime_set(0,period_ns);
hrtimer_start(&my_hrtimer, ktime_period_ns, HRTIMER_MODE_REL);
return 0;
}
static void __exit bat_stat_exit(void)
{
int ret_cancel = 0;
while( hrtimer_callback_running(&my_hrtimer) ) {
ret_cancel++;
}
if (ret_cancel != 0) {
printk(KERN_INFO " testjiffy Waited for hrtimer callback to finish (%d)\n", ret_cancel);
}
if (hrtimer_active(&my_hrtimer) != 0) {
ret_cancel = hrtimer_cancel(&my_hrtimer);
printk(KERN_INFO " testjiffy active hrtimer cancelled: %d\n", ret_cancel);
}
if (hrtimer_is_queued(&my_hrtimer) != 0) {
ret_cancel = hrtimer_cancel(&my_hrtimer);
printk(KERN_INFO " testjiffy queued hrtimer cancelled: %d\n", ret_cancel);
}
printk(KERN_INFO "Exit testjiffy\n");
}
module_init(bat_stat_init);
module_exit(bat_stat_exit);
MODULE_LICENSE("GPL");
我使用的 Makefile 如下所示,因为它用于编译两个 LKM。
obj-m := <file_name>.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
可以在这个 youtube 上查看我使用这两个 LKM 获得的输出 link (只有 2 分钟的视频)。如果您希望将其作为图像查看,请附在下面:
我想知道:
提前致谢。
最佳答案
由于使用 hrtimers
,您遇到了问题。此机制专为高精度而设计,回调在 hardirq 上下文中调用(禁用 IRQ),因此您的回调函数必须是原子的。然而,您从回调中调用的函数不是原子的,可能会休眠(因为互斥锁)。普通计时器有类似的问题,因此为了解决这个问题,您应该使用其他方式或重复任务,例如工作队列。
您的代码中的其他一些小问题:
batt_stat
函数声明不同此外,我真的看不出有任何理由将其拆分为两个内核模块,您应该只使用一个。
关于c - 运行两个不同的 LKM 每秒获取电池统计信息时系统挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29830285/
我写了一个LKM(loadable kernel module),需要调用/linux/driver下的另一个内核驱动模块中的函数。我不知道如何将这些功能导入 LKM。由于/lib/modules/l
我知道内核使用 vmalloc() 加载可加载内核模块 (LKM) 假设整个 LKM 都驻留在堆中是否安全? 最佳答案 更准确地说,内核模块的内存是使用 vmalloc_exec() 分配的。 Is
我有一个简单的可加载内核模块,它通过提供闪烁周期、开/关功能等来控制 LED... 设备位于/sys/led ,并且运行正常。 我已经为命令行提供了一个输入参数,它接受 LED 连接到哪个 GPIO。
我的 LKM 劫持了 stdin/sshd 输入:https://pastebin.com/RChpbt9G # uname -a Linux kali 4.19.0-kali4-amd64 #1 S
所以我一直在尝试在运行 4.15.0-43-generic 并安装了 linux-headers-4.15.0-43 的 Ubuntu 18.04 上编译一个简单的“Hello world”LKM。
假设我在 linux-kernel 中插入了 Loadable-Kernel-Module 并且 Hook 了读、写、打开和关闭函数。所以现在我可以停止对任何文件的访问,但我想阻止文件被复制到设备外部
这个问题在这里已经有了答案: Implementing Linux System Call using LKM (1 个回答) 关闭 6 年前。 所以我看到了一堆关于添加系统调用的问题,但我找不到任
我制作了简单的 LKM(Linux 内核模块)以在用户级别与内核级别信息交互我的 MPI 应用程序(每个计算节点的多进程)。我需要在运行时从内核中提取一些数据到用户级应用程序。我的 MPI 应用程序使
我写了下面的代码: #include #include #include #include #include void **sys_call_table; int __init kaslr_
作为练习(安全研究),我正在尝试实现一个包装的系统调用。根据 getdents 文档 - 您必须实现自己的 linux_dirent 结构(https://linux.die.net/man/2/ge
我开始学习一个非常基本的“hello world”LKM,另外我已经向内核添加了功能并成功重新编译并且它可以工作。我现在喜欢做的是将一个变量添加到已编译的内核代码中,然后在加载和卸载模块时从我的 LK
我是内核新手,在使用内核模块的导出符号编译 Linux 内核时需要一些帮助。 我尝试了以下 - LKM 源代码中的 EXPORT_SYMBOL(func_name),LKM 编译并在其 Module.
我正在开发一个 Linux 内核模块 (LKM),它分析我笔记本电脑的电池参数并在每个给定时间间隔内写入内核日志文件 (/var/log/kern.log)。使用日志文件中的数据,我将绘制实时图表。
是否有可能在版本为 3.0.31- 的内核中使用为 3.0.8+ mod_unload ARMv5(我自制的内核)编译的可加载内核模块gd5a18e0 SMP 抢占 mod_unload ARMv7(
我在内核树之外使用 LKM,我想为我的模块使用一些编译选项,例如 MYLKM_CONFIG_{something}。我知道这可以使用 C 预处理 (#define//#ifdef//#endif) 来
我是内核开发技术的新手。我想知道一旦动态加载内核模块,是否有办法在内核和内核模块 (LKM) 之间建立通信。我想要做的是从内核的特定部分调用一个函数来发送一些数据,而内核模块正在等待它。如果模块还没有
我有一个生成数据的 Linux 内核模块,我想将该数据发送到用户空间应用程序。有哪些选择,它们有哪些优点/缺点? 比方说,数据可能是每秒几个 char[] 和几个 int[] 的 100 个结构。 此
我最近一直在研究这个问题,并查看了各种文章和 stackoverflow 帖子,但我似乎无法找到直接的答案。在创建内核模块时,我看到大多数代码如下所示: #include static int te
我的目标是编写一个 LKM(Linux 内核模块)来拦截所有 TCP 数据包、查找 tcp_sock 结构并根据某些条件从 tcp_sock 结构(例如:tcpsock->snd_una)记录一些信息
我正在从 Linux (3.x) 的系统调用表中覆盖 SYS_READ,但在卸载模块本身时遇到了一些麻烦。我首先加载找到系统调用表的模块,然后启用 RW,用我自己的 SYS_READ 函数覆盖 SYS
我是一名优秀的程序员,十分优秀!