Linux内核(十五)sysrq 详解 II —— 代码框架详解

文章目录

    • sysrq模块初始化流程图
    • sysrq模块代码详解
    • sysrq产生kernel crash事件流程
    • sysrq 整体框架图
    • sysrq 框架中添加自定义实例


Linux 版本:Linux version 3.18.24

sysrq模块初始化流程图

sysrq模块源码路径:linux-3.18.24.x/drivers/tty/sysrq.c
编译开启:CONFIG_MAGIC_SYSRQ=y
在这里插入图片描述


sysrq模块代码详解

1、sysrq模块初始化

static int __init sysrq_init(void)
{
    sysrq_init_procfs();                // 创建sysrq在proc下节点

    if (sysrq_on())                    // 每个linux版本不一样,红帽企业版Linux是需要控制的
        sysrq_register_handler();      // 注册sysrq的处理函数

    return 0;
}
module_init(sysrq_init);

2、创建sysrq在proc下节点:sysrq_init_procfs

static const struct file_operations proc_sysrq_trigger_operations = {
    .write      = write_sysrq_trigger,                // 写回调函数
    .llseek     = noop_llseek,
};

static void sysrq_init_procfs(void)
{
    if (!proc_create("sysrq-trigger", S_IWUSR, NULL,            // 在proc下创建sysrq-trigger节点,并注册文件操作结构体
             &proc_sysrq_trigger_operations))
        pr_err("Failed to register proc interface\n");
}

3、本linux系统内,proc下sysrq事件的回调函数注册始终是打开的:sysrq_on()

static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;   // #define CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 0x1

static bool sysrq_on(void)
{
    return sysrq_enabled || sysrq_always_enabled;            // sysrq始终都是打开的
}

static int __init sysrq_always_enabled_setup(char *str)
{
    sysrq_always_enabled = true;                            // sysrq_always_enabled始终都是打开的
    pr_info("sysrq always enabled.\n");

    return 1;
}

__setup("sysrq_always_enabled", sysrq_always_enabled_setup);    // 系统启动时自动执行

4、注册sysrq事件的回调函数:sysrq_register_handler

static inline void sysrq_register_handler(void)
{
    unsigned short key;
    int error;
    int i;

    // 首先检查是否实例化了_weak接口。
    for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) {
        key = platform_sysrq_reset_seq[i];
        if (key == KEY_RESERVED || key > KEY_MAX)
            break;

        sysrq_reset_seq[sysrq_reset_seq_len++] = key;
    }

    // DT构型优先于任何已经通过弱接口定义。
    sysrq_of_get_keyreset_config();

    // 注册input回调
    error = input_register_handler(&sysrq_handler);
    if (error)
        pr_err("Failed to register input handler, error %d", error);
    else
        sysrq_handler_registered = true;
}

sysrq产生kernel crash事件流程

在串口终端上,能直接将CommandKey写入/proc/sysrq-trigger文件流程
如:echo ‘c’ > sysrq-trigger 产生一个kernel crash
当执行命令之后,会调用proc写回调函数:write_sysrq_trigger

static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
                   size_t count, loff_t *ppos)
{
    if (count) {
        char c;

        if (get_user(c, buf))                // 从用户端获取传入的字符串
            return -EFAULT;
        __handle_sysrq(c, false);            // 调用处理函数
    }

    return count;
}

处理函数__handle_sysrq解析:

void __handle_sysrq(int key, bool check_mask)
{
    struct sysrq_key_op *op_p;
    int orig_log_level;
    int i;

    rcu_sysrq_start();
    rcu_read_lock();
    
    orig_log_level = console_loglevel;            // 使用默认等级#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */
    console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;    // 输出到终端
    printk(KERN_INFO "SysRq : ");

        op_p = __sysrq_get_key_op(key);            // 找到sysrq_key_table表中对应结构体
                -> i = sysrq_key_table_key2index(key);    // 通过传入的key值(例中为'c')转为sysrq_key_table表中索引值
                -> op_p = sysrq_key_table[i];       // 获取对应结构体(sysrq_key_table表在下个函数解析)(例中'c'对应为sysrq_crash_op)
        if (op_p) {
        if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
            printk("%s\n", op_p->action_msg);        
            console_loglevel = orig_log_level;
            op_p->handler(key);            // 执行结构体中的处理函数
        } else {
            printk("This sysrq operation is disabled.\n");
        }
    } else {
        ......
    }
    rcu_read_unlock();
    rcu_sysrq_end();
}

sysrq_key_table表包含36个sysrq_key_op结构体指针(对应传入key值为‘0’ — ‘9’,‘a’ — ‘z’)

struct sysrq_key_op {
        void (*handler)(int);        // 处理函数
        char *help_msg;            // 帮助信息
        char *action_msg;            // 相关动作信息
        int enable_mask;            // 使能掩码
};

static struct sysrq_key_op *sysrq_key_table[36] = {
    &sysrq_loglevel_op,     /* 0 */
    &sysrq_loglevel_op,     /* 1 */
    &sysrq_loglevel_op,     /* 2 */
    &sysrq_loglevel_op,     /* 3 */
    &sysrq_loglevel_op,     /* 4 */
    &sysrq_loglevel_op,     /* 5 */
    &sysrq_loglevel_op,     /* 6 */
    &sysrq_loglevel_op,     /* 7 */
    &sysrq_loglevel_op,     /* 8 */
    &sysrq_loglevel_op,     /* 9 */

    /*
     * a: Don't use for system provided sysrqs, it is handled specially on
     * sparc and will never arrive.
     */
    NULL,               /* a */
    &sysrq_reboot_op,       /* b */
    &sysrq_crash_op,        /* c & ibm_emac driver debug */
    &sysrq_showlocks_op,        /* d */
    &sysrq_term_op,         /* e */
    ......
    &sysrq_showstate_blocked_op,    /* w */
    NULL,               /* x */
    NULL,               /* y */
    &sysrq_ftrace_dump_op,      /* z */
};

例子中,用户层传入‘c’ 对应的结构体是sysrq_crash_op

// 触发一个系统crash的处理函数
static void sysrq_handle_crash(int key)
{
    char *killer = NULL;

    panic_on_oops = 1;      /* force panic */
    wmb();
    *killer = 1;
}
static struct sysrq_key_op sysrq_crash_op = {
    .handler    = sysrq_handle_crash,
    .help_msg   = "crash(c)",
    .action_msg = "Trigger a crash",
    .enable_mask    = SYSRQ_ENABLE_DUMP,
};

sysrq 整体框架图

在这里插入图片描述


sysrq 框架中添加自定义实例

diff --git a/linux-3.18.24.x/drivers/tty/sysrq.c b/linux-3.18.24.x/drivers/tty/sysrq.c
index 42bad18c6..a156551d3 100755
--- a/linux-3.18.24.x/drivers/tty/sysrq.c
+++ b/linux-3.18.24.x/drivers/tty/sysrq.c
@@ -408,6 +408,18 @@ static struct sysrq_key_op sysrq_unrt_op = {
        .enable_mask    = SYSRQ_ENABLE_RTNICE,
 };

+static void sysrq_handle_dwb(int key)
+{
+       console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
+       printk("sysrq_handle_dwb test ok. \n");
+}
+static struct sysrq_key_op sysrq_dwb_op = {
+       .handler        = sysrq_handle_dwb,
+       .help_msg       = "dwb test",
+       .action_msg     = "dwb",
+       .enable_mask    = SYSRQ_ENABLE_DUMP,
+};
+
 /* Key Operations table and lock */
 static DEFINE_SPINLOCK(sysrq_key_table_lock);

@@ -451,7 +463,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        &sysrq_showmem_op,              /* m */
        &sysrq_unrt_op,                 /* n */
        /* o: This will often be registered as 'Off' at init time */
-       NULL,                           /* o */
+       &sysrq_dwb_op,                          /* o */
        &sysrq_showregs_op,             /* p */
        &sysrq_show_timers_op,          /* q */
        &sysrq_unraw_op,                /* r */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/21588.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++控制台打飞机小游戏

我终于决定还是把这个放出来。 视频在这&#xff1a;https://v.youku.com/v_show/id_XNDQxMTQwNDA3Mg.html 具体信息主界面上都有写。 按空格暂停&#xff0c;建议暂停后再升级属性。 记录最高分的文件进行了加密。 有boss&#xff08;上面视频2分47秒&#xff09;。 挺好…

Oracle数据库中了locked1勒索病毒攻击后怎么办,什么是locked1勒索病毒

Oracle数据库是一种被集团企业广泛使用的关系型数据库管理系统&#xff0c;但是随着科学技术的不断发展&#xff0c;在现代互联网环境中数据库安全性成为了一个非常重要的问题。而其中主要的威胁就是勒索病毒攻击。一旦数据库被勒索病毒攻击入侵&#xff0c;许多重要的数据就会…

消息中间件概念

什么是消息队列 消息队列是消息中间件的一种实现方式。 什么是消息中间件&#xff1f; 将消息中间件需要理解一下什么是消息和中间件&#xff1f; 消息 消息是指软件对象之间进行交互作用和通讯利用的一种方式。 中间件 百度百科的介绍&#xff1a; ​ 中间件&#xff08;Mid…

gma 1.1.6 | 2.0.0a1 (2023.05.14) 更新日志

从现在开始&#xff0c;gma 开始同步更新 gma 2 的前期预览版&#xff0c;并与 gma 1 的正式版同步发布。 gma 1.1.6 更新日志 新增 1、添加 3组 新的指北针样式。 修复 1、【map】高分辨栅格数据集内存溢出问题。   添加高分辨率栅格数据集且进行强制数据缩放时 偶现内存…

node笔记_koa框架的路由

文章目录 ⭐前言⭐koa 原生路由写法⭐引入 koa-router&#x1f496; 安装koa-router&#x1f496; 动态读取路径文件作为路由 ⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文介绍koa框架的路由。 往期文章 node_windows环境变量配置 node_npm发布包 linux_配置no…

Vue 注册组件介绍

Vue组件的基本概念 Vue组件是一种可复用的Vue实例&#xff0c;用于封装可重用的HTML元素、JavaScript代码和CSS样式。它可以让开发者更好地组织和复用代码&#xff0c;使Web应用程序更加可维护和可扩展 Vue组件通常由三部分组成&#xff1a;模板&#xff08;template&#xf…

近期关于Transformer结构有潜力的改进方法总结

目录 0 引言1 Gated Linear Unit (GLU)1.1 思路 2 Gated Attention Unit (GAU)2.1 思路2.2 实验结论2.3 混合注意力 3 FlashAttention3.1 标准Attention的实现3.2 FlashAttention的实现针对目标1针对目标2 4 总结5 参考资料 0 引言 标准Transformer在最新的实际大模型中并没有…

代码随想录算法训练营day44 | 完全背包,518. 零钱兑换 II,377. 组合总和 Ⅳ

代码随想录算法训练营day44 | 完全背包&#xff0c;518. 零钱兑换 II&#xff0c;377. 组合总和 Ⅳ 完全背包完全背包问题概述例题遍历顺序分析 518. 零钱兑换 II解法一&#xff1a;动态规划 377. 组合总和 Ⅳ解法一&#xff1a;动态规划 总结 完全背包 教程视频&#xff1a;h…

Nginx + fastCGI 实现动态网页部署

简介 本文章主要介绍下&#xff0c;如何通过Nginx fastCGI来部署动态网页。 CGI介绍 在介绍fastCGI之前先介绍下CGI是什么。CGI : Common Gateway Interface&#xff0c;公共网关接口。在物理层面上是一段程序&#xff0c;运行在服务器上&#xff0c;提供同客户端HTML页面的…

了解这3大特性,再也不担心传输线问题了!

电阻是一个实实在在的物理元器件&#xff0c;通过欧姆定律我们可以知道&#xff0c;电压、电流和电阻三者之间的关系&#xff0c;UI*R。 我们通过一个具体的电路来分析这三者之间的具体关系&#xff0c;请看下面的一张最简单的电路图。这个电路图只有一个电源一个电阻和一些导…

MySQL---多表联合查询(下)(内连接查询、外连接查询、子查询(ALL/ANY/SOME/IN/EXISTS关键字)、自关联查询)

1. 内连接查询 数据准备&#xff1a; use mydb3;-- 创建部门表 create table if not exists dept3(deptno varchar(20) primary key , -- 部门号name varchar(20) -- 部门名字 );-- 创建员工表 create table if not exists emp3(eid varchar(20) primary key , -- 员工编号e…

尝试探索水下目标检测,基于yolov5轻量级系列模型n/s/m开发构建海底生物检测系统

其实&#xff0c;水下目标检测相关的项目早在之前就已经做了几个了&#xff0c;但是没有系统性地对比过&#xff0c;感兴趣的话可以先看下之前的文章&#xff0c;如下&#xff1a; 《基于自建数据集【海底生物检测】使用YOLOv5-v6.1/2版本构建目标检测模型超详细教程》 《基于…

AVL树(平衡二叉搜索树)

如果BST树插入的顺序是有序的&#xff0c;那么BST树就会退化成一个双链表结构&#xff0c;查询的速率就会很慢&#xff0c; 所以有了AVL树的意义。 AVL树的定义&#xff1a; 是具有下列性质的二叉搜索树 1、它的左子树和右子树都是AVL树 2、左子树和右子树的高度之差的绝对值…

办公智慧化风起云涌,华为MateBook X Pro 2023是最短距离

今年以来&#xff0c;我们几乎每个月&#xff0c;甚至每星期都可以看到大模型应用&#xff0c;在办公场景下推陈出新。 办公智慧化已成必然&#xff0c;大量智力工作正在被自动化。一个普遍共识是&#xff1a;AI能力范围之内的职业岌岌可危&#xff0c;AI 能力范围之外的职业欣…

瑞吉外卖 - 分页查询分类功能(12)

某马瑞吉外卖单体架构项目完整开发文档&#xff0c;基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成&#xff0c;有需要的胖友记得一键三连&#xff0c;关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料&#xff1a;https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

《Netty》从零开始学netty源码(五十八)之NioEventLoop.execute()

目录 NioEventLoop.execute()addTask()startThread()NioEventLoop.run()select()处理keys与执行任务processSelectedKeys()处理AbstractNioChannelselectAgain() runAllTasks()fetchFromScheduledTaskQueue()runAllTasksFrom()afterRunningAllTasks() 带截止时间的runAllTasks(…

由浅入深Netty入门案例

目录 1 概述1.1 Netty 是什么&#xff1f;1.2 Netty 的作者1.3 Netty 的地位1.4 Netty 的优势 2 Hello World2.1 目标2.2 服务器端2.3 客户端2.4 流程梳理2.5 提示 1 概述 1.1 Netty 是什么&#xff1f; Netty is an asynchronous event-driven network application framework…

免费可用 ChatGPT 网页版

前言 ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;美国OpenAI 研发的聊天机器人程序 &#xff0c;于2022年11月30日发布 。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过理解和学习人类的语言来…

在 Python 中执行逐元素加法

文章目录 Python 中的逐元素加法在 Python 中使用 zip() 函数执行逐元素加法在 Python 中使用 map() 函数执行逐元素加法在 Python 中使用 NumPy 执行逐元素加法 我们将通过示例介绍在 Python 中按元素添加两个列表的不同方法。 Python 中的逐元素加法 在 Python 中使用列表时…

最简单配置jenkins容器使用宿主机的docker方法

构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可 设置Jenkins容器使用宿主机Docker 设置宿主机docker.sock权限 chown root:root /var/run/docker.sock chmod orw /var/run/docker.sock 添加数据卷 v…