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
sudo vim .config
CONFIG_SYSTEM_TRUSTED_KEYS="" #修改选项为空
sudo apt install dwarves
sudo aptitude install zstd
sudo apt-get install libzstd-dev
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(535,123,456);
//触发后使用dmesg 查询系统日志