概述
文章目录
- 基本理解Linux 内核事件通知链
- 1. TP 驱动相关代码
- 2. LCM 背光相关代码
- 3. 运行结果
- 深入探究Linux 内核事件通知链
- 1. 通知链的引入
- 2. 四种通知链的类型
- 原子通知链(Atomic notifier chains)
- 可阻塞通知链(Blocking notifier chains)
- 原始通知链(Raw notifierchains)
- SRCU 通知链(SRCU notifier chains)
- 3. 一个简单的通知链实例
基本理解Linux 内核事件通知链
内核事件通知链一个比较典型的例子就是Display 背光通知TP suspend和resume 的过程,我们这里先从的LCD 背光通知TP suspend 入场,以快速理解Linux 内核事件通知链应用。
1. TP 驱动相关代码
kernel-4.9/drivers/input/touchscreen/xxxxx_touch/xxxx_core.c
TP 驱动probe 函数里指定到背光通知回调函数fb_notifier_callback
,并注册到通知链里。fb_notifier_callback 函数根据收到的通知event信息调用TS resume 或suspend 函数。
static int xxx_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
... ...
ts_data->fb_notif.notifier_call = fb_notifier_callback;
ret = fb_register_client(&ts_data->fb_notif);
}
static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
{
struct fb_event *evdata = data;
int *blank;
struct xxx_ts_data *xxx_data = container_of(self, struct xxx_ts_data, fb_notif);
printk("[xxx][WU] event = %ld, FB_EVENT_BLANK = %d or FB_EARLY_EVENT_BLANK = %d",
event, FB_EVENT_BLANK); //16 == 9 or 16; 9 == 9 or 16
if (evdata && evdata->data && event == FB_EARLY_EVENT_BLANK
&& fts_data && fts_data->client) {
blank = evdata->data;
printk("[FTS][WU] blank = %d", *blank);
if (*blank == FB_BLANK_UNBLANK){//0
printk("[FTS][WU] fts_ts_resume FB_BLANK_UNBLANK = %d", FB_BLANK_UNBLANK);
fts_ts_resume(&fts_data->client->dev);
}
else if (*blank == FB_BLANK_POWERDOWN){//4
printk("[FTS][WU] fts_ts_suspend FB_BLANK_POWERDOWN = %d", FB_BLANK_POWERDOWN);
fts_ts_suspend(&fts_data->client->dev);
}
}
return 0;
}
注:若对上面container_of
有题问,可参考文章 《从基本理解到深入探究Linux kernel container_of 宏》
2. LCM 背光相关代码
kernel-4.9/drivers/video/fbdev/core/fbmem.c
LCM 背光代码根据相关场景给通知链发送相关事件的通知,通知链收到通知就执行上面的背光通知回调函数fb_notifier_callback,fb_notifier_callback函数根据不同event事件执行不同的函数。
int fb_blank(struct fb_info *info, int blank)
{ ...
early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);// FB_EARLY_EVENT_BLANK = 16
if (info->fbops->fb_blank)
ret = info->fbops->fb_blank(blank, info);
if (!ret)
fb_notifier_call_chain(FB_EVENT_BLANK, &event); //FB_EVENT_BLANK = 9
else {
/** if fb_blank is failed then revert effects of
* the early blank event. */
if (!early_ret)
fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
}
return ret;
}
...
void fb_set_suspend(struct fb_info *info, int state)
{
struct fb_event event;
event.info = info;
if (state) {
fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); // FB_EVENT_SUSPEND = 0x02
info->state = FBINFO_STATE_SUSPENDED;
} else {
info->state = FBINFO_STATE_RUNNING;
fb_notifier_call_chain(FB_EVENT_RESUME, &event); // FB_EVENT_RESUME = 0x03
}
}
3. 运行结果
下面是板子运行的log(已经屏蔽客户信息),我们在下面在log解释原理比较简明吧!
从运行结果可以知道背光通知TP过程中,先休眠TP再休眠LCM。
[32m[ 1045.412245] [33mPM[0m: suspend entry 2019-01-13 19:15:43.130364966 UTC // linux kernel 进入休眠
// 退出休眠与进入休眠的UTC时间戳一差,就是kernel 休眠的时间(19:15:55 - 19:15:43)
// 按电源键唤醒系统亮屏 ... ...
[32m[ 1050.799717] [33mPM[0m: suspend exit 2019-01-13 19:15:55.594697461 UTC // linux kernel 退出休眠
[32m[ 1051.144198] [0m[xxx][WU] event = 16, FB_EVENT_BLANK = 9 // 背光发送两次event,一次是16一次是9
[32m[ 1051.144211] [0m[xxx][WU] event = 9, FB_EVENT_BLANK = 9
[32m[ 1051.144221] [0m[xxx][WU] blank = 0 // 其中参数的blank 为0 调用TP resume
[32m[ 1051.144232] [0m[xxx][WU] xxx_ts_resume FB_BLANK_UNBLANK = 0
[32m[ 1051.144233] [33m[xxx]xxx_ts_resume[0m: Enter
[32m[ 1051.146266] [33m[xxx]xxx_ts_resume[0m: Exit(1668)
// 亮屏了10s后,按电源键灭屏 ... ...
[32m[ 1061.519665] [0m[xxx][WU] event = 16, FB_EVENT_BLANK = 9 // 背光发送两次event,一次是16一次是9
[32m[ 1061.519680] [0m[xxx][WU] event = 9, FB_EVENT_BLANK = 9
[32m[ 1061.519690] [0m[xxx][WU] blank = 4 // 其中参数的blank 为4 调用TP suspend
[32m[ 1061.519702] [0m[xxx][WU] xxx_ts_suspend FB_BLANK_POWERDOWN = 4
[32m[ 1061.519703] [33m[xxx]xxx_ts_suspend[0m: Enter
[32m[ 1061.523594] [33m[xxx]xxx_ts_suspend[0m: Exit(1609)
[32m[ 1061.528000] [33m mdss_dsi_panel_power_off // 然后display 下电
[32m[ 1061.529240] [33mhbtp[31m: hbtp->input_dev not ready!
[32m[ 1061.532073] [33mPM[0m: suspend entry 2019-01-13 19:16:06.327045373 UTC
...
[32m[ 1061.649485] [33mPM[0m: suspend exit 2019-01-13 19:16:06.444469957 UTC
[32m[ 1061.853378] [33mPM[0m: suspend entry 2019-01-13 19:16:06.648349227 UTC
[32m[ 1061.853419] [33mPM[0m: Syncing filesystems ... done.
[32m[ 1061.888011] [33mPM[0m: Preparing system for sleep (mem)
[32m[ 1061.888187] [0mFreezing user space processes ... (elapsed 3.964 seconds) done.
[32m[ 1065.852448] [0mFreezing remaining freezable tasks ... (elapsed 0.009 seconds) done.
[32m[ 1065.861693] [33mPM[0m: Suspending system (mem)
[32m[ 1065.861723] [0mSuspending console(s) (use no_console_suspend to debug)
// 因为TP已经休眠了, 上面 fb_set_suspend 函数也发来fb set supend 事件,不过这次已经无效了
[32m[ 1065.895347] [0m[xxx][WU] event = 2, FB_EVENT_BLANK = 9, FB_EVENT_SUSPEND = 2 // fb_set_suspend
[32m[ 1065.933676] [0m[xxx][WU] event = 2, FB_EVENT_BLANK = 9, FB_EVENT_SUSPEND = 2 // fb_set_suspend
[32m[ 1066.742596] [33mPM[0m: suspend exit 2019-01-13 19:16:27.002118646 UTC
总结下来就三个函数:
int fb_register_client(struct notifier_block *nb)
int fb_unregister_client(struct notifier_block *nb)
int fb_notifier_call_chain(unsigned long val, void *v)
上面三个函数就只是简单调用系统接口,如下代码 linux/drivers/video/fbdev/core/fb_notify.c
/*
* linux/drivers/video/fb_notify.c
*
* Copyright (C) 2006 Antonino Daplas <adaplas@pol.net>
*
* 2001 - Documented with DocBook
* - Brad Douglas <brad@neruo.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/fb.h>
#include <linux/notifier.h>
#include <linux/export.h>
static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
/**
* fb_register_client - register a client notifier
* @nb: notifier block to callback on events
*/
int fb_register_client(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&fb_notifier_list, nb);
}
EXPORT_SYMBOL(fb_register_client);
/**
* fb_unregister_client - unregister a client notifier
* @nb: notifier block to callback on events
*/
int fb_unregister_client(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
}
EXPORT_SYMBOL(fb_unregister_client);
/**
* fb_notifier_call_chain - notify clients of fb_events
*
*/
int fb_notifier_call_chain(unsigned long val, void *v)
{
return blocking_notifier_call_chain(&fb_notifier_list, val, v);
}
EXPORT_SYMBOL_GPL(fb_notifier_call_chain);
注:EXPORT_SYMBOL_GPL
是导出参数的函数给kernel其他地方使用,要加include头文件。
一般会使用这个几个接口就行了,若不想放弃请看下面深入探究Linux 内核事件通知链。
深入探究Linux 内核事件通知链
1. 通知链的引入
Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施。为满足这样的需求,内核实现了事件通知链机制(notification chain)。
通知链只能用在各个子系统之间,而不能在内核和用户空间进行事件的通知。组成内核的核心系统代码均位于kernel目录下,通知链表位于kernel/notifier.c
中,对应的头文件为include/linux/notifier.h
。
事件通知链表是一个事件处理函数的列表,每个通知链都与某个或某些事件有关,当特定的事件发生时,就调用相应的事件通知链中的回调函数,进行相应的处理。
2. 四种通知链的类型
内核使用struct notifier_block结构代表一个notifier
struct notifier_block;
typedef int (*notifier_fn_t)(struct notifier_block *nb,
unsigned long action, void *data); //notifier回调函数类型
struct notifier_block {
notifier_fn_t notifier_call; //回调函数
struct notifier_block __rcu *next; //用于挂到通知链上
int priority;
}; //notifier 结构体
内核提供了四种不同类型的notifier chain,notifier block 和 notifier chain的数据结构组织方式如下:
原子通知链(Atomic notifier chains)
之所以被称为原子通知链,是因为通知链元素的回调函数(当事件发生时要执行的函数)在中断或原子操作上下文中运行,不允许阻塞。
struct atomic_notifier_head {
spinlock_t lock; // 自旋锁保护通知链
struct notifier_block __rcu *head; //通知链元素的链表
};
原子通知链对应的API
//1.初始化一个原子通知链
#define ATOMIC_NOTIFIER_HEAD(name)
struct atomic_notifier_head name =
ATOMIC_NOTIFIER_INIT(name)
//2.注册一个notifier block 到通知链
extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
struct notifier_block *nb);
//3.发送一个事件到通知链上的notifier block
extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
unsigned long val, void *v);
//4.从通知链删除一个notifier block
extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
struct notifier_block *nb);
相关函数定义如下
/*
* Atomic notifier chain routines. Registration and unregistration
* use a spinlock, and call_chain is synchronized by RCU (no locks).
*/
int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
struct notifier_block *n)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&nh->lock, flags);
ret = notifier_chain_register(&nh->head, n);
spin_unlock_irqrestore(&nh->lock, flags);
return ret;
}
int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
struct notifier_block *n)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&nh->lock, flags);
ret = notifier_chain_unregister(&nh->head, n);
spin_unlock_irqrestore(&nh->lock, flags);
synchronize_rcu();
return ret;
}
/**
* Calls each function in a notifier chain in turn. The functions
* run in an atomic context, so they must not block.
* This routine uses RCU to synchronize with changes to the chain.
*/
int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
unsigned long val, void *v,
int nr_to_call, int *nr_calls)
{
int ret;
rcu_read_lock();
ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
rcu_read_unlock();
return ret;
}
int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
unsigned long val, void *v)
{
return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
}
可阻塞通知链(Blocking notifier chains)
通知链元素的回调函数在进程上下文中运行,允许阻塞。
struct blocking_notifier_head {
struct rw_semaphore rwsem;
struct notifier_block *head;
};
可阻塞通知链对应的API
//1.初始化一个阻塞通知链
#define BLOCKING_NOTIFIER_HEAD(name)
struct blocking_notifier_head name =
BLOCKING_NOTIFIER_INIT(name)
//2.注册一个notifier block 到通知链
extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *nb);
//3.发送一个事件到通知链上的notifier block
extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
unsigned long val, void *v);
//4.从通知链删除一个notifier block
extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
struct notifier_block *nb);
相关函数定义如下
/*
* Blocking notifier chain routines. All access to the chain is
* synchronized by an rwsem.
*/
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *n)
{
int ret;
/*
* This code gets used during boot-up, when task switching is
* not yet working and interrupts must remain disabled. At
* such times we must not call down_write().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
return notifier_chain_register(&nh->head, n);
down_write(&nh->rwsem);
ret = notifier_chain_register(&nh->head, n);
up_write(&nh->rwsem);
return ret;
}
int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
struct notifier_block *n)
{
int ret;
/*
* This code gets used during boot-up, when task switching is
* not yet working and interrupts must remain disabled. At
* such times we must not call down_write().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
return notifier_chain_unregister(&nh->head, n);
down_write(&nh->rwsem);
ret = notifier_chain_unregister(&nh->head, n);
up_write(&nh->rwsem);
return ret;
}
int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
unsigned long val, void *v,
int nr_to_call, int *nr_calls)
{
int ret = NOTIFY_DONE;
/*
* We check the head outside the lock, but if this access is
* racy then it does not matter what the result of the test
* is, we re-check the list after having taken the lock anyway:
*/
if (rcu_access_pointer(nh->head)) {
down_read(&nh->rwsem);
ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
nr_calls);
up_read(&nh->rwsem);
}
return ret;
}
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
unsigned long val, void *v)
{
return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
}
原始通知链(Raw notifierchains)
对通知链元素的回调函数没有任何限制,所有锁和保护机制都由调用者维护。
struct raw_notifier_head {
struct notifier_block *head;
};
原始通知链对应的API
//1.初始化一个原始通知链
#define RAW_NOTIFIER_HEAD(name)
struct raw_notifier_head name =
RAW_NOTIFIER_INIT(name)
//2.注册一个notifier block 到通知链
extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
struct notifier_block *nb);
//3.发送一个事件到通知链上的notifier block
extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v);
//4.从通知链删除一个notifier block
extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
struct notifier_block *nb);
相关函数定义如下
/*
* Raw notifier chain routines. There is no protection;
* the caller must provide it. Use at your own risk!
*/
int raw_notifier_chain_register(struct raw_notifier_head *nh,
struct notifier_block *n)
{
return notifier_chain_register(&nh->head, n);
}
int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
struct notifier_block *n)
{
return notifier_chain_unregister(&nh->head, n);
}
int __raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v,
int nr_to_call, int *nr_calls)
{
return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
}
int raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v)
{
return __raw_notifier_call_chain(nh, val, v, -1, NULL);
}
SRCU 通知链(SRCU notifier chains)
可阻塞通知链的一种变体。对应的链表头:
struct srcu_notifier_head {
struct mutex mutex;
struct srcu_struct srcu;
struct notifier_block *head;
};
SRCU 通知链对应的API
//1.初始化一个SRCU通知链
#ifdef CONFIG_TREE_SRCU
#define _SRCU_NOTIFIER_HEAD(name, mod)
static DEFINE_PER_CPU(struct srcu_data, name##_head_srcu_data);
mod struct srcu_notifier_head name =
SRCU_NOTIFIER_INIT(name, name##_head_srcu_data)
#else
#define _SRCU_NOTIFIER_HEAD(name, mod)
mod struct srcu_notifier_head name =
SRCU_NOTIFIER_INIT(name, name)
#endif
//2.注册一个notifier block 到通知链
extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
struct notifier_block *nb);
//3.发送一个事件到通知链上的notifier block
extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v);
//4.从通知链删除一个notifier block
extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
unsigned long val, void *v);
相关函数定义如下
#ifdef CONFIG_SRCU
/*
* SRCU notifier chain routines. Registration and unregistration
* use a mutex, and call_chain is synchronized by SRCU (no locks).
*/
int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
struct notifier_block *n)
{
int ret;
/*
* This code gets used during boot-up, when task switching is
* not yet working and interrupts must remain disabled. At
* such times we must not call mutex_lock().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
return notifier_chain_register(&nh->head, n);
mutex_lock(&nh->mutex);
ret = notifier_chain_register(&nh->head, n);
mutex_unlock(&nh->mutex);
return ret;
}
int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
struct notifier_block *n)
{
int ret;
/*
* This code gets used during boot-up, when task switching is
* not yet working and interrupts must remain disabled. At
* such times we must not call mutex_lock().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
return notifier_chain_unregister(&nh->head, n);
mutex_lock(&nh->mutex);
ret = notifier_chain_unregister(&nh->head, n);
mutex_unlock(&nh->mutex);
synchronize_srcu(&nh->srcu);
return ret;
}
int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
unsigned long val, void *v,
int nr_to_call, int *nr_calls)
{
int ret;
int idx;
idx = srcu_read_lock(&nh->srcu);
ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
srcu_read_unlock(&nh->srcu, idx);
return ret;
}
int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
unsigned long val, void *v)
{
return __srcu_notifier_call_chain(nh, val, v, -1, NULL);
}
#endif /* CONFIG_SRCU */
3. 一个简单的通知链实例
我们可以自己写一个内核模块在Ubuntu 运行验证一下通知链的使用方法。
- 1.模块代码
/**
* file : raw-notifer-chain.c
* owner: wuchengbing
* data : 20190125
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
//#include <linux/fs.h>
//#include <linux/delay.h>
#include <linux/notifier.h>
// define notifier event type
#define EVENT_A 0x01
#define EVENT_B 0x02
static RAW_NOTIFIER_HEAD(raw_chain_list); //define notifer chain list
// define callback function
int raw_notifer_callback(struct notifier_block *nb, unsigned long event, void *v)
{
switch (event) {
case EVENT_A:
printk("raw_notifer_callback running EVENT_An");
break;
case EVENT_B:
printk("raw_notifer_callback running EVENT_Bn");
break;
default:
break;
}
return NOTIFY_DONE;
}
// define notifier block
static struct notifier_block raw_notif = {
.notifier_call = raw_notifer_callback, //appoint notifier callback function
};
static int __init raw_notifier_init(void)
{
printk("raw_notifier_chain_registernn");
raw_notifier_chain_register(&raw_chain_list, &raw_notif);
printk("raw_notifier call EVENT_An");
raw_notifier_call_chain(&raw_chain_list, EVENT_A, NULL);
printk("raw_notifier call EVENT_Bn");
raw_notifier_call_chain(&raw_chain_list, EVENT_B, NULL);
return 0;
}
static void __exit raw_notifier_exit(void)
{
printk("raw_notifier_chain_unregisternn");
raw_notifier_chain_unregister(&raw_chain_list, &raw_notif);
}
module_init(raw_notifier_init);
module_exit(raw_notifier_exit);
MODULE_AUTHOR("Wu_Being");
MODULE_LICENSE("GPL");
- 2.Makefile 文件
##
# file : Makefile
# owner: wuchengbing
# data : 20190125
##
obj-m += raw-chain-notifier.o # geneate modules ko file
CURRENT_PATH := $(shell pwd) # current core path
LINUX_KERNEL := $(shell uname -r) # kernel version
# kernel core path
LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)
# make or make all
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
# make clean
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
- 3.运行结果
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ ls -l
total 8
-rw-rw-r-- 1 wucb0122 wucb0122 453 1月 25 10:10 Makefile
-rw-rw-r-- 1 wucb0122 wucb0122 1440 1月 25 10:08 raw-chain-notifier.c
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ make
make -C /usr/src/linux-headers-3.13.0-147-generic M=/home/wucb0122/Codes/notifier_chain/raw-notifer-chain modules
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-147-generic'
CC [M] /home/wucb0122/Codes/notifier_chain/raw-notifer-chain/raw-chain-notifier.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/wucb0122/Codes/notifier_chain/raw-notifer-chain/raw-chain-notifier.mod.o
LD [M] /home/wucb0122/Codes/notifier_chain/raw-notifer-chain/raw-chain-notifier.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-147-generic'
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ls -ltr
total 36
-rw-rw-r-- 1 wucb0122 wucb0122 1440 1月 25 10:08 raw-chain-notifier.c
-rw-rw-r-- 1 wucb0122 wucb0122 451 1月 25 10:12 Makefile
-rw-rw-r-- 1 wucb0122 wucb0122 4752 1月 25 10:12 raw-chain-notifier.o
-rw-rw-r-- 1 wucb0122 wucb0122 83 1月 25 10:12 modules.order
-rw-rw-r-- 1 wucb0122 wucb0122 966 1月 25 10:12 raw-chain-notifier.mod.c
-rw-rw-r-- 1 wucb0122 wucb0122 0 1月 25 10:12 Module.symvers
-rw-rw-r-- 1 wucb0122 wucb0122 2784 1月 25 10:12 raw-chain-notifier.mod.o
-rw-rw-r-- 1 wucb0122 wucb0122 5395 1月 25 10:12 raw-chain-notifier.ko
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ sudo insmod raw-chain-notifier.ko
[sudo] password for wucb0122:
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ sudo dmesg -c
...
[153967.504748] raw_chain_notifier: module verification failed: signature and/or required key missing - tainting kernel
[153967.505121] raw_notifier_chain_register
[153967.505121]
[153967.505123] raw_notifier call EVENT_A
[153967.505124] raw_notifer_callback running EVENT_A
[153967.505124] raw_notifier call EVENT_B
[153967.505125] raw_notifer_callback running EVENT_B
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ make clean
make -C /usr/src/linux-headers-3.13.0-147-generic M=/home/wucb0122/Codes/notifier_chain/raw-notifer-chain clean
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-147-generic'
CLEAN /home/wucb0122/Codes/notifier_chain/raw-notifer-chain/.tmp_versions
CLEAN /home/wucb0122/Codes/notifier_chain/raw-notifer-chain/Module.symvers
make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-147-generic'
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ ls -ltr
total 8
-rw-rw-r-- 1 wucb0122 wucb0122 451 1月 25 10:12 Makefile
-rw-rw-r-- 1 wucb0122 wucb0122 1479 1月 25 10:19 raw-chain-notifier.c
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ sudo rmmod raw-chain-notifier.ko
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$ sudo dmesg -c
[154548.347863] raw_notifier_chain_unregister
[154548.347863]
wucb0122@wucb0122-ubuntu14:~/Codes/notifier_chain/raw-notifer-chain$
Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《从基本理解到深入探究Linux kernel 通知链(notifier chain)》:https://blog.csdn.net/u014134180/article/details/86563754
最后
以上就是酷炫自行车为你收集整理的从基本理解到深入探究 Linux kernel 通知链(notifier chain)基本理解Linux 内核事件通知链深入探究Linux 内核事件通知链的全部内容,希望文章能够帮你解决从基本理解到深入探究 Linux kernel 通知链(notifier chain)基本理解Linux 内核事件通知链深入探究Linux 内核事件通知链所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复