LINUX字符設備驅(qū)動編寫基本流程_第1頁
LINUX字符設備驅(qū)動編寫基本流程_第2頁
LINUX字符設備驅(qū)動編寫基本流程_第3頁
LINUX字符設備驅(qū)動編寫基本流程_第4頁
LINUX字符設備驅(qū)動編寫基本流程_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、- 簡介Linux 下的 MISC 簡單字符設備驅(qū)動雖然使用簡單,但卻不靈活。只能建立主設備號為 10 的設備文件。 字符設備比較容易理解, 同時也能夠滿足大多數(shù)簡 單的硬件設備 , 字符設備通過文件系 統(tǒng)中的名字來讀取。這些名字就是文件系統(tǒng)中的特 殊文件或者稱為設備文件、 文件系統(tǒng)的簡單結(jié)點, 一般位于 /dev/ 目錄下 使用 ls 進行查 看會顯示以 C 開頭證明這是字符設備文件crw-w 1 root tty 4, 0 4 月 14 11:05 tty0 。第一個數(shù)字是主設備 號,第二個數(shù)字是次設備號。- 分配和釋放設備編號1) 在 建 立 字 符 設 備 驅(qū) 動 時 首 先 要 獲

2、取 設 備 號 , 為 此 目 的 的 必 要 的 函 數(shù) 是 register_chrdev_region, 在 linux/fs.h 中 聲 明 : int register_chrdev_region(dev_t first, unsigned int count, char *name);first 是你想 要分配的起始設備編號, first 的次編號通 常是 0,count 是你請求的連續(xù)設備編號的 總數(shù)。 count 如果太大會溢出到下一個主設備號中。 name 是設備的名字,他會出 現(xiàn)在 /proc/devices 和 sysfs 中。操作成功返回 0,如果失敗會返回一個負的錯誤

3、碼。2) 如果明確知道設備號可用那么上一個方法可行,否則我們可以使用內(nèi)核動態(tài)分配的設 備號 int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name);dev 是個只輸出的參數(shù), firstminor 請求的第一個要用的次 編號, count和name的作用如上1)對于新驅(qū)動,最好的方法是進行動態(tài)分配3) 釋放設備號, void unregister_chrdev_region(dev_t first unsigned int count);- 文件操作 file_ope

4、rations 結(jié)構體, 內(nèi)部連接了多個設備具體操作函數(shù)。 該變量內(nèi)部 的函數(shù)指針指向驅(qū)動程序中的具體操作,沒有對應動作的指針設置為NULL。1) fops的第一個成員是 struct module *owner 通常都是設置成 THIS_MODULElinux/module.h 中定義的宏。用來在他的操作還在被使用時阻止模塊被卸載。2) loff_t (*llseek) (struct file *, loff_t, int);該方法用以改變文件中的當前讀 /寫位置該函數(shù)用返回新位置。3) ssize_t (*read) (struct file *, char _user *, size_

5、t, loff_t *);以從設備文件中讀取數(shù)據(jù),讀取成功返回讀取的字節(jié)數(shù)。4) ssize_t (*write) (struct file *, const char _user *,size_t , loff_t *); 該函數(shù)用以向設備寫入數(shù)據(jù),如果成功返回寫入的字節(jié)數(shù)。5) int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);ioctl 系統(tǒng)調(diào)用提供發(fā)出設備特定命令的方法。6) int (*open) (struct inode *, struct file *);設備文件進行的第一個操作,

6、打開設備文件。7) int (*release) (struct inode * , struct file *); 釋放文件結(jié)構函數(shù)指針。 一般初始化該結(jié)構體如下:struct file_operations fops = .owner = THIS_MODULE, .llseek= xxx_llseek, .read = xxx_read, .writexxx_write,.ioctl = xxx_ioctl, .open = xxx_open, .release = xxx_release ;PS:以上的文件操作函數(shù)指針并不是全部,只是介紹了幾個常用的操作。- 文件結(jié)構struct fi

7、le 定義在 linux/fs.h 中,是設備驅(qū)動中第二個最重要的數(shù)據(jù)結(jié)構, 此處的 file 和用戶空間程序中的 FILE 指針沒有關系。前者位于內(nèi)核空間,后者位于用戶控件。 文件結(jié)構代表一個打開的文件。 (他不特定給設備驅(qū)動 ; 系統(tǒng)中每個打開的文件 有一個關聯(lián)的 struct file 在內(nèi)核空間 )。它由內(nèi)核在 open 時創(chuàng)建,并可以傳遞給文件 件操作函數(shù),文件關閉之后,內(nèi)核釋放數(shù)據(jù)結(jié)構。1)mode_t f_mode 。確定文件讀寫模式2)loff_t f_ops 。當前讀寫位置3)unsigned int f_flags。文件標志, O_RDONL、Y O_NONBLOC,K4)

8、 struct file_operations *f_op 。關聯(lián)文件相關操作5) void *private_data。 open系統(tǒng)調(diào)用設置該指針NULL指向分配的數(shù)據(jù)。6) struct dentry *f_dentry。關聯(lián)到文件的目錄入口 dentry 結(jié)構。-inode 結(jié)構inode 結(jié)構由內(nèi)核在內(nèi)部用來表示文件。它和代表打開文件描述符的文件結(jié)構是不同的。 inode 結(jié)構包含大量關于文件的信息。作為通用規(guī)則,這個結(jié)構只有兩個成 員對驅(qū)動代碼有作用。dev_t i_rdev 。對于代表設備文件的節(jié)點,這個成員包含實際的設備編號。struct cdev *i_cdev 。內(nèi)核內(nèi)部結(jié)

9、構,代表字符設備。- 字符設備注冊在內(nèi)核調(diào)用你的設備操作前,你編寫分配并注冊一個或幾個struct cdev.struct cdev *my_cdev = cdev_alloc(); my_cdev-;ops = &my_fops;或者定義成 static 均可。對定義的 cdev 變量進行初始化,可以使用專門的函數(shù),或者使用如上的方法。cdev_init( my_cdev, &my_fops); 其實上邊的兩行代碼就是做了這個函數(shù)的工作。最后告訴內(nèi)核該 cdev。cdev_add(struct cdev *dev, dev_t num, unsigned in

10、t count);/* 上述總結(jié),到此關于設備文件相關的結(jié)構數(shù)據(jù)以及如何注冊銷毀等操作相關的 函數(shù)基本上都已經(jīng)介紹完畢。主要的還是要設計具體操作的函數(shù)來實現(xiàn)具體的 邏輯操作 */以下代碼整理、摘錄自 An droid深度探索HAL與驅(qū)動開發(fā)-李寧LED驅(qū)動篇#include#include#include#include#include#include#include#deifne DEVICE_NAME s3c6410_leds#define DEVICE_COUNT 1#define S3C6410_LEDS_MAJOR 0#define S3C6410_LEDS_MINOR 234#de

11、fine PARAM_SIZE 3static int major = S3C6410_LEDS_MAJOR;static int minor = S3C6410_LEDS_MINOR;static dev_t dev_number;static int leds_state = 1;static char *params = string1,string2,string3;static iint param_size = PARAM_SIZE;static struct class *leds_class = NULL;static int s3c6410_leds_ioctl (struc

12、t file *file, unsigned int cmd, unsigned long arg)switch (cmd)unsigned tmp;case 0:case 1:if (arg ; 4)return -EINVAL;tmp = ioread32 (S3C64XX_GPMDAT);if (cmd = 1)tmp &= (1 << arg);elsetmp |= (1 << arg);iowrite32 (tmp, S3C64XX_GPMDAT);return 0;default : return -EINVA

13、L;static ssize_t s3c6410_leds_write (struct file *file, const char _user *buf, size_t count, loff_t *ppos)unsigned tmp = count;unsigned long i = 0;memset(mem, 0, 4);if (count ; 4)tmp = 4;if (copy_from_user (mem, buf, tmp) )return -EFAULT;elsefor( i=0; i<4; i+)tmp = ioread32(S3C64XX_GPMDAT);if

14、 (memi = '1')tmp &= (1 << i);elsetmp |= (1 << i);iowrite32(tmp, S3C64XX_GPMDAT);return count;static struct file_operations dev_fops =.write.owner = THIS_MODULE, .unlocked_ioctl = s3c6410_leds_ioctl, s3c6410_leds_write;static struct cdev leds_cdev;static in

15、t leds_create_device(void)int ret = 0;int err = 0;cdev_init (&leds_cdev, &dev_fops);leds_cdev.owner = THIS_MODULE;if (major ; 0)dev_number = MKDEV(major,minor);err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVICE_NAME);if (err < 0)printk(KERN_WANRING register_chrdev_r

16、egion errorn);return errelseerr = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT, DEVICE_NAME); if(err < 0)printk (KERN_WARNING alloc_chrdev_region errorn);return err;major = MAJOR(leds_cdev.dev);major = MINOR(leds_cdev.dev);dev_number = leds_cdev.dev;ret = cdev_add(&led

17、s_cdev,dev_number, DEVICE_COUNT);leds_class = class_create (THIS_MODULE, DEVICE_NAME); device_create (leds_class, NULL, dev_number, NULL, DEVICE_NAME); return ret;static void leds_init_gpm(int leds_default)int tmp = 0;tmp = ioread32(S3C64XX_GPMCON);tmp &= (0xffff);tmp |= 0x1111;iowrite32(tmp

18、,S3C64XX_GPMCON);tmp = ioread32(S3C64XX_GPMPUD);tmp &= (0XFF);tmp |= 0xaa;iowrite32(tmp,S3C64XX_GPMPUD);tmp = ioread32(S3C64XX_GPMDAT);tmp &= (0xf);tmp |= leds_default;iowrite32(tmp, S3C64XX_GPMDAT);static leds_init( void)int ret;ret = leds_create_device();leds_init_gpm (leds_state);printk(DEVICE_NAMEtinitializedn);return ret;static void leds_destroy_device(void)device_destroy(leds_class, dev_number);if(leds_class)class_destroy(leds_class);unregister_chrdev_region(dev

溫馨提示

  • 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

提交評論