天天看點

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

實驗報告封面

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗
20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

實驗步驟

1、閱讀和了解源代碼

進入/arm2410cl/exp/drivers/01_demo,使用vi 編輯器或其他編輯器閱讀了解源代碼。

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

2、實驗開始前配置環境變量

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

3、編譯驅動子產品及測試程式上面介紹了在 Makefile 中有兩種編譯方法,可以在本機上使用gcc 也可以使用交叉編譯器進行編譯,這裡我們隻介紹用交叉編譯器進行編譯的結果。

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

4、測試驅動程式如果使用 gcc 編譯的話,需要通過下面的指令來建立裝置節點,如果使用交叉編譯器的話,不需要建立裝置節點。

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

首先要插入驅動子產品demo.o,然後可以用lsmod 指令來檢視子產品是否已經被插入,在不使用該子產品的時候還可以用rmmod 指令來将子產品解除安裝。

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

根據上述指令輸入:

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

下面使用測試程式來進行測試:./test_demo

直接運作出現請求打開失敗的提示,經過多次探索問題解決運作成功

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗
20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

問題與解決

1、問題:忘記配置環境變量,需要将實驗一armv4l檔案夾要考到bc中

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗
  • 解決方法:将armv4l檔案夾拷貝到bc中再次輸入相關指令
    20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

輸入指令./install.sb

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

2、問題:交叉編譯器進行編譯第一次輸入指令出現錯誤

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗
  • 解決方法:
    20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

輸入指令後問題解決

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

3、問題:在使用測試程式進行測試時,多次出現device open failed提示

20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗
  • 解決方法:懷疑是前面某一步驟漏輸入或者指令輸錯,依次再次輸入排除問題,再次輸入insmod demo.o,發現插件已存在于是再次運作,依然失敗,排除插件插入因素
  • 輸入指令#mknod /dev/demo c 254 0 ,建立裝置節點(因為第一次編譯時根據指導書訓示沒有操作此步驟),進行運作發現成功。
20145216 20145330 《資訊安全系統設計基礎》 實驗四 子產品方式驅動實驗

了解源代碼

  • 源代碼
#define DEVICE_NAME  "demo"
	static ssize_t demo_write(struct file *filp,const char * buffer, size_t count)
	{ 
	    char drv_buf[];
	    copy_from_user(drv_buf , buffer, count);
	    …
	}
	static ssize_t demo_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)
	{
	char drv_buf[];
	copy_to_user(buffer, drv_buf,count);
	….
	}
	static int demo_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)
	{
	}
	static int demo_open(struct inode *inode, struct file *file)
	{
	}
	static int demo_release(struct inode *inode, struct file *filp)
	{
	    MOD_DEC_USE_COUNT;
	    DPRINTK("device release\n");
	    return 0;
	}
	static struct file_operations demo_fops = {
	    owner:  THIS_MODULE,
	    write:demo_write, 
	    read: demo_read, 
	    ioctl: demo_ioctl,
	    open: demo_open,
	    release:demo_release,
	};
	#ifdef CONFIG_DEVFS_FS
	static devfs_handle_t devfs_demo_dir, devfs_demoraw;
	#endif
	static int __init demo_init(void)
	{
	    int result;
	    #ifdef CONFIG_DEVFS_FS
	    devfs_demo_dir = devfs_mk_dir(NULL, "demo", NULL);
	    devfs_demoraw = devfs_register(devfs_demo_dir, "0", DEVFS_FL_DEFAULT,
	    demo_Major, demo_MINOR, S_IFCHR | S_IRUSR | S_IWUSR,&demo_fops, NULL);
	    #else
	    SET_MODULE_OWNER(&demo_fops);
	    result = register_chrdev(demo_Major, "scullc", &demo_fops);
	    if (result < 0) return result;
	    if (demo_Major == 0) demo_Major = result; /* dynamic */
	    #endif
	    printk(DEVICE_NAME " initialized\n");
	    return 0;
	}
	static void __exit demo_exit(void)
	{
	    unregister_chrdev(demo_major, "demo");
	    kfree(demo_devices);
	    printk(DEVICE_NAME " unloaded\n");
	}
	module_init(demo_init);
	module_exit(demo_exit);

           

注釋

  • 将驅動映射為标準接口
    • static struct file_operations demo_fops = {…}完成了将驅動函數映射為标準接口。
    • 驅動向核心注冊
    • devfs_registe()和 register_chrdev()函數完成将驅動向核心注冊。
  • Open方法

Open 方法提供給驅動程式初始化裝置的能力,進而為以後的裝置操作做好準備,此外open操作一般還會遞增使用計數,用以防止檔案關閉前子產品被解除安裝出核心。

- 遞增使用計數
- 檢查特定裝置錯誤。
- 如果裝置是首次打開,則對其進行初始化。
- 識别次裝置号,如有必要修改 f_op 指針。
- 配置設定并填寫 filp->private_data 中的資料。
           
  • Release 方法

與 open 方法相反,release 方法應完成如下功能:

- 釋放由 open 配置設定的 filp->private_data 中的所有内容
- 在最後一次關閉操作時關閉裝置
- 使用計數減一
           
  • Read 和 和 Write 方法

ssize_t demo_write(struct file *filp,const char * buffer, size_t count,loff_t *ppos)

ssize_t demo_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)

read 方法完成将資料從核心拷貝到應用程式空間,write 方法相反,将資料從應用程式空間拷貝到核心。對于者兩個方法,參數 filp 是檔案指針,count 是請求傳輸資料的長度,buffer 是使用者空間的資料緩沖區,ppos 是檔案中進行操作的偏移量,類型為 64 位數。由于使用者空間和核心空間的記憶體映射方式完全不同,是以不能使用象 memcpy 之類的函數,必須使用如下函數:

unsigned long copy_to_user (void *to,const void *from,unsigned long count);

unsigned long copy_from_user(void *to,const void *from,unsigned long count);

  • ioctl方法

ioctl 方法主要用于對裝置進行讀寫之外的其他控制,比如配置裝置、進入或退出某種

操作模式,這些操作一般都無法通過 read/write 檔案操作來完成。

  • 編寫中斷處理函數的注意事項:

中斷處理程式與普通C代碼沒有太大不同,不同的是中斷處理程式在中斷期間運作,它有如下限制:

不能向使用者空間發送或接受資料

不能執行有睡眠操作的函數

不能調用排程函數

  • 使用/proc檔案系統

/proc 檔案系統是由程式建立的檔案系統,核心利用它向外輸出資訊。/proc 目錄下的

每一個檔案都被綁定到一個核心函數,這個函數在此檔案被讀取時,動态地生成檔案的内

容。

大多數情況下 proc 目錄下的檔案是隻讀的。使用/proc 的子產品必須包 含

頭檔案

實驗感想與體會

這次實驗我們耗費了整整兩個課時,在閱讀實驗指導書後本來覺得步驟不是很多應該能很快完成。沒想到遇到各種細小的問題,并不是一帆風順的。做實驗的魅力就在于要不斷的嘗試與探索,在這個過程中操作更加熟練知識條理更加清晰,我們這次采用了新的排除法發現查錯效率高了不少,今後會繼續努力的。

隊友連結:http://www.cnblogs.com/sjy519/p/6083253.html