[保姆级教程] 如何在 Linux Kernel (V5.17.7) 中添加一个系统调用(System call)

RISC-V系统调用中断处理机制与Linux内核实践 系统调用是用户态程序与内核交互的核心机制,其实现依赖于CPU架构的中断处理体系。以RISC-V架构为例,通过ecall指令触发硬件中断后,CPU自动切换特权级别并跳转到内核处理程序,这一过程涉及sepc、scause等关键寄存器的协同工作。理解系统调用原理对开发高性能系统软件至关重要,尤其在嵌入式设备和云计算场景中。本文以Linux 5.19.16内核为研究对象,结合GDB调试和MenuOS改造实践,详细剖析了从ecall指令触发到内核态处理返回的全链路过程,包括寄存器传参规则、上下文保存机制等RISC-V 阅读详情

        最近在学习 《linux Kernel Development》,本书用的linux kernel 是v2.6 版本的。看完”系统调用“一节后,想尝试添加一个系统调用,然后重编一个kernel。经过几个小时的尝试,实现了这个小功能,其中也遇到了不少坑,本文主要是记录分享下如何在Linux Kernel (V5.17.7) 中添加一个系统调用(System call)。

        编kernel之前需要注意:

  • 修改的kernel是目前最新的release 版本(V5.17.7), 书中v2.6版本的kernel太老了,gcc需要降到4.8版本,否则无法编过。 kernel 发布地址:https://www.kernel.org/
  • 需要选用大内存,多核的机器编kernel,否则会出现各种异常问题,而且编kernel 很费时间。15GB内存的机器,编不过kernel。换用100GB内存的机器就好了😅

    本文主要包含以下几点内容:

  1. 环境准备
  2. 修改kernel
  3. rebuild kernel 以及安装kernel
  4. 测试结果

1、环境准备

     我编kernel的机器是:Ubuntu 20.04.1 LTS,内存180GB,  cores: 88

1.1 更新系统的源

sudo apt update && sudo apt upgrade -y

1.2 安装编译kernel 需要的依赖

sudo apt install build-essential libncurses-dev libssl-dev libelf-dev bison flex -y

我这里用的vim,没有的话也需要安装:

sudo apt install vim -y

1.3 清除已经安装的packages

sudo apt clean && sudo apt autoremove -y

1.4 下载kernel code

wget -P ~/ https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.17.7.tar.xz
tar -xvf ~/linux-5.17.7.tar.xz -C ~/

2、修改kernel

2.1 检查你自己当前系统的kernel 版本

uname -r

5.11.0-36-generic

重新安装kernel之后,这个版本号会被修改。

2.2 切换到工作目录中,然后创建自己的系统调用

cd ~/linux-5.17.7/
mkdir hello

 2.3 创建自己的系统调用

vim hello/hello.c

 添加代码。

#include <linux/kernel.h>
#include <linux/syscalls.h>

SYSCALL_DEFINE0(hello)

{
    printk("hello_system_call.\n");
    return 0;
}

 2.4 为你的系统调用创建 Makefile

vim hello/Makefile

 添加下面内容:

obj-y := hello.o

 2.5 将你的系统调用添加到Kernel 的makefile中

vim Makefile

 搜索 core-y, 完成如下添加:

 2.6 将系统调用的相应函数原型添加到系统调用的头文件中

vim include/linux/syscalls.h

 添加:

asmlinkage long sys_hello(void);

2.7 在system_table 中为你的系统调用开辟一个新的系统调用号。

vim arch/x86/entry/syscalls/syscall_64.tbl

3、编译kernel 并安装

    前面的步骤都很简单,这一步可能会出现各种问题,而且很耗时。

3.1 创建你的.config

    这里一路默认设置就好。

make menuconfig

3.2 查询你的机器logicl cores 有多少个

nproc

3.3 编译安装你的kernel

make -j32
echo $?  // make 结束之后记得检查一下 状态
###if output is 0 then
sudo make modules_install -j32
echo $? 
sudo make install -j32

3.4 查看kernel 是否安装进去了

sudo update-grub
sudo reboot

4、测试结果

4.1 首先check 你的kernel 换好没

uname -r

4.2 编一个code 调用你的系统调用

  由于系统调用不像普通函数那样,需要通过sys_call 以及系统调用号才能实现系统调用。创建一个test.c

#include <linux/kernel.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define __NR_hello 451

long hello_syscall(void)
{
    return syscall(__NR_hello);
}
int main(int argc, char *argv[])
{
    long activity;
    activity = hello_syscall();
    if(activity < 0)
    {
        perror("Sorry, xxx. Your system call appears to have failed.");
    }
    else
    {
        printf("Congratulations, xxx! Your system call is functional. Run the command dmesg in the terminal and find out!\n");
    }
    return 0;
}

4.3 测试结果

gcc -o test test.c
./test
dmesg // 后面也能看到系统调用打印的信息

 Congratulations, xxx! Your system call is functional. Run the command dmesg in the terminal and find out!

《Linux内核完全注释》pdf v3.0 阅读详情

相关推荐

Linux没有蓝屏是真的吗?从Kernel Panic到Python模拟与故障排查

操作系统面对内核级致命错误时,需要一套清晰可靠的故障表达机制。Windows用蓝屏展示Bug Check信息,而Linux则通过内核日志输出Panic/Oops详情。理解这两者的差异,关键在于看清Linux继承了Unix的文本化诊断哲学:它把崩溃现场写入dmesg、journalctl等日志,让运维人员能远程回溯甚至定位到具体驱动函数。这种机制在服务器、虚拟化等场景下比图形界面更高效。实际工程中,无论是内核卡死、系统服务崩溃,还是虚拟机安装Linux时宿主蓝屏,都有对应的排查思路和工具链。本文用一个Pyth

weixin_34327761的博客 490

向linux内核增加新的系统调用,为linux内核添加新的系统调用

为linux内核添加新的系统调用作者:李志勇更多精彩:更多精彩:开发平台:x86 ubuntu目标平台:S3C6410linux3.4.4一、 打开内核源码目录下arch/arm/kernel/calls.S文件,在389行添加:/*378 */CALL(sys_my_syscall)378是新添加的系统调用的系统调用号,sys_my_syscall是该系调用的名字二、打开内核源码目录下ar...

weixin_33701632的博客 622

64/32位Linux系统的差异(地址空间布局,系统调用)对比分析

映射地址:可以看到,对应的地址0x7fd9b8c00000是PSE页,映射了10M,是PMD级的大页映射,也就是2M页面的映射。连续影射了5个PMD大页。这些大页的分配是在mmap后,执行memset(addr, 0x5a, ...)时通过page fault流程进行分配的,对应执行hugetlb_fault的执行流程。

tugouxp的专栏 3224

Linux的syscall源码,添加一个syscall

我们之前学习的各种内核态与用户态数据交换时都需要系统调用,只是我们没感受到,而这次我们向内核添加一个自己的syscall,来感受下这一功能的特殊魅力。下面说明在Kernel源码里如何添加一个syscall:1.在include/linux/syscalls.h文件里最后一行的#endif前添加自己的系统调用函数声明,内容如下:asmlinkage long sys_slam(void);2.在ke...

weixin_39664456的博客 584

【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】007 - 一号内核线程 kernel_init线程 工作流程分析

【鸿蒙OH-v5.0源码分析之 Linux Kernel 部分】007 - 一号内核线程 kernel_init线程 工作流程分析

|~~~热爱生活、努力学习的小伙汁~~~| 882

Mac上Office合法安装与激活全指南:2021/2024/M365区别解析

Office是微软办公套件的核心产品,其在macOS平台的部署逻辑与Windows截然不同——不依赖传统密钥激活,而是基于Microsoft账户与设备标识的云端绑定机制。理解这一原理,是解决‘无法验证开发者’‘打不开’‘功能受限’等常见问题的前提。Office 2021代表永久许可模型,Office 2024 LTSC面向企业离线场景,Microsoft 365则是持续订阅服务,三者在授权验证方式、更新策略与系统兼容性上存在本质差异。实际应用中,需结合macOS版本、芯片架构(Intel/Apple Sil

weixin_33491377的博客 1115

在Linux内核中添加系统调用,并编译内核

1 环境准备 运行系统:vmware下安装的ubuntu10.10 32bit桌面版。 编译内核版本: linux-2.6.32.63 内核目录: /home/wanchouchou/linuxKernel/linux-2.6.32.63 为了方便,使用chmod 777 -Rlinux-2.6.32.63/ 将所有的内核文件都改为全权限,这样就可以在非r...

weixin_30644369的博客 254

运算放大器基础1——用作比较器

运算放大器,运放,在电路设计中非常常见。在图2中,当前状态下,开关切换到0V,“正相输入”和“负相输入”都是接地,运放两个输入端电压相同。最后,调节可变电阻,使其两端电压大于3.37V,比如3.43V,作为运放正相输入,由于电压大于反相输入,LED点亮(运放输出为5V)。其次,调节可变电阻,使其两端电压小于3.37V,比如2.09V,作为运放正相输入,由于电压小于反相输入,LED不点亮。好,现在我们将0.1V电源换个方向,这样实际“正相输入”的是-0.1V,比“负相输入”的电压要低,看看输出是什么?

m0_60069998的博客 6122

【Linux内核学习】 如何添加一个系统调用

总的来说, 系统调用是为了应用程序的接口的各种库在不同平台上能够共用的一种有效的机制,各种库在不同平台上提供的接口都是一致的,但是在各种系统或者平台上,这些接口的实现可能是不一样的,即,实现这些接口的系统调用可能不一样,有的可能实现成一个系统调用,也可能调用多个系统调用来实现。执行系统调用后,通过异常中断,陷入内核,传递系统调用号以及参数(正确的),执行正确的系统调用函数,并把返回值带回用户空间。

HoshinoGenLIAO的博客 562

Ubuntu22.04 apt 安装 ROS1 ROS Noetic Ninjemys

ubuntu 22.04 apt-get 安装 ros1 ros Noetic 最新版

autolabor的博客 5万+

32位MIPS流水线CPU设计

32位MIPS流水线CPU设计(vivado)

m0_51320209的博客 3199

linux 添加新的系统调用,如何在Linux中添加新的系统调用

Linux用来实现系统调用异常的实际指令是:Int ?$0x80这一指令使用中断/异常向量号128(即16进制的80)将控制权转移给内核。为达到在使用系统调用时不必用机器指令编程,在标准的C语言库中为每一系统调用提供了一段短的子程序,完成机器代码的编程工作。事实上,机器代码段非常简短。它所要做的工作只是将送给系统调用的参数加载到CPU寄存器中,接着执行int ?$0x80指令。然后运行系统调用,系...

weixin_32204175的博客 851

Flotherm XT学习历程

大家好,通过半年的热仿真软件学习使用,最终发现最好用,最好上手的软件就是Flotherm XT,对新手非常友好,但由于软件近几年才发布,网上教程非常少,后面我将在这里持续分析软件使用心得,和大家一起学习。

xiaoredred的博客 6255

RISC-V系统调用机制与MenuOS移植实践

系统调用是操作系统为用户程序提供服务的核心机制,涉及处理器特权级切换和上下文保存等关键技术。在RISC-V架构中,通过ecall指令触发系统调用,配合stvec、sepc等CSR寄存器完成异常处理流程。本文以MenuOS移植为例,详解RISC-V系统调用实现原理,包括工具链准备、源码修改、Makefile适配等实践步骤,并通过GDB调试分析handle_exception和sys_write等关键流程。实验环境搭建涉及RISC-V交叉编译工具链和QEMU模拟器,适合想深入了解RISC-V系统编程和内核机制的

weixin_33985679的博客 750

LeRobot — 基于 PyTorch 的真实世界机器人学习框架(一)- 核心框架模块解析

LeRobot 是一个开源的机器人学习框架,由 Hugging Face 开发,旨在降低机器人学的准入门槛。该框架提供完整的机器学习流程支持,包括数据采集、训练、评估和部署。核心模块涵盖数据集标准化、策略算法、硬件抽象和强化学习组件,采用模块化设计实现灵活扩展。通过集成 Hugging Face Hub,用户可以轻松共享数据集和预训练模型。LeRobot 特别注重真实世界的机器人应用,支持多种前沿算法如模仿学习、视觉语言动作模型等,并提供统一的硬件接口和仿真环境适配。

熊猫小妖的AI世界 170

131、高通骁龙影像平台总览:Spectra ISP 各代架构演进与特性对比

摘要:本文深入分析了高通骁龙Spectra ISP从250到780代的架构演进与技术痛点,揭示了各代关键改进与隐藏问题。重点剖析了双ISP带宽分配、AI ISP黑盒决策、温度控制等实战问题,并给出具体解决方案(如寄存器配置、QoS调整等)。文章强调工程师需平衡带宽、功耗与画质的三角关系,建议调试时先关闭AI模块建立基线,关注统计引擎配置,并建立温度监控机制。最后指出理解架构局限比追求完美设计更重要,需要针对不同场景找到合适的妥协方案。(148字)

sundong_81的博客 205

【优麒麟】编译linux kernel + 增加系统调用 + 编写批处理脚本

hust操作系统实验一 —— linux内核编译,增加系统调用,并编写批处理脚本程序。处理了多种报错。

m0_54129327的博客 3259

混响效果的编程实现:Schroeder混响模型与Moorer型混响

Schroeder混响模型是由Manfred R. Schroeder在1962年提出的,它基于一系列串联的反射器(Allpass Comb Filters)和并联的反射器(Feedback Comb Filters)构成。Schroeder混响模型是由Manfred R. Schroeder在1962年提出的,它基于一系列串联的反射器(Allpass Comb Filters)和并联的反射器(Feedback Comb Filters)构成。通过调整各个反射器和全通滤波器的参数,可以实现不同的混响效果。

2301_79326857的博客 1081

Linux5.0系统调用过程分析实验

学号085 原创作品转载请注明出处 本实验来源 https://github.com/mengning/linuxkernel/ 实验简介 本实验要求举例跟踪分析Linux内核5.0系统调用处理过程,编译内核5.0,选择系统调用号后两位与您的学号后两位相同的系统调用进行跟踪分析,给出相关关键源代码及实验截图,仔细分析系统调用、保护现场与恢复现场、系统调用号及参数传递过程,阐明自己对系统调用工作机...

weixin_42956878的博客 519

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Linux 进程间通信之 System V 共享内存:IPC 的原理与实战

在 Linux IPC 体系中,System V 共享内存是速度最快的进程间通信方式。与管道、命名管道需要通过内核缓冲区中转数据不同,共享内存直接将一块物理内存映射到多个进程的虚拟地址空间,进程间数据传递无需内核参与,仅需用户态的内存拷贝,效率远超其他 IPC 方式。本文将从原理、API、实战、内核管理四个维度,全面解析 System V 共享内存的底层逻辑与使用技巧。

会当凌绝顶,一览众山小 1524

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

LeetCode 118「杨辉三角」题解:逐行模拟生成算法与多语言实现

> 本文以 doocs/leetcode 开源仓库中 [118. 杨辉三角](https://link.gitcode.com/i/c559dce6c734b7c44d315f9366133932) 的题解文档为主体,系统讲解「杨辉三角」的递推定义、逐行模拟的生成思路与复杂度分析,并完整给出 Python3、Java、C++、Go、TypeScript、Rust、JavaScript、C# 八种语

gitblog_00309的博客 425

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

扩展—Linux System V IPC理论

本文介绍了如何利用设计模式封装Linux SystemV IPC机制,使进程间通信更加优雅易用。主要内容包括: 使用建造者模式封装信号量: 将信号量的创建、初始化和P/V操作封装成类 提供链式调用的接口简化使用 自动管理生命周期,防止资源泄漏 使用责任链模式扩展消息队列: 将消息处理流程拆分为独立的处理节点(格式化、保存、备份) 各节点可自由组合和开关,提高扩展性 实现了解耦和开闭原则 结合实践案例: 信号量实现父子进程同步打印 消息队列实现客户端-服务端通信 处理消息的日志记录和自动备份 这种将系统编程与

我的博客 230

Linux系统篇25——通信(三):System V 共享内存:从页表映射到 shmget/shmat 一文搞懂

共享内存 = 同一块物理内存,被映射到多个进程的虚拟地址空间;进程之间不再经过内核拷贝即可交换数据。但它的代价是"不带同步互斥",必须自己配信号量/管道来控制访问顺序。那篇把 IPC 全家福摆过一遍,其中对共享内存的定位是:"把同一块物理内存映射到多个进程,大家直接读写,零拷贝、性能最高。但它不负责同步,必须配信号量使用。" 本篇就是把那一句"零拷贝"背后的页表映射原理和API 实战补齐。

2502_94387000的博客 901

从Linux 0.11源码剖析信号量实现:哈工大Lab5系统调用改造指南

本文深入解析Linux 0.11信号量实现机制,提供哈工大Lab5系统调用改造的实战指南。从信号量的理论基础到内核代码修改,详细介绍了如何添加sem_open、sem_wait等系统调用,并通过生产者-消费者问题验证实现正确性。适合操作系统学习者深入理解进程同步机制。

o1p2q3r的博客 484

P2v Linux 输入密码弹出,P2V后LINUX系统开机处理方法

P2V后LINUX 处理/boot/sh-3.2# mkinitrd -v -f initrd-2.6.18-164.el5.img $(uname -r)要打包的内核文件名 内核版本号##更新当前虚拟机的内核;#如果修复光盘与系统不一至的情况:$(uname -r)这里直接敲虚拟机的内核版本号;问题集:开机出现“Error loading operating system”的提示信息,...

weixin_36403165的博客 621

Linux系统调用与futex机制深度解析

系统调用是操作系统为用户程序提供服务的核心接口,通过特权级切换实现用户态与内核态的安全交互。现代Linux采用syscall指令替代传统软中断,配合MSR寄存器配置实现纳秒级切换。在同步机制方面,futex通过用户态原子操作与内核态等待队列的混合设计,大幅降低线程同步开销。本文深入剖析系统调用初始化流程、参数传递规则以及futex的四种基本操作,结合x86_64和ARM架构差异,揭示Linux如何平衡性能与安全性。通过实际测试数据展示优化效果,为高并发编程和性能调优提供实践指导。

weixin_33985507的博客 322
上一篇: Linux kernel 分析之一:内核镜像/映像
下一篇: 初识ARM处理器
土豆西瓜大芝麻
博客等级 码龄18年 1189粉丝 238原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值