設計一個模塊,功能是列出系統中所有內核線程的程序名、PID號和進程狀態。


設計一個模塊,功能是列出系統中所有內核線程的程序名、PID號和進程狀態。主要步驟:

閱讀內核源代碼,了解進程描述符task_struct中與本實驗有關的成員項,以及訪問進程隊列的宏for_each_process

分析內核模塊實例,掌握內核模塊的主要構成;

閱讀Makefile文件,理解內核模塊編譯、加載過程;

以下是hello.c文件

#include <linux/sched.h>
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
//#define for_each_process(p)
static int hello_init(void)
{
        struct task_struct *p;
        printk(KERN_ALERT"名稱\t進程號\t狀態\t");
//      p=NULL;
        for_each_process(p)
        {
                printk(KERN_ALERT"%d\t%d\t%d\n",p->comm,p->pid, p->state);
        }
        return 0;
}
static void hello_exit(void)
{
        printk(KERN_ALERT "hello world exit\n");
}
module_init(hello_init);//加載函數
module_exit(hello_exit);                //卸載函數
MODULE_LICENSE("GPL");  //許可證申明
MODULE_DESCRIPTION("hello module");

MODULE_AUTHOR("liguangcai");

以下是Makefile文件:

ifneq ($(KERNELRELEASE),)
 obj-m:=readprocess.o
else
 KDIR:= /lib/modules/$(shell uname -r)/build
 PWD:= $(shell pwd)

default://注意,default前面最好不要有空格,剛開始做的時候前面加空格報錯了
 $(MAKE) -C $(KDIR) M=$(PWD) modules  
clean:://注意,前面最好不要有空格
 $(MAKE) -C $(KDIR) M=$(PWD) clean
endif://注意,前面最好不要有空格

編寫完上述兩個文件后回到這兩個文件所在的目錄鍵入命令: make

然后:

#insmod hello.ko

查看加載模塊是否成功:

 #dmesg

自此實驗完成!
 
 
實驗參考:

一、Linux的內核模塊

內核模塊是Linux內核向外部提供的一個插口,其全稱為動態可加載內核模塊(Loadable Kernel Module,LKM),簡稱模塊。Linux內核之所以提供模塊機制,是因為它本身是一個單內核(monolithic kernel)。單內核的最大優點是效率高,因為所有的內容都集成在一起,但其缺點是可擴展性和可維護性相對較差,模塊機制就是為了彌補這一缺陷。 

模塊是具有獨立功能的程序,它可以被單獨編譯,但不能獨立運行。它在運行時被鏈接到內核作為內核的一部分在內核空間運行,這與運行在用戶空間的進程是不同的。模塊通常由一組函數和數據結構組成,用來實現一種文件系統、一個驅動程序或其他內核上層的功能。

總之,模塊是一個為內核(從某種意義上來說,內核也是一個模塊)或其他內核模塊提供使用功能的代碼塊。

1.  利用內核模塊的動態裝載性的優點: 

將內核映象的尺寸保持在最小,並具有最大的靈活性;便於檢驗新的內核代碼,而不需重新編譯內核並重新引導。 

2.  內核模塊的缺點:

裝入的內核模塊和其他內核部分一樣,具有相同的訪問權限,因此,差的內核模塊會導致系統崩潰;為了使內核模塊訪問所有內核資源,內核必須維護符號表,並在裝入和卸載模塊時修改這些符號表;有些模塊要求利用其他模塊的功能,因此,內核要維護模塊之間的依賴性。內核必須能夠在卸載模塊時通知模塊,並且要釋放分配給模塊的內存和中斷等資源;內核版本和模塊版本的不兼容,也可能導致系統崩潰。

 相關操作說明:

a、必需模塊函數

加載函數    module_init(hello_init);  

卸載函數    module_exit(hello_exit);    

b、可選模塊函數

MODULE_LICENSE(“*******”);    許可證申明

MODULE_AUTHOR(“********”);    作者申明

MODELE_DESCRIPTION(“***”);    模塊描述

MODULE_VERSION(“V1.0”);       模塊版本

MODULE_ALIAS("*********");    模塊別名

c、加載內核模塊

載入模塊使用insmod命令:

#insmod hello.ko

卸載內核模塊使用rmmod命令:

#rmmod hello

d、查看加載模塊是否成功

   dmesg可以看到系統的內核模塊信息。

三、與本次試驗相關的內核代碼:

1.  進程控制塊的相關內容:

linux/sched.h文件中:

#define TASK_RUNNING 0

#define TASK_INTERRUPTIBLE 1

#define TASK_UNINTERRUPTIBLE 2

#define __TASK_STOPPED 4

#define __TASK_TRACED 8

#define EXIT_ZOMBIE 16

#define EXIT_DEAD 32

#define TASK_DEAD 64

#define TASK_WAKEKILL 128

#define TASK_WAKING 256

#define TASK_PARKED 512

struct task_struct {

volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */

struct list_head tasks;

struct mm_struct *mm;

pid_t pid;

pid_t tgid;

struct task_struct __rcu *real_parent; /* real parent process */

struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */

char comm[TASK_COMM_LEN]; /* executable name excluding path */

}

2.  for_each_process(p)宏:

宏for_each_process(p)的功能是掃描整個進程鏈表

#define for_each_process(p) \ for (p = &init_task ; (p = next_task(p)) != &init_task ; )

使用方法:

struct task_struct *p;

for_each_process(p){

//p指向的進程描述符進行操作

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM