Kernel Module
V1.1
email: mesmerli@hotmail.com
Add a module into Linux building system
什麼是 Kernel Module
在不需要重新編譯 Linux 核心的狀況下,藉由 Kernel Module,可以擴充 Liunx 的核心功能。
通常用來擴充核心的驅動程式,並使用動態載入的方式載入核心。
Hello Kernel Module 實驗
透過最簡單的 Kernel Module 了解如何編譯執行 Kernel Module
並藉由 printk 的輸出字串,了解 Kernel Module 載入與移除時,哪些函數會被核心呼叫。
Hello Kernel Module 實驗步驟
Host 端
- 建構 Hello World Module
- 進入 HelloWorldModule 目錄
- make -f Makefile_Cross
Taget 端
- 使用 NFS 的方式,mount host 端的目錄,以存取剛剛建立的 Kernel Module。
- mount 192.168.0.200:/usr/src/creator/nfs /mnt
- 安裝 Kernel Module
- insmod HelloWorldModule_Cross.o
Makefile
CC=gcc
CFLAGS = -O2 -DMODULE -D__KERNEL__ -Wall
-I/usr/src/linux-2.4/include
HelloWorldModule.o: HelloWorldModule.c
$(CC) $(CFLAGS) -c HelloWorldModule.c
install:
/sbin/insmod HelloWorldModule.o
remove:
/sbin/rmmod HelloWorldModule
clean:
rm -f HelloWorldModule.o
message:
cat /var/log/messages
Makefile_Cross
CC=arm-linux-gcc
CFLAGS = -O2 -DMODULE -D__KERNEL__ -Wall
-I/usr/src/creator/s3c2410/linux/include
HelloWorldModule_Cross.o: HelloWorldModule.c
$(CC) $(CFLAGS) -c HelloWorldModule.c -o HelloWorldModule_Cross.o
install:
/sbin/insmod HelloWorldModule_Cross.o
remove:
/sbin/rmmod HelloWorldModule_Cross
clean:
rm -f HelloWorldModule_Cross.o
message:
cat /var/log/messages
HelloWordModule.c
#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
printk("Hello World!n");
return 0;
}
void cleanup_module(void)
{
printk("Hello World Module was removed!");
}
MODULE_LICENSE("GPL");
Export Symbol 實驗
安裝兩支 Kernel Module,第二支程式呼叫第一支程式開放之 Symbol。
Export Symbol 實驗步驟
Host 端
- 建構 Kernel Module
- 進入 ExportSymbol 目錄
- make -f Makefile_Cross
Taget 端
- 使用 NFS 的方式,mount host 端的目錄,以存取剛剛建立的 Kernel Module。
- mount 192.168.0.200:/usr/src/creator/nfs /mnt
- 安裝 Kernel Module
- insmod baseModule_Cross.o
- insmod topModule_Cross.o
Export Symbol 實驗步驟
Host 端
- 建構 Kernel Module
- 進入 ExportSymbol 目錄
- make -f Makefile_Cross
Taget 端
- 使用 NFS 的方式,mount host 端的目錄,以存取剛剛建立的 Kernel Module。
- mount 192.168.0.200:/usr/src/creator/nfs /mnt
- 安裝 Kernel Module
- insmod baseModule_Cross.o
- insmod topModule_Cross.o
baseModule.c
int baseShowMessage(void);
EXPORT_SYMBOL(baseShowMessage);
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
int baseShowMessage()
{
printk("Hello LinuxKernelModule EXPORT_SYMBOL!");
return 0;
}
int init_module(void)
{
printk("n--- Base Module install ok! ---n");
return 0;
}
void cleanup_module(void)
{
printk("n--- Base Module uninstall ok! ---n");
}
MODULE_LICENSE("GPL");
topModile.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
extern int baseShowMessage(void);
int init_module(void)
{
baseShowMessage();
printk("n--- Top Module install ok! ---n");
return 0;
}
void cleanup_module(void)
{
printk("n--- Top Module uninstall ok! ---n");
}
MODULE_LICENSE("GPL");
Pass Parameter 實驗
在 insmod 指令列上傳遞參數給 Kernel Module。
Pass Parameter 實驗步驟
Host 端
- 建構 Kernel Module
- 進入 PassParameter 目錄
- make -f Makefile_Cross
Taget 端
- 使用 NFS 的方式,mount host 端的目錄,以存取剛剛建立的 Kernel Module。
- mount 192.168.0.200:/usr/src/creator/nfs /mnt
- 安裝 Kernel Module
- insmod PassParameter_Cross.o
PassParameter.c
#include <linux/module.h>
#include <linux/kernel.h>
static int module_int = 100;
static char *module_string = "Linux Kernel Module";
MODULE_PARM(module_int,"i");
MODULE_PARM(module_string,"s");
int init_module(void)
{
printk("My Linux Kernel Module n");
printk("module_int = %dn",module_int);
printk("module_string = %sn",module_string);
return 0;
}
void cleanup_module(void)
{
printk("My Linux Kernel Module was removed!");
}
MODULE_LICENSE("GPL");
Proc 檔案系統的虛擬檔案
Kenel Module 可以透過 PROC 檔案系統傳遞系統資訊。
SimpleProc 實驗步驟
Host 端
- 建構 Kernel Module
- 進入 SimpleProc 目錄
- make -f Makefile_Cross
Taget 端
- 使用 NFS 的方式,mount host 端的目錄,以存取剛剛建立的 Kernel Module。
- mount 192.168.0.200:/usr/src/creator/nfs /mnt
- 安裝 Kernel Module
- insmod SimpleProc_Cross.o
- 讀取系統資訊
- cat /proc/simpleProc
SimpleProc.c
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
static struct proc_dir_entry *proc_mtd;
static char ProcBuffer[50000];
static char Temp1[1000];
extern int baseCount;
static int WritingLength;
static int procfile_read(char *buffer,char **buffer_location,off_t offset,int buffer_length,int zero)
{
int ReturnLength;
if(offset >0) return 0;
WritingLength=0;
sprintf(Temp1,"baseCount=%dx0Dx0A",baseCount++);
if(WritingLength+strlen(Temp1) < 50000)
{
memcpy(&ProcBuffer[WritingLength],Temp1,strlen(Temp1));
WritingLength+=strlen(Temp1);
}
*buffer_location = ProcBuffer;
ReturnLength=WritingLength;
WritingLength=0;
return ReturnLength;
}
int init_module(void)
{
if ((proc_mtd = create_proc_entry("simpleProc", 0, 0 )))
proc_mtd->read_proc = procfile_read;
printk("SimpleProc: SimpleProc install ok! n");
return 0;
}
void cleanup_module(void)
{
baseCount=0;
if (proc_mtd)remove_proc_entry( "simpleProc", 0);
printk("SimpleProc uninstall successful! n");
}
MODULE_LICENSE("GPL");
SimpleProcRW 實驗步驟
Host 端
- 建構 Kernel Module
- 進入 SimpleProc 目錄
- make -f Makefile_Cross
Taget 端
- 使用 NFS 的方式,mount host 端的目錄,以存取剛剛建立的 Kernel Module。
- mount 192.168.0.200:/usr/src/creator/nfs /mnt
- 安裝 Kernel Module
- insmod SimpleProcRW_Cross.o
- 讀寫系統資訊
- cat /proc/simpleProcRW
- echo ABCDEFG > /proc/simpleProcRW
- cat /proc/simpleProcRW
- 進入 SimpleProc 目錄
- make -f Makefile_Cross
- mount 192.168.0.200:/usr/src/creator/nfs /mnt
- insmod SimpleProcRW_Cross.o
- cat /proc/simpleProcRW
- echo ABCDEFG > /proc/simpleProcRW
- cat /proc/simpleProcRW
SimpleProcRW.c
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/tcp.h>
#include <linux/ip.h>
#include <linux/proc_fs.h>
#include <net/ip.h>
#include <asm/uaccess.h>
static struct proc_dir_entry *proc_mtd;
static char ProcBuffer[50000];
static char Temp1[1000];
extern int baseCount;
static int WritingLength;
static int procfile_read(char *buffer,char **buffer_location,off_t offset,int buffer_length,int zero)
{
int ReturnLength;
if(offset >0) return 0;
sprintf(Temp1,"baseCount=%dx0Dx0A",baseCount++);
if(WritingLength+strlen(Temp1) < 50000)
{
memcpy(&ProcBuffer[WritingLength],Temp1,strlen(Temp1));
WritingLength+=strlen(Temp1);
}
*buffer_location = ProcBuffer;
ReturnLength=WritingLength;
WritingLength=0;
return ReturnLength;
}
static int procfile_write(struct file *file, const char *buffer, unsigned long count,
void *data)
{
WritingLength = count ;
if( WritingLength > 50000 ) WritingLength =50000;
if ( copy_from_user(ProcBuffer, buffer, WritingLength) )
{
return -EFAULT;
}
return WritingLength;
}
int init_module(void)
{
if ((proc_mtd = create_proc_entry("simpleProcRW", 0, 0 )))
{
proc_mtd->read_proc = procfile_read;
proc_mtd->write_proc = procfile_write;
}
printk("SimpleProc: SimpleProc install ok! n");
return 0;
}
void cleanup_module(void)
{
baseCount=0;
if (proc_mtd)remove_proc_entry( "simpleProcRW", 0);
printk("SimpleProc uninstall successful! n");
}
MODULE_LICENSE("GPL");
以應用程式存取 Proc 檔案系統
ShowProc.c
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <curses.h>
#include <stdlib.h>
char buf[2048];
FILE *fp,*fplogfile;
void handler()
{
}
int main( int argc, char *argv[] )
{
int i;
if(argc != 3 )
{
printf("Usage: root# ./ShowProc [proc file name] [log file name]n");
exit(0);
}
if((fplogfile=fopen(argv[2],"w+"))==NULL)
{
printf("Warning: File(%s) can not open.",argv[2]);
exit(0);
}
signal(SIGALRM,handler);
while(1)
{
alarm(1);
pause();
system("clear");
if((fp=fopen(argv[1],"rb"))==NULL)
{
printf("Warning: File(%s) can not open.",argv[1]);
fclose(fplogfile);
exit(0);
}
while(fgets(buf,2047,fp))
{
i = 0;
printf("%s",buf);
fprintf(fplogfile,"%s",buf);
while(buf[i])
{
if(buf[i] == 'n') buf[i] = ';';
i++;
}
}
fclose(fp);
}
return 0;
}
ProcWrite.c
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
//#include <curses.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
int i;
char buf[2048];
FILE *fp;
if(argc != 3 )
{
printf("Usage: root# ./ProcWrite [proc file name] [Data to write]n");
exit(0);
}
if((fp=fopen(argv[1],"wb"))==NULL)
{
printf("Warning: File(%s) can not open.",argv[1]);
exit(0);
}
strcpy(buf,argv[2]);
fwrite(buf,1,strlen(buf),fp);
fclose(fp);
}
0 意見:
張貼留言