日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

liunx(3)-内核模块编写与系统调用

發(fā)布時(shí)間:2025/6/17 windows 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 liunx(3)-内核模块编写与系统调用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 問(wèn)題
    • 運(yùn)行環(huán)境
    • 程序組成
    • 實(shí)現(xiàn)思路
    • helllo.c
    • Makefile
    • main.c
    • 程序運(yùn)行


問(wèn)題

??????在Linux內(nèi)核中增加一個(gè)系統(tǒng)調(diào)用,并編寫(xiě)對(duì)應(yīng)的linux應(yīng)用程序。利用該系統(tǒng)調(diào)用能夠遍歷系統(tǒng)當(dāng)前所有進(jìn)程的任務(wù)描述符,并按進(jìn)程父子關(guān)系將這些描述符所對(duì)應(yīng)的進(jìn)程id顯示出來(lái)。


運(yùn)行環(huán)境

??????Ubuntu-20.04 64位虛擬機(jī)

程序組成

??????1,采用hello.c實(shí)現(xiàn)新的系統(tǒng)調(diào)用的函數(shù) ,按照內(nèi)核模塊編寫(xiě)的規(guī)范來(lái)編寫(xiě)程序(包含有兩部分:1,修改系統(tǒng)調(diào)用表;2,編寫(xiě)自己的系統(tǒng)調(diào)用服務(wù)程序)
??????2,main.c 用來(lái)進(jìn)行調(diào)用所編寫(xiě)的中斷例程

實(shí)現(xiàn)思路

??????因?yàn)橹傲私膺^(guò)匯編的中斷向量表,有過(guò)一定的實(shí)踐,所以直接采用修改linux系統(tǒng)調(diào)用表的方法。

1,如何在系統(tǒng)調(diào)用表中添加新的表項(xiàng)?
??????先找到系統(tǒng)調(diào)用表的入口地址,由于現(xiàn)在的linux系統(tǒng)會(huì)對(duì)給表做一個(gè)安全的保護(hù),不讓用戶(hù)輕易的修改系統(tǒng)調(diào)用表,所以需要去掉系統(tǒng)的保護(hù)之后,才能將我們自己編寫(xiě)的程序地址加載到系統(tǒng)調(diào)用表中,接下來(lái)才能被調(diào)用。

??????a,查找系統(tǒng)調(diào)用表地址 sudo cat /proc/kallsyms | grep sys_call_table 演示如下:

cedric@ubuntu:~/Desktop/C$ sudo cat /proc/kallsyms | grep sys_call_table ffffffffb7400280 R x32_sys_call_table ffffffffb74013a0 R sys_call_table ffffffffb74023e0 R ia32_sys_call_table

??????其中中間的地址ffffffffb74013a0是我們后面會(huì)采用到的。注意:這個(gè)地址并非一成不變的,特別的,每次開(kāi)機(jī)都需要執(zhí)行該命令獲得新的系統(tǒng)調(diào)用表的地址。
??????b,需要修改cr0控制寄存器的第16位以便于用來(lái)寫(xiě)系統(tǒng)調(diào)用表,將該位清0,禁用系統(tǒng)對(duì)調(diào)用表的寫(xiě)保護(hù)。在此采用匯編語(yǔ)言來(lái)實(shí)現(xiàn)。注意:在使用內(nèi)嵌匯編時(shí),在linux下需要采用AT&T的匯編語(yǔ)法,并且在對(duì)寄存器操作時(shí)應(yīng)該禁用中斷響應(yīng),防止出錯(cuò)。禁用寫(xiě)保護(hù)的匯編代碼如下:

asm volatile("cli;" //禁止中斷"push %rax;""movq %cr0,%rax;""and $0xfffffffffffeffff,%rax;" //第16位置0,禁用寫(xiě)保護(hù)"movq %rax,%cr0;""popq %rax;"//"sti;");

??????c,修改系統(tǒng)調(diào)用表項(xiàng),將其替換為自己編寫(xiě)的程序。首先將得到的系統(tǒng)調(diào)用表地址保存到變量SYS_CALL_TABLE_ADDRESS中(每次開(kāi)機(jī)都要進(jìn)行修改),然后將系統(tǒng)調(diào)用表223號(hào)表項(xiàng)內(nèi)容保存起來(lái),禁用系統(tǒng)的寫(xiě)保護(hù),將我們編寫(xiě)的函數(shù)sys_mycall地址替換223號(hào)表項(xiàng),恢復(fù)系統(tǒng)的寫(xiě)保護(hù),整個(gè)替換工作就此結(jié)束。代碼如下:

sys_call_table_my=(unsigned long*)(SYS_CALL_TABLE_ADDRESS); //初始化全局變量saveAddress=sys_call_table_my[NUM]; //保存223號(hào)表項(xiàng)clear_cr0();sys_call_table_my[NUM]=(unsigned long) &sys_mycall; //設(shè)置223號(hào)表項(xiàng)為我們自己的函數(shù)restore_cr0();

2,實(shí)現(xiàn)具體想要的功能,將所有進(jìn)程按照父子關(guān)系進(jìn)行顯示。
??????采用list_for_each函數(shù),從init_task的地址開(kāi)始遞歸訪(fǎng)問(wèn)即可,代碼如下:

static void getTasks(struct task_struct* root) {struct task_struct* p;struct list_head* list;list_for_each(list,&root->children) {p = list_entry(list,struct task_struct,sibling);printk("parent: id and name: %d %s myself: id and name: %d %s\n",p->parent->pid,p->parent->comm,p->pid,p->comm);getTasks(p);} }

helllo.c

??????這里需要注意一下內(nèi)核模塊的編寫(xiě)規(guī)范,包括模塊憑證,入口和退出函數(shù),以及printk函數(shù)的使用。

#include <linux/init.h> #include <linux/module.h> #include <linux/sched.h> //定義task_struct #include <linux/list.h> //定義list_head #include <linux/init_task.h> //定義init_task MODULE_LICENSE("Dual BSD/GPL");#define SYS_CALL_TABLE_ADDRESS 0xffffffff87a013a0 //本電腦sys_call_table對(duì)應(yīng)的地址 #define NUM 223static unsigned long saveAddress;//保存223號(hào)表項(xiàng)的入口地址 unsigned long* sys_call_table_my=0;//用來(lái)作為系統(tǒng)調(diào)用表的首地址 static int clear_cr0(void)//AT&T 64位匯編 {asm volatile("cli;" //禁止中斷"push %rax;""movq %cr0,%rax;""and $0xfffffffffffeffff,%rax;" //第16位置0,禁用寫(xiě)保護(hù)"movq %rax,%cr0;""popq %rax;"//"sti;");printk(KERN_INFO " Hello World enter\n");return 0; }static void restore_cr0(void) {asm volatile(//"cli;""pushq %rax;""movq %cr0,%rax;""or $0x0000000000010000,%rax;""movq %rax,%cr0;""popq %rax;""sti;" //恢復(fù)中斷);printk(KERN_INFO " Cruel World exit\n"); }static void getTasks(struct task_struct* root) {struct task_struct* p;struct list_head* list;list_for_each(list,&root->children) {p = list_entry(list,struct task_struct,sibling);printk("parent: id and name: %d %s myself: id and name: %d %s\n",p->parent->pid,p->parent->comm,p->pid,p->comm);getTasks(p);} }static int sys_mycall(void)//測(cè)試自己的系統(tǒng)調(diào)用 {printk(KERN_INFO"The pids will be show...: \n");getTasks(&init_task);return current->pid; }static int call_init(void) {sys_call_table_my=(unsigned long*)(SYS_CALL_TABLE_ADDRESS); //初始化全局變量printk(KERN_INFO"call_init......\n");saveAddress=sys_call_table_my[NUM]; //保存223號(hào)表項(xiàng)clear_cr0();sys_call_table_my[NUM]=(unsigned long) &sys_mycall; //設(shè)置223號(hào)表項(xiàng)為我們自己的函數(shù)restore_cr0();return 0; }static void call_exit(void) {printk(KERN_INFO"call_exit......\n");clear_cr0();sys_call_table_my[NUM]=saveAddress; //恢復(fù)223號(hào)表項(xiàng)原有內(nèi)容restore_cr0(); }module_init(call_init); module_exit(call_exit);MODULE_AUTHOR("cedric");

Makefile

??????這是一個(gè)可用的Makefile文件,文件名就是Makefile,不需要后綴名。它對(duì)hello.c程序進(jìn)行編譯。

ifneq ($(KERNELRELEASE),) # call from kernel build systemobj-m := hello.o elseKERNELDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd) default:make -C $(KERNELDIR) M=$(PWD) modules endif

main.c

??????它僅用來(lái)調(diào)用新的223號(hào)中斷程序,測(cè)試最終結(jié)果。

#include<unistd.h> #include<sys/syscall.h> #include<stdio.h>int main() {int pid=syscall(223); //在此調(diào)用223號(hào)中斷例程。printf("The current pid is: %d\n",pid);return 0; }

程序運(yùn)行

1,采用 sudo cat /proc/kallsyms | grep sys_call_table 命令獲取當(dāng)前電腦的系統(tǒng)調(diào)用表地址。
2,修改hello.c 中的對(duì)應(yīng)語(yǔ)句,如下:
#define SYS_CALL_TABLE_ADDRESS 0xffffffff87a013a0
3,進(jìn)入到root模式下make: sudo su + make
4,加載內(nèi)核模塊 hello.ko: insmod hello.ko
5,編譯main.c: gcc –o main main.c
6,通過(guò)main調(diào)用223號(hào)服務(wù)例程: ./main
7,在系統(tǒng)日志中查看輸出結(jié)果: cat /var/log/syslog
8,卸載內(nèi)核模塊: rmmod hello

總結(jié)

以上是生活随笔為你收集整理的liunx(3)-内核模块编写与系统调用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。