1. 程式人生 > >Linux:驅動之字元設備註冊

Linux:驅動之字元設備註冊

  •  驅動之字元設備註冊

目前尚不是最終版本,還望有心人自己學習的時候,把自己整合的知識點相關的答案也好問題也好,或者實踐過程中的一些操作截圖,再或者其他的一些想要分享材料發給筆者郵箱:[email protected],我們一起完善這篇部落格!筆者寫這篇部落格的時候已經工作第四個年頭了,目前是在整理之前有過的學習資料,僅作為筆記,供同志們參考!短時間內可能不會去全部完善。

  • 思路和框架

目的:給空模組新增驅動殼子;

核心工作量:file_operations及其元素填充、註冊驅動。

  • 如何動手寫驅動程式碼

腦海裡先有框架,知道自己要幹嘛;

細節程式碼不需要一個字一個字敲,可以到核心中去尋找參考程式碼複製過來改;

寫下的所有程式碼必須心裡清楚明白,不能似懂非懂。

  • 開始動手

先定義file_operations結構體變數;

// 自定義一個file_operations結構體變數,並且去填充
static const struct file_operations test_fops = {
	// 慣例,直接寫即可
	.owner		= THIS_MODULE,				
	// 將來應用open開啟這個裝置時實際呼叫的
	// 就是這個.open對應的函式
	.open		= test_chrdev_open,			
	.release	= test_chrdev_release,		
};

open和close函式原型確定、內容填充;

static int test_chrdev_open(struct inode *inode, struct file *file)
{
	// 這個函式中真正應該放置的是開啟這個裝置的硬體操作程式碼部分
	// 但是現在暫時我們寫不了這麼多,所以用一個printk列印個資訊來意思意思。
	printk(KERN_INFO "test_chrdev_open\n");
	
	return 0;
}

static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");
	
	return 0;
}

完整的相關程式碼見下述檔案:

Makefile

# ubuntu的核心原始碼樹,如果要編譯在ubuntu中安裝的模組就開啟這2個
# KERN_VER = $(shell uname -r)
# KERN_DIR = /lib/modules/$(KERN_VER)/build	
		
# 開發板的linux核心的原始碼樹目錄
KERN_DIR = /root/qt/kernel
 
obj-m	+= module_test.o
 
all:
	make -C $(KERN_DIR) M=`pwd` modules 
#	arm-none-linux-gnueabi-gcc app.c -o app
	
cp:
	cp *.ko /root/removal/rootfs/root/driver_test
#	cp app /root/removal/rootfs/root/driver_test
 
.PHONY: clean	
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean

module_test.c

// 為了module_init,module_exit相關的,加入下面標頭檔案
#include <linux/module.h>
// 為了__init,__exit相關的,加入下面標頭檔案
#include <linux/init.h>		
#include <linux/fs.h>

#define MYMAJOR		250
#define MYNAME		"test_chrdev"

static int test_chrdev_open(struct inode *inode, struct file *file)
{
	// 這個函式中真正應該放置的是開啟這個裝置的硬體操作程式碼部分
	// 但是現在暫時我們寫不了這麼多,所以用一個printk列印個資訊來意思意思。
	printk(KERN_INFO "test_chrdev_open\n");
	
	return 0;
}

static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");
	
	return 0;
}

// 自定義一個file_operations結構體變數,並且去填充
static const struct file_operations test_fops = {
	// 慣例,直接寫即可
	.owner		= THIS_MODULE,				
	// 將來應用open開啟這個裝置時實際呼叫的
	// 就是這個.open對應的函式
	.open		= test_chrdev_open,			
	.release	= test_chrdev_release,		
};

// 模組安裝函式
static int __init chrdev_init(void)
{	
	int ret = -1;
	
	printk(KERN_INFO "chrdev_init helloworld init\n");

	// 在module_init巨集呼叫的函式中去註冊字元裝置驅動
	ret = register_chrdev(MYMAJOR, MYNAME, &test_fops);
	if (ret)
	{
		printk(KERN_ERR "register_chrdev fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "register_chrdev success...\n");

	return 0;
}

// 模組解除安裝函式
static void __exit chrdev_exit(void)
{
	printk(KERN_INFO "chrdev_exit helloworld exit\n");
	
	// 在module_exit巨集呼叫的函式中去登出字元裝置驅動
	unregister_chrdev(MYMAJOR, MYNAME);
	
}
 
module_init(chrdev_init);
module_exit(chrdev_exit);
 
// MODULE_xxx這種巨集作用是用來新增模組描述資訊
// 描述模組的許可證
MODULE_LICENSE("GPL");
// 描述模組的作者				
MODULE_AUTHOR("aston");	
// 描述模組的介紹資訊			
MODULE_DESCRIPTION("module test");
// 描述模組的別名資訊	
MODULE_ALIAS("alias xxx");			
  • 註冊驅動

主裝置號的選擇?

返回值的檢測?

  • 驅動測試

編譯等 make && make cp?

insmod並且檢視設備註冊的現象?

rmmod並且檢視設備註銷的現象?

  • 讓核心自動分配主裝置號

為什麼要讓核心自動分配?

如何實現?

int mymajor;
	// major傳0進去表示要讓核心幫我們自動分配一個合適的空白的沒被使用的主裝置號
	// 核心如果成功分配就會返回分配的主裝置號;如果分配失敗會返回負數
	mymajor = register_chrdev(0, MYNAME, &test_fops);
	if (mymajor < 0)
	{
		printk(KERN_ERR "register_chrdev fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "register_chrdev success... mymajor = %d.\n", mymajor);

測試?

實現的完整程式碼見下述檔案:

module_test.c

// 為了module_init,module_exit相關的,加入下面標頭檔案
#include <linux/module.h>
// 為了__init,__exit相關的,加入下面標頭檔案
#include <linux/init.h>		
#include <linux/fs.h>

#define MYMAJOR		250
#define MYNAME		"test_chrdev"

int mymajor;

static int test_chrdev_open(struct inode *inode, struct file *file)
{
	// 這個函式中真正應該放置的是開啟這個裝置的硬體操作程式碼部分
	// 但是現在暫時我們寫不了這麼多,所以用一個printk列印個資訊來意思意思。
	printk(KERN_INFO "test_chrdev_open\n");
	
	return 0;
}

static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");
	
	return 0;
}

// 自定義一個file_operations結構體變數,並且去填充
static const struct file_operations test_fops = {
	// 慣例,直接寫即可
	.owner		= THIS_MODULE,				
	// 將來應用open開啟這個裝置時實際呼叫的
	// 就是這個.open對應的函式
	.open		= test_chrdev_open,			
	.release	= test_chrdev_release,		
};

// 模組安裝函式
static int __init chrdev_init(void)
{	
	printk(KERN_INFO "chrdev_init helloworld init\n");

	// 在module_init巨集呼叫的函式中去註冊字元裝置驅動
	// major傳0進去表示要讓核心幫我們自動分配一個合適的空白的沒被使用的主裝置號
	// 核心如果成功分配就會返回分配的主裝置號;如果分配失敗會返回負數
	mymajor = register_chrdev(0, MYNAME, &test_fops);
	if (mymajor < 0)
	{
		printk(KERN_ERR "register_chrdev fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "register_chrdev success... mymajor = %d.\n", mymajor);

	return 0;
}

// 模組解除安裝函式
static void __exit chrdev_exit(void)
{
	printk(KERN_INFO "chrdev_exit helloworld exit\n");
	
	// 在module_exit巨集呼叫的函式中去登出字元裝置驅動
	unregister_chrdev(mymajor, MYNAME);
	
}
 
module_init(chrdev_init);
module_exit(chrdev_exit);
 
// MODULE_xxx這種巨集作用是用來新增模組描述資訊
// 描述模組的許可證
MODULE_LICENSE("GPL");
// 描述模組的作者				
MODULE_AUTHOR("aston");	
// 描述模組的介紹資訊			
MODULE_DESCRIPTION("module test");
// 描述模組的別名資訊	
MODULE_ALIAS("alias xxx");			

相關推薦

Linux驅動字元註冊

 驅動之字元設備註冊 目前尚不是最終版本,還望有心人自己學習的時候,把自己整合的知識點相關的答案也好問題也好,或者實踐過程中的一些操作截圖,再或者其他的一些想要分享材料發給筆者郵箱:[email protected],我們一起完善這篇部落格!筆者寫這篇部落格

Linux驅動字元備註冊新介面(未完)

驅動之字元設備註冊新介面 目前尚不是最終版本,還望有心人自己學習的時候,把自己整合的知識點相關的答案也好問題也好,或者實踐過程中的一些操作截圖,再或者其他的一些想要分享材料發給筆者郵箱:[email protected],我們一起完善這篇部落格!筆者寫這篇部

Linux驅動字元裝置工作原理(未完)

字元裝置驅動工作原理 系統整體工作原理 應用層->API->裝置驅動->硬體? API:open、read、write、close等? 驅動原始碼中提供真正的open、read、write、close等函式實體? file_

Linux驅動平臺驅動模型簡析(驅動分離分層概念的建立)

技術 描述 rst 操作 mem iou 系統 簡單 reg Linux設備模型的目的:為內核建立一個統一的設備模型,從而有一個對系統結構的一般性抽象描述。換句話說,Linux設備模型提取了設備操作的共同屬性,進行抽象,並將這部分共同的屬性在內核中實現,而為需要新添加設備

字元註冊platform平臺驅動機制

怎麼利用平臺裝置驅動機制來寫驅動: ------------------------------------------------------------------------- 1.先實現裝置方向的:      1)看晶片手冊,和原理圖獲取資源      2)構建平

淺談linux字元註冊

在呼叫cdev_add()函式向系統註冊字元裝置之前應該先呼叫:int register_chrdev_region(dev_t from,unsigned count,const char *name)函式為其分配裝置號,此函式可用:int alloc_chrdev_region(dev_t *dev,un

深入淺出Linux裝置驅動字元裝置驅動

一、linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。使用驅動程式: 字元裝置:是指只能一個位元組一個位元組讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後資料。字元裝置是面向流的裝置,常見的字元裝置有滑鼠、鍵盤、串列埠、

Linux驅動為應用程式實現呼叫(未完)

應用程式如何呼叫驅動 目前尚不是最終版本,還望有心人自己學習的時候,把自己整合的知識點相關的答案也好問題也好,或者實踐過程中的一些操作截圖,再或者其他的一些想要分享材料發給筆者郵箱:[email protected],我們一起完善這篇部落格!筆者寫這篇部落格

Linux裝置驅動字元裝置驅動---轉

一、linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。 應用程式呼叫的流程框圖: 三種裝置的定義分別如下, 字元裝置:只能一個位元組一個位元組的讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後順序進行。字元裝置是面向流的裝置,常見的字

塊裝置剖析註冊

本文所有內容基於核心版本Linux-v3.2.40。     add_disk()是塊設備註冊的核心介面,是塊裝置驅動的最後一步,也是最關鍵的一步,下面就分析一下該函式實現的具體細節。    當申請完一個gendisk並進行初始化之後,就可以藉助add_diak將之註冊到通用塊層。表面上看,add_dia

Linux裝置驅動字元裝置(一)

Linux中裝置驅動的分類 從上圖可以看到Linux系統將各異的裝置分為三大類:字元裝置,塊裝置和網路裝置。核心針對每一類裝置都提供了對應驅動模型架構,包括基本的核心設施和檔案系統介面。 字元裝置:在傳送過程中以字元為單位,一個位元組一個位元組的讀寫,不

Linux裝置驅動字元裝置驅動

一、linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。 應用程式呼叫的流程框圖: 三種裝置的定義分別如下, 字元裝置:只能一個位元組一個位元組的讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後順序進行。字元裝置是面向流的裝置,常見的字元裝置如

從需求的角度去理解Linux系列總線、驅動

電平 可移植性 需求 講解 好處 鼠標 地理 embed 博客專家 筆者成為博客專家後整理以前原創的嵌入式Linux系列博文,現推出以讓更多的讀者受益。 《從需求的角度去理解linux系列:總線、設備和驅動》是一篇有關如何學習嵌入式Linux系統的方法論文章,也是從

Linux驅動開發(2)——註冊

結構體platform_device 註冊裝置使用結構體platform_device,原始碼路徑include/linux/platform_device.h struct platform_device { const char * name;//裝

字元驅動裝置2.2--註冊

核心內部使用struct cdev結構來標識字元裝置。在核心呼叫裝置的操作之前,必須註冊一個或 多個該結構。該結構定義在<linux/cdev.h>中。 struct cdev { struct kobject kobj; struct modu

Linux 核心時鐘架構時鐘事件註冊

void clockevents_register_device(struct clock_event_device *dev); void clockevents_config_and_register(struct clock_event_device *dev,  

物聯網平臺構架系列Amazon, Microsoft, IBM IoT 平臺導論

物聯網; iot; aws; 亞馬遜; greengrass;microsoft; azure;ibm; watson; bluemix 最近研究了一些物聯網平臺技術資料,以做選型參考。腦子裏積累大量信息,便想寫出來做一些普及。作為科普文章,力爭通俗易懂,不確保概念嚴謹性。我會給考據癖者提供相關英文

讓天堂的歸天堂,讓塵土的歸塵土——談Linux的總線、驅動模型

linux 總線 設備 驅動公元1951年5月15日的國會聽證上,美國陸軍五星上將麥克阿瑟建議把朝鮮戰爭擴大至中國,布萊德利隨後發言:“如果我們把戰爭擴大到共產黨中國,那麽我們會被卷入到一場錯誤的時間,錯誤的地點同錯誤的對手打的一場錯誤的戰爭中。”寫代碼,適用於同樣的原則,那就是把正確的代碼放到正確的位置而不

Linux總線、驅動》USB發現機制

buffer 嵌入 void smo b- 嵌入式系統 root 顯示 ice 說明:本分析基於mstar801平臺Linux2.6.35.11內核,其他內核版本僅供參考。 一、程序在內核中的位置 1.usb host做為pci總線下的一個設備存在(嵌入式系統中有可能也會

喜羊羊系列-驅動 動態載入進內核】

popu error 驅動 abi free -s map .net obj 博客:http://blog.csdn.net/muyang_ren 這篇和設備驅動編