1. 程式人生 > >核心模組學習之簡單的核心模組編寫

核心模組學習之簡單的核心模組編寫

核心模組的特點

       linux核心模組是一個編譯好的,具有特定格式的獨立目標檔案,使用者可通過系統提供的一組與模組相關的命令將核心模組載入進核心,當核心模組被載入後,它具有一下特點:

1.與核心一起執行在相同的核心態和核心地址空間

2.執行時和核心擁有一樣的特權級

       3.可訪問核心中的各種資料結構

       被載入到核心的核心模組程式碼和靜態編譯進核心的程式碼沒有區別,核心模組與核心中其他模組之間的互動只需要函式呼叫。當用戶不在需要某功能模組時,可將其從核心中解除安裝,配置靈活。

載入模組的管理

   linux核心管理核心模組主要有兩項任務,核心符號表管理,維護核心模組引用計數。

   1.核心將資源等級在符號表中,核心模組被載入後,模組可通過符號表使用核心中的資源,新模組載入到核心時,系統將新模組提供的符號加進

符號表中,這樣新載入模組就可訪問一家在模組提供的資源;在解除安裝一個模組時,系統釋放分配給該模組所用系統資源,同事將該模組提供的符號從符號

表中刪除。

   2.引用計數是用來管理核心模組之間依賴性的。核心模組在載入後都在同一地址空間,核心模組之間可相互引用各自到處的符號,也就產生了依賴。如果A模組需要用到B模組到處的符號,而B模組沒有被載入到核心,A模組的載入就會出錯;同樣,一個核心模組如果有其他核心模組引用它匯出的符號,核心也不允許該模組被解除安裝。如果一個模組被依賴,它的引用技術就會增加,當依賴減少時,相應的引用計數也會減少,一個核心模組只有在引用計數為0的時候才能被解除安裝。   

如何編寫一個核心模組

       這裡介紹的核心模組程式設計以2.6核心版本為例,由於核心模組在核心空間執行,無法與c庫函式連結,因此它的編寫受到核心程式設計的限制,如不能使用浮點計算。

    一個典型的核心模組結構應包含一下幾個部分:

       1.標頭檔案宣告

       #include<linux/init.h>

       #include<linux/module.h>

       #include<linux/moduleparam.h>

       init.h中包含模組初始化和清理函式的定義;

       module.h包含載入模組需要的函式和符號定義;

       moduleparam.h允許模組載入時使用者傳遞引數。

       2.模組許可宣告

       MODULE_LICENSE("GPL");

       模組需要通過MODULE_LICENSE巨集宣告此模組的許可證。從/usr/scr/linux_xxx/include/linux/module.h檔案可看到被核心接受的許可證

有GPL、GPL v2、GPL and additional rights、Dual BSD/GPL等

       3.初始化和清理函式宣告

       staticint xxx_init()

       {

              xxx;

              return0;

       }

       staticvoid xxx_exit()

       {

              xxx;

       }

       module_init(xxx_init);

       module_exit(xxx_exit);

       核心模組必須使用巨集module_init和module_exit去註冊初始化與清理函式,而且初始化與清理函式必須在註冊之前定義。初始化與清理函式是配對使用的,例如module_init()中申請了一個資源,那麼module_exit()中就應該釋放這個資源。

    總體來說我們需要做一下幾個工作:    

1.檢視和下載當前版本的Linux原始碼

    如果當前執行的核心版本與你編譯連結的標頭檔案版本不一致,載入核心模組時會遇到insmod: error inserting 'xxx.o' :-l invalid module format這樣的錯誤

可以使用uname -a檢視版本,在使用apt-get install linux-source 下載原始碼包。

#include<linux/init.h>

#include<linux/module.h>

#include<linux/moduleparam.h>

MODULE_LICENSE("GPL");

/* theinit function*/

inthello_init()

{

    printk(" hello world !\n");

    printk(" I have runing in akerner");

    return 1;

}

/* thedistory function*/

inthello_exit()

{

    printk("I will shut down myself inkernerl mod \n");

    return 0;

}

module_init(hello_init);

module_exit(hello_exit);

2.編寫makefile

在與模組程式相同的目錄下編寫模組程式的Makefile檔案

obj-m := hello.o 

       KERNELDIR:= /lib/modules/$(shell uname -r)/build

       PWD:= $(shell pwd)  

modules:     

       $(MAKE)-C $(KERNELDIR) M=$(PWD) modules  

modules_install:     

       $(MAKE)-C $(KERNELDIR) M=$(PWD) modules_install  

clean:     

       rm-rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

說明:

       1.執行該Makefile檔案時將跑到 KERNELDIR下呼叫make,即/lib/modules/$(shell uname -r) /build下必須有一個Makefiule檔案;

       2.PWD指定要編譯的模組程式原始檔所在的目錄,$(shell pwd) 表示當前目錄,最終要生成的目標是modules

幾點說明

關於printfk

       1.printk是核心提供的列印函式。printf是glibc提供的函式,linux核心函式是不能依賴於任何程式庫的;

       2.printk()列印的資訊一般在/var/log/messages檔案裡;

       3.可以使用dmesg命令檢視,如果只想顯示最後n行,可以用dmesg | tail -n。

關於模組的命令

       1.載入

       insmod/path/modulename 載入後在/sys/module中就可以看到模組了

       2.解除安裝

       rmmod/path/modulename 解除安裝後在/sys/module中模組移除

       3.檢視系統以載入模組

       lsmod

       4.檢視模組資訊

       modinfo/path/modulename

相關推薦

核心模組學習簡單核心模組編寫

核心模組的特點        linux核心模組是一個編譯好的,具有特定格式的獨立目標檔案,使用者可通過系統提供的一組與模組相關的命令將核心模組載入進核心,當核心模組被載入後,它具有一下特點: 1.與核心一起執行在相同的核心態和核心地址空間 2.執行時和核心擁有一樣的特權級

hibernate學習簡單核心概念

一、hibernate 1. hibernate是什麼? hibernate是一個開放原始碼的物件關係對映框架(ORM),它是當今主流的Java持久層框架之一。 (1)hibernate框架應用在JavaEE三層架構中的dao層框架。 (2)在dao層對資料庫進行crud操作,hibern

[資料倉庫]電商核心業務知識訂單商品模組

電商核心業務知識 訂單商品模組(9張表) --訂單主要資訊表 drop table if exists itqsc.ods_b2c_orders; create external table itqsc.ods_b2c_orders ( order_id  bigint, -

Linux 核心時鐘架構時鐘源模組對外介面

既然時鐘源對外提供了計數能力,那麼可以通過哪些介面呢? 這裡需要唯一說明的是,整個時鐘源模組對外只有一個介面,即提供到timekeeping使用,其讀取計數值計數,計算時間。 核心函式是timekeeping_notify(); 這個函式在選取合適的clocksourc

Spark學習Spark核心

一、Spark中的一些專業術語 任務: Application:使用者寫的應用程式,包括Driver Program和Executor Program。 Job:一個action類運算元觸發執行的操作。 stage:一組任務(task)就是一個stage。

python學習路---day21--模組和棧

模組和棧一:計數模組collections 基礎版本: s="qwewsfdfjiehrfqweqweqwqewq" dic={} for el in s: d

linux安全模組學習LSM的介紹實現

相關背景介紹 近年來Linux系統由於其出色的效能和穩定性,開放原始碼特性帶來的靈活性和可擴充套件性,以及較低廉的成本,而受到計算機工業界的廣泛關注和應用。 但在安全性方面,Linux核心只提供了經典的UNIX自主訪問控制(root使用者,使用者ID,模式位安全機制),以及部分的支援了POS

小程式學習旅---wxs模組自定義方法

// pages/user/user.js Page({ /** * 頁面的初始資料 */ data: { d: '1500000000000' }, goShop () { wx.navigateTo({ url:

ESP8266 WIFI模組學習路(1)——模組的USB串列埠連線

ESP8266 WIFI模組是我一直想學習的模組,現在物聯網發展如此之快。 我們先看看ESP8266 WIFI模組長什麼樣子吧,如下圖: 然後,我們還需要一個TTL-USB串列埠線,如圖: 還需要一個串列埠除錯助手,為了接發資料。我使用的除錯助手如下圖:

紅外通訊模組、NEC紅外收發模組——學習三——兩個微控制器互動控制小車

先上兩個圖: 微控制器A: 微控制器B: 現在實現的功能的是: 微控制器A控制微控制器B完成一定的任務,包括以下幾點: 微控制器A作為遙控器,資料的傳送端 微控制器A有微控制器和紅外線模組組成,完成的功能是:微控制器控制紅外模組,使得紅外模組向外傳送控

ESP8266 WIFI模組學習路(2)——模組與微控制器連線進行遠端操作

上一個部落格:ESP8266 WIFI模組學習之路(1)是關於對串列埠連線的,簡單驗證ESP8266是怎麼樣連線及其功能驗證,下面將通過微控制器連線,和手機進行遠端操作。 ESP8266和微控制器的連線,我這裡的微控制器型號為:STC12C5A60S2 ESP8266

python爬蟲學習日誌記錄模組

這次的程式碼就是一個日誌記錄模組,程式碼很容易懂,註釋很詳細,也不需要安裝什麼庫。提供的功能是日誌可以顯示在螢幕上並且儲存在日誌檔案中。呼叫的方式也很簡單,測試程式碼裡面有。 原始碼: #encoding=utf-8 import logging import getpass import

Python3.6 模組學習random模組

random是內建(built-in)函式,作用是產生隨機數 匯入模組: import random接著就可以呼叫random模組下的函數了使用 dir(random)可以檢視random模組下有哪些函式,結果如下:>>> dir(random) ['BP

PYTHON模組學習smtplib

python的smtplib提供了一種很方便的途徑傳送電子郵件。它對smtp協議進行了簡單的封裝。 smtp協議的基本命令包括:     HELO 向伺服器標識使用者身份     MAIL 初始化郵件傳輸 mail from:     RCPT 標識單個的郵件接收人;常在M

python學習——import sys模組

首先,我們利用import語句 輸入 sys模組。基本上,這句語句告訴Python,我們想要使用這個模組。sys模組包含了與Python直譯器和它的環境有關的函式。 當Python執行import sys語句的時候,它在sys.path變數中所列目錄中尋找sys.py模組。

Android FM模組學習四原始碼解析(三)

     由於最近一直忙專案,沒有時間來更新文件,今天抽空來寫一點,希望大家可以學習使用!      這一章當然還是來分析FM模組的原始碼。FmReceiver.java publicFmReceiver(String devicePath,FmRxEvCallbacks

python的簡單學習簡單使用模組、列表、元組、字典、序列、引用、

python模組簡單學習import sysimport sys #利用import語句輸入sys模組,sys模組包含了與python直譯器和它的環境有關的函式 print ('The command line arguments are:') for i in sys.a

Python模組學習Timer定時任務,函式自調實現定時獲取部落格園部落格瀏覽量

Timer定時任務 下面是Timer函式的官方doc介紹資訊 “”” Call a function after a specified number of seconds: t = Timer(30.0, f, args=No

Python網路程式設計 ---Socket模組學習獲取遠端裝置IP(二)

1、使用內建庫函式gethostbyname(),引數為遠端裝置的主機名。新建檔案 getremotemachineinfo.py#!/usr/bin/python import socket def get_remote_machine_info():     remote

Linux學習zImage核心映象解壓過程詳解---說明為什麼解壓地址可以是zImage載入地址

轉自:http://www.embedu.org/Column/Column13.htm作者: 劉洪濤,華清遠見嵌入式培訓中心 講師。在華清遠見教學過程中,發現很多學員對核心映象解壓過程比較感興趣,但網上相關的文章往往不能把關鍵問題講清楚,所以寫了這篇文章。本文以linux-2.6.14核心在S3C2410平