s3c2410的字符型設備驅(qū)動程序設計_第1頁
s3c2410的字符型設備驅(qū)動程序設計_第2頁
s3c2410的字符型設備驅(qū)動程序設計_第3頁
s3c2410的字符型設備驅(qū)動程序設計_第4頁
s3c2410的字符型設備驅(qū)動程序設計_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、 福建工程學院 課程設計報告 實驗課題: s3c2410的字符型設備驅(qū)動程序設計 指導老師:陳老師 日期:2011年5月24號1、 實驗原理:1 Linux系統(tǒng)下驅(qū)動程序的相關概念: Linux系統(tǒng)中,設備驅(qū)動程序是操作系統(tǒng)內(nèi)核的重要組成部分,它與硬件設備之間建立了標準的抽象接口。通過這個接口,用戶可以像處理普通文件一樣,對硬件設備進行打開(open)、關閉(close)、讀寫(read/write)等操作。通過分析和設計設備驅(qū)動程序,可以深入理解Linux系統(tǒng)和進行系統(tǒng)開發(fā)。Linux設備分為字符設備、塊設備和網(wǎng)絡設備。本課程設計研究字符型設備驅(qū)動程序設計。 Linux系統(tǒng)為每一個設備分配了

2、一個主設備號和 次設備號,主設備號標識設備對應驅(qū)動程序 ,次設備號標識具體設備的實例。例如一塊開發(fā)板上有2個串口終端 / dev/ tty0, / dev/ tty1 ,它們的主設備號都是4,次設備號分別為0和1。每一類設備使用的主設備號是獨一無二的,系統(tǒng)增加一個驅(qū)動程序就要賦予它一個主設備號,這一賦值過程在驅(qū)動程序的初始化過程中進行。2設備驅(qū)動程序的組成 設備驅(qū)動在加載時首先需要調(diào)用入口函數(shù) init module ( ) ,該函數(shù)完成設備驅(qū)動的初始化工作 ,比如寄 存器置位、結構體賦值等一系列工作,其中最重要的一個工作就是向內(nèi)核注冊該設備 ,字符設備調(diào)用函數(shù)register_chrdev

3、完成注冊。注冊成功后 ,該設備獲得了系統(tǒng)分配或向系統(tǒng)申請的主設備號、自定義的次設備號,并建立起與設備文件的關聯(lián)。設備驅(qū)動在卸載時需要回收相應的資源 ,將設備的響應寄存器值復位并從系統(tǒng)中注銷該設備。系統(tǒng)調(diào)用部分則是對設備的 操作過程 , 比如 open、read、write、ioctl等操作。設備驅(qū)動程序可以分成以下 3個主要部分: (1) 自動配置和初始化子程序。負責檢測所需驅(qū)動的硬件設備是否存在以及是否能正常工作 ,這部分驅(qū)動程序僅在初始化時被調(diào)用一次。(2) 服務 I/O 就是請求子程序,是驅(qū)動程序的上半部分,這部分是系統(tǒng)調(diào)用的結果。 (3) 中斷服務程序又稱驅(qū)動程序的下半部分,設備在 I

4、/O請求結束或其他狀態(tài)改變時產(chǎn)生中斷。因為設備驅(qū)動程序一般支持同一類型的若干個設備 ,所以調(diào)用中斷服務子程序時都帶有一個或多個參數(shù)以唯一標識請求服務的設備。 3字符設備驅(qū)動程序中重要的數(shù)據(jù)結構和函數(shù)對于每個系統(tǒng)調(diào)用,驅(qū)動程序中都有一個與之對應的函數(shù)。對于字符設備驅(qū)動程序 ,這些函數(shù)集合在一個file_op erations類型的數(shù)據(jù)結構中,它定義了常見文件I/O 函數(shù)的入口.編寫字符設備驅(qū)動程序就是為具體硬件的 file_ operations結構編寫各個函數(shù) ,大多數(shù)的驅(qū)動程序只是利用了其中的一部分 對于驅(qū)動程序中不提供的功能,把相應位置的值設為 NULL ) ,對于字符設備來說 ,要提供的

5、主要入口有: open ( ) 、release ( ) 、read ( ) 、write( ) 、lseek ( ) 、ioctl ( )等。本課程設計中用到的主要有 open ( )、read ( )、write( )、release ( )函數(shù)。int (*open)(struct inode*,struct file*); 該操作用來打開設備文件。int (*release)(struct inode*,struct file*); 該操作用來釋放文件結構。ssize_t(*read)(structfile*,char_user*,size_t,loff_t*); 該操作用來從設備中讀

6、取數(shù)據(jù)。ssize_t(*read)(structfile*,char_user*,size_t,loff_t*); 該操作發(fā)送數(shù)據(jù)給設備。4驅(qū)動程序的注冊和卸載驅(qū)動程序有一個初始化函數(shù) ,在安裝驅(qū)動程序時會調(diào)用它。在初始化函數(shù)中會將驅(qū)動程序的 file_operations與主設備號一起向內(nèi)核進行注冊。對字符設備使用如下函數(shù)進行注冊:int register_chrdev ( unsigned int major, const char* name, struct file_operations* fop s) ; 其中,major是為設備驅(qū)動程序向系統(tǒng)申請的主設備號,如果為 0則系統(tǒng)動態(tài)地

7、分配 l個主設備號, name是設備名。fop s是 file_operation s對各個調(diào)用入口點的說明。此函數(shù)返回0表示成功;返回 - 1是表示出 錯;返回 - E INVAL 表示申請的主設備號非法;返回- EBU SY表示所申請的主設備號正在被其他設備驅(qū)動程序使用。模塊在調(diào)用 rmmod 函數(shù)時被卸載 ,此時的入口點是 cleanup_module函數(shù)或宏 module_exit,并在其中完成對設備的注銷。類似的,字符設備的卸載函數(shù)定義為:int unregister_chrdev ( unsigned int major, const char* name) ;2、 實驗目的:了解

8、、掌握字符型驅(qū)動程序的設計過程、編譯、加載以及測試過程,包括了解file_operation數(shù)據(jù)結構、驅(qū)動程序的注冊與注銷、makefile文件的編寫。 3、 實驗步驟:寫入驅(qū)動程序源程序fakedev.c,本程序設計思維為設備輸入一串字符,再輸出同樣的字符。設備驅(qū)動程序的主體流程為:module_init->fakedev_init_module->register_chrdev->fakedev_fops->fakkdev_open/release/read/write. 源代碼fakedev.c#include <linux/config.h> /*預

9、定義和必要的頭文件*/#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/proc_fs.h>#include <l

10、inux/fcntl.h>#include <linux/seq_file.h>#include <linux/cdev.h>#include <asm/uaccess.h>#define DEVICE_NAME "fake device"MODULE_LICENSE("Dual BSD/GPL"); /*用宏來聲明該模塊的許可協(xié)議*/struct fake_device /* 該設備其他的私有數(shù)據(jù)和信號量的信息的定義 */int usage;char *data;int new_msg;struct fake_

11、device fakedev; int fakedev_major = 200; /*指定設備主設備號為200*/ /*以下為file_operation數(shù)據(jù)結構*/static int fakedev_open(struct inode *inode, struct file *file) /*定義了fakedev_open即打開操作函數(shù),這里函數(shù)定義為只打印一行消息*/ printk ("fakedev_device_open(%p,%p)n", inode, file); return 0;static int fakedev_release(struct inode

12、 *inode, struct file *file) /*定義了 fakedev_release即釋放文件結構函數(shù)。*/static void fakedev_device_release(%p,%p)n", inode, file);static ssize_t fakedev_read(struct file *f,char *buf,int size,loff_t off) /*定義了 fakedev_read即從設備中讀取數(shù)據(jù)的函數(shù)*/ int length;int count=size;if(count<0)return -EINVAL;if(fakedev.usa

13、ge)return -EBUSY;fakedev.usage=1;if(fakedev.data =0 )return 0;length = strlen(fakedev.data);if (length < count)count=length;copy_to_user(buf,fakedev.data,count+1);fakedev.new_msg=0;fakedev.usage=0;return count;static ssize_t fakedev_write(struct file *f,const char *buf,int size,loff_t off) /*定義fa

14、kedev_write函數(shù)即發(fā)送數(shù)據(jù)給設備函數(shù)*/ int count=size;if(count<0)return -EINVAL;if(fakedev.usage|fakedev.new_msg)return -EBUSY;fakedev.usage = 1;kfree(fakedev.data);fakedev.data = kmalloc(sizeof(char)*(count + 1),GFP_KERNEL);if(!fakedev.data)return -ENOMEM;copy_from_user(fakedev.data,buf,count + 1);fakedev.us

15、age = 0;fakedev.new_msg = 1;return count;struct file_operations fakedev_fops = /*定義該字符設備的具體文件操作,包括read、write、open、release*/.read = fakedev_read, .write = fakedev_write,.open = fakedev_open,.release = fakedev_release,;static int fakedev_init_module(void) /*定義fakedev_init_module,即字符設備向 系統(tǒng)注冊函數(shù)*/ int re

16、sult;result = register_chrdev(fakedev(fakedev_major,DEVICE_NAME,&fakedev_fops);if (result < 0)return result;if (fakedev_major = 0)fakedev_major = result;printk(KERN_INFO "Register FAKEDEV.major-number=%dn",result);return 0;static void fakedev_cleanup_module(void) /*定義fake_exit_modul

17、e,即字符設備向系統(tǒng)注銷函數(shù)*/ printk(KERN_INFO "Unregister FAKEDEVn");unregister_chrdev(fakedev_major, DEVICE_NAME);module_init(fakedev_init_module); /*包含了注冊、注銷兩個函數(shù)的指針*/module_exit(fakedev_cleanup_module);Makefile文件:在linux2.6內(nèi)核中,模塊的編譯需要配置過的內(nèi)核代碼,編譯過程首先會到內(nèi)核源碼目錄下,讀取頂層的makefile文件,然后再返回模塊代碼所在目錄進行編譯.可根據(jù)網(wǎng)絡上公開

18、的針對字符設備驅(qū)動程序的makefile模板進行該模塊makefile文件設計。 Makefile文件# Makefile2.6ifneq ($(KERNELRELEASE),)#kbuild syntax. dependency relationshsip of files and target modules are listed here.obj-m := fakedev.o /*指定模塊源文件*/elsePWD := $(shell pwd)KVER ?= $(shell uname -r)KDIR := /lib/modules/$(KVER)/build /*指定內(nèi)核源碼的路徑*/

19、all : $(MAKE) -C $(KDIR) M=$(PWD)clean : rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versionsendif通過執(zhí)行makefile來編譯驅(qū)動程序的源文件fakedev.c,以得到可執(zhí)行目標文件。截圖如下:由截圖可見:編譯之后得到可加載模塊fakedev.ko。fakedev源程序的測試程序fakedev_test.c。測試的例程:運行之前需要使用mkond命令來創(chuàng)建設備文件,然后執(zhí)行不帶參數(shù)的insmod,將上面編譯得到的可加載模塊fakedev.ko裝載到內(nèi)核。測試代碼fakedev_test.c#include<

20、;stdio.h> /*所需頭文件與預定義*/#include<stdlib.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#define MAX_LENGTH 100int mian (int argc, char *argv)char strMAX_LENGTH;char p;printf("please enter the words(max char num:%d):n",MAX_LENGTH -1);p = fgets(str,MAX_LENGTH,stdin); /*接收控制臺輸入的一組字符串*/int fakedev_fd=open("/dev/fakedev",O_RDWR);/*通過open系統(tǒng)調(diào)用打開虛擬設 if (fakedev_fd=-1) 備并獲得文件描述符fakedev_fd*/perror(&qu

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論