linux内核编译,linux自定义系统调用函数

目录

  • 资源下载
  • 环境介绍
  • 开始编译
  • 其他查询
  • 报错解决
    • No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'
    • Failed to generate BTF for vmlinux
    • /bin/sh: 1: zstd: not found
  • 自定义linux系统调用函数

资源下载

linux内核源码下载:https://cdn.kernel.org/pub/linux/kernel/
我下载的是:linux-5.11.1.tar.gz
linux源码在线看:https://elixir.bootlin.com/linux/v5.11/source

环境介绍

虚拟机:VMware® Workstation 16 Pro
操作系统:ubuntu-20.04
原内核版本:5.15.0-76-generic
编译后内核版本:5.11.1
虚拟机磁盘大小:80G以上

开始编译

文件准备:

sudo cp linux-5.11.1.tar.gz /usr/src/
cd /usr/src/
sudo gunzip linux-5.11.1.tar.gz 
sudo tar -xf linux-5.11.1.tar
cd linux-5.11.1

安装依赖:

sudo apt install make
sudo apt install gcc
sudo apt-get install ncurses-dev
sudo apt install bison
sudo apt install libgtk2.0-dev libglib2.0-dev libglade2-dev
sudo apt install flex
sudo apt install libssl-dev
sudo apt install libelf-dev

配置工具,二选一,根据需求对内核进行裁剪,生成.config文件:

sudo make menuconfig
sudo make gconfig

开始编译:

sudo make -j8

安装内核:

sudo make modules_install
sudo make
sudo make install
reboot	#重新载入内核,按 shift 进入高级选项,选择内核版本

其他查询

uname -r	#查询当前内核版本
rpm -qa kernel	#查询已安装内核版本列表,centos
dpkg --list | grep linux-image	#查询已安装内核版本列表,ubuntu

printk(KERN_ALERT "source=%d\n",source);#打印内核调试信息
dmesg | tail -20	#查询内核缓存,最后20条信息

#卸载内核版本
sudo apt-get remove --purge linux-image-5.11.0-27-generic
sudo yum remove linux-image-5.11.0-27-generic

报错解决

No rule to make target ‘debian/canonical-certs.pem’, needed by ‘certs/x509_certificate_list’

sudo vim .config
CONFIG_SYSTEM_TRUSTED_KEYS=""	#修改选项为空

Failed to generate BTF for vmlinux

sudo apt install dwarves

/bin/sh: 1: zstd: not found

sudo aptitude install zstd
sudo apt-get install libzstd-dev

自定义linux系统调用函数

1、在系统调用表中添加系统调用号:

sudo vim /usr/src/linux-5.11.1/arch/x86/entry/syscalls/syscall_64.tbl
#最后一行添加
535     64  chwtest                 sys_chwtest	

2、在系统调用头文件中添加声明:

sudo vim /usr/src/linux-5.11.1/include/linux/syscalls.h
#添加
asmlinkage long sys_chwtest(int, int);

3、定义系统调用入口
/linux-5.11.1/net/socket.c

INDIRECT_CALLABLE_DECLARE(int cc_chwtest(int, int));
SYSCALL_DEFINE2(chwtest, int, fd, int, backlog)
{
        printk(KERN_ALERT "socket.c,fd=%d,testnum=%d\n",fd,backlog);
        cc_chwtest(fd, backlog);
        return 0;
}

4、调用传输层自定义方法
/linux-5.11.1/net/ipv4/af_inet.c

int cc_chwtest(int fd, int testnum)
{
    printk(KERN_ALERT "af_inet,fd=%d,testnum=%d\n",fd,testnum);
    return 0;
}

/linux-5.11.1/include/net/inet_common.h

int cc_chwtest(int fd, int testnum)

//传输层接收入口
/linux-5.11.1/net/ipv4/tcp_ipv4.c

#include 
const struct tcphdr *th = tcp_hdr(skb);
const struct iphdr *ih = ip_hdr(skb);
const struct ethhdr *eh = eth_hdr(skb);

printk(KERN_ALERT "th->source=%d,th->dest=%d\n",th->source,th->dest);
printk(KERN_ALERT "ih->saddr=%d,ih->daddr=%d\n",ih->saddr,ih->daddr);
for(int index=0;index<6;index++)
{
    printk(KERN_ALERT "h_dest[%d]=%hx,h_source[%d]=%hx\n",index,eh->h_dest[index],index,eh->h_source[index]);
}
printk(KERN_ALERT "eh->h_proto=%d\n",eh->h_proto);

5、应用层调用系统自定义函数

通常,系统调用靠 C 库支持。用户程序通过包含标准头文件并和 C 库链接,就可以使用系统调用(或者调用库函数,再由库函数实际调用)。但这里只将系统调用添加到了内核中,并不能使用 glibc 库。而对此,Linux 本身提供了一个 syscall() 函数,用于直接对系统调用进行访问。将想要调用的系统调用的系统调用号和参数传入 syscall() 中即可使用此系统调用。

syscall(535123456);
//触发后使用dmesg 查询系统日志

你可能感兴趣的:(linux/嵌入式,linux,运维,服务器)