1. 程式人生 > >Linux模組程式設計方法總結

Linux模組程式設計方法總結

一、編寫一個基本的核心模組

1、編輯原始檔,程式碼hello.c

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

int init_hello_module(void)

{

       printk("init_hello_module\n");

       return0;

}

void exit_hello_module(void)

{

       printk("exit_hello_module\n");

}

MODULE_LICENSE("GPL");

module_init(init_hello_module);

module_exit(exit_hello_module);

Makefile檔案

ifeq ($(KERNELRELEASE),)

$(info 1st)

all:

       make-C /lib/modules/$(shell uname -r)/build M=$(shell pwd)

clean:

       rm*.o *.ko *.mod.c modules.order

else

$(info 2nd)

obj-m:=hello.o

endif

2.編譯

make

3. 測試sudo insmod hello.ko、sudo rmmod hello、dmesg

3. 原理:

Makefile原理

1、當用戶在shell

輸入make 命令,會先在當前目錄下找Makefile

2、解析的第一條語句是 ifeq ($(KERNELRELEASE),) 判斷當前的Makefile中是否有KERNELRELEASE 變數因為當前Makefile中沒有KERNELRELEASE,所以ifeq 條件成立

3、執行第一條規則語句 all: make -C path/to/kernel M=$(shell pwd) 呼叫了make命令,根據 -C 指定的核心頂層原始碼路徑,去解析核心頂層原始碼對應的 Makefile

4、核心頂層原始碼makefile中根據 M=$(shell pwd)引數第二次進入當前目錄,解析當前 Makefile

,這時,因為是從核心頂層原始碼的Makefile 進入的,而KERNELRELEASE 在核心頂層原始碼Makefile已經定義,所以這一次ifeq條件不成立,進入 else分支

5、這時核心Makefile檢查編譯模組所依賴的.o檔案(hello.o)是否存在,如果不存在,根據hello.c生成hello.o

6、核心Makefile會第三次進入當前目錄,還是走else 分支,這一次因為hello.o已經存在會根據 hello.o生成hello.ko

 

二、多個檔案生成一個模組

在同一目錄下增加show.c檔案

#include <linux/kernel.h>

static int a;

int show_addr(void)

{

       printk("aaddr = %p\n",&a);

       return0;

}

Makefile改為

ifeq ($(KERNELRELEASE),)

$(info 1st)

all:

       make-C /lib/modules/$(shell uname -r)/build M=$(shell pwd)

clean:

       rm*.o *.ko *.mod.c modules.order

else

$(info 2nd)

obj-m:=helloshow.o

helloshow-y+=hello.o

helloshow-y+=show.o

endif

三、多個模組之間的函式呼叫

Show.c改為如下:

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

static int a;

int show_addr(void)

{

       printk("aaddr = %p\n",&a);

       return0;

}

int init_show_module(void)

{

       printk("init_show_module\n");

       show_addr();

       return0;

}

void exit_show_module(void)

{

       printk("exit_show_module\n");

}

EXPORT_SYMBOL(show_addr);

MODULE_LICENSE("GPL");

module_init(init_show_module);

module_exit(exit_show_module);

Makefile改為如下:

ifeq ($(KERNELRELEASE),)

$(info 1st)

all:

       make-C /lib/modules/$(shell uname -r)/build M=$(shell pwd)

clean:

       rm*.o *.ko *.mod.c modules.order

else

$(info 2nd)

obj-m:=hello.o show.o

endif

 

四、模組傳遞引數

1. 在hello.c中增加模組引數定義

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

static int count = 5;

static int a = 100;

static int b = 100;

static char *string = "helloworld";

int init_hello_module(void)

{

       printk("init_hello_module\n");

       for(;count-->0;)

       {

              printk("init:stringis %s\n",string);

       }

       return0;

}

void exit_hello_module(void)

{

       printk("exit_hello_module\n");

       for(;count-->0;)

       {

              printk("exit:stringis %s\n",string);

       }

}

MODULE_LICENSE("GPL");

module_param(count, int, 0644);

module_param(a, int, 0644);

module_param(b, int, 0644);

module_param(string, charp, 0644);

module_init(init_hello_module);

module_exit(exit_hello_module);

2. 編譯測試模組引數傳遞

方法1,在載入模組的時候修改引數值

方法2,通過sysfs檔案系統的節點修改模組引數值