天天看點

【驅動】linux驅動程式開發及環境搭建

1.mystery引入

   1)裝置驅動程式對外提供如下的功能:

       1)裝置初始化:對硬體裝置進行初始化操作

       2)資料交換:資料交換包括由核心層向硬體層傳送資料、從硬體層讀取資料到核心層;

                     應用程式向裝置檔案傳送資料、裝置檔案向應用程式回送資料

       3)裝置請求與檢測:檢測各硬體裝置的各種參數資訊、錯誤資訊

       4)裝置釋放:裝置使用完後的資源釋放

   2)驅動一般分為字元裝置驅動、塊裝置驅動和網絡裝置驅動

       1)字元裝置驅動:可以按位元組操作的方式對裝置檔案進行存取,一般對應慢速裝置,例如序列槽裝置

       2)塊裝置驅動:是按資料塊的方式對裝置檔案進行通路,一般對應高速裝置,例如DMA

       3)網絡裝置驅動:是面向網卡裝置,用于處理網絡封包的發送與接收

   3)字元裝置與塊裝置均可以通過通路檔案的方式進行操作,二者唯一的不同的是Linux對于它們的資料管理方式的不同。

   4)應用程式對字元裝置的I/O操作,會直接傳送到核心驅動層,而塊裝置的操作,則是需要借助于中間的緩存區,以間接的方式進行資料交換。

2.環境搭建及測試

   1)下載下傳對應版本的核心源碼包

   2)因為現在對核心還不是很熟,加上核心源碼比較大,是以我先下一個核心的開發包

   3)終端:

sudo yum install kernel-devel      

   4)如圖

【驅動】linux驅動程式開發及環境搭建

   5)環境搭建好了,問題又來了。。uname -r 的結果和我系統核心版本不一樣。。

   這裡我直接用我系統的核心版本号作測試了,我的系統核心版本是3.6.10-2.fc17.i686

   6)第一個版本的Makefile檔案如下:

obj-m:=chardev.o
KDIR:=/lib/modules/3.6.10-2.fc17.i686/build
SRCPWD:=$(shell pwd)
all:
    make -C $(KDIR) M=$(SRCPWD) modules
clean:
    rm -rf chardev.o      

   7)編譯結果如圖

【驅動】linux驅動程式開發及環境搭建

3.驅動驗證

   1)裝置安裝

       當安裝驅動時,又出現錯誤了,糾結。。錯誤:編譯使用的核心和目前系統的核心不一樣!

   2)反思

      1)這時我才想起,前斷時間我更新了下系統,當時把系統核心更新到了3.6,但是無法進入系統,是以我直接把grub項的3.6核心的引導删掉了,現在打開grub查找錯誤

      2)grub中關于核心3.6開機引導項内容如下:

【驅動】linux驅動程式開發及環境搭建

      3)看了這斷代碼,對更新後新核心無法進入系統的原因就明了了,我在想,為什麼更新核心的時候沒有制作initrd

      4)于是我退後一步,自己制作initrd,終端下:

mkinitrd initrd-3.6.6 3.6.6      

      (先切換到linux-3.6.6的上一級目錄),由于系統更新核心時已經編譯過核心鏡像和核心子產品了,并且也已經安裝過核心子產品了

      5)是以我要做的就是将initrd複制到boot目錄下,然後再添加新的引導項

      6)在上圖 echo 'Loading Fedora (3.6.10-2.fc17.i686)' 的下一行添加自己制作的initrd,代碼:initrd/boot/initrd-3.6.10-2.fc17.i686.img

      7)重新開機電腦,OK,成功引導進行新核心,但是有很多地方不盡人意

         1)電腦需要重裝顯示卡驅動,分辨率太低

         2)無法聯網,需要重裝網卡驅動

         3)無法挂載FAT格式的盤

         4)無法挂載NTFS格式的盤

      8)是以,我還是決定用3.3的核心,隻是在3.6下作驅動程式測試

4.驅動測試

   1)如圖所示:

【驅動】linux驅動程式開發及環境搭建

   2)驅動裝置建立好後,編寫一個程式驗證下

   3)效果如圖:

【驅動】linux驅動程式開發及環境搭建

   4)這裡出現OPEN錯誤和READ錯誤,但是卻又讀出了驅動函數的内容,表示驅動還是成功的,由于這個核心開始出現的不盡人意,也沒有去調試這個錯誤的原因

5.驅動源代碼

#include <linux/kernel.h>
#include <linux/fs.h>                
#include <linux/module.h>
#include <asm/uaccess.h>             
#include <linux/cdev.h>               
static int char_read(struct file *filp,char __user *buffer,size_t,loff_t *);      
static int char_open(struct inode *,struct file *);                                    
static int char_write(struct file *filp,const char __user *buffer,size_t ,loff_t*);
static int char_release(struct inode *,struct file *);                                 
static int device_open_count;                   
static int major;
static const struct file_operations file_ops =
{
    .read = char_read,
    .write = char_write,
    .open = char_open,
    .release = char_release,
};
static int __init char_init(void)
{
    int value;
    major = 0;
    value = register_chrdev(major, "chardev", &file_ops);
    if (value < 0)
    {
        printk("無法注冊裝置");
        return value;
    }
    if (major == 0)
        major = value;
    return 0;
}
static int char_open(struct inode *inode,struct file *file)
{
    if(device_open_count == 0)
        device_open_count++;
    else
    {
        printk("裝置已經被打開\n");
        return -1;
    }
    try_module_get(THIS_MODULE);
    return 0;
}
static int char_release(struct inode *inode,struct file *file)
{
    device_open_count--;
    module_put(THIS_MODULE);
    return 0;
}
static int char_read(struct file *filp,char __user *buffer,size_t length,loff_t *offset)
{
    if(length < 0)
        return -1;
    else if(length > 12)
        length = 12;
    if(copy_to_user(buffer,"Hello Linux!",length))
        return length;
    return -1;
}
static int char_write(struct file *filp,const char __user  *buffer,size_t length,loff_t *offset)
{
    return 0;
}
static void __exit module_close(void)
{
    unregister_chrdev(major, "chardev");
}
module_init(char_init);
module_exit(module_close);      

6.Makefile源代碼

obj-m:=chardev.o
KDIR:=/lib/modules/$(shell uname -r)/build
SRCPWD:=$(shell pwd)
all:
    make -C $(KDIR) M=$(SRCPWD) modules
clean:
    rm -rf chardev.o      

7.測試程式源代碼

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(void)
{
    int testdev;
    int i,rf=0;
    char buf[15];
    memset(buf, 0, sizeof(buf));
    testdev = open("/dev/chardev",O_RDWR);
    if ( testdev == -1 )
    {
        perror("open\n");
        exit(0);
    }
    rf=read(testdev,buf,11);
    if(rf<0)
        perror("read error\n");
    printf("R:%s\n",buf);
    close(testdev);
    return 0;
}      

本文出自 “成鵬緻遠” 部落格,請務必保留此出處http://infohacker.blog.51cto.com/6751239/1155153

QQ聯系方式:[email protected]

【驅動】linux驅動程式開發及環境搭建

出處:lcw.cnblogs.com

郵箱:[email protected]

本文申明:本文版權歸作者和部落格園共有,歡迎轉載,轉載請注明出處.