1. 程式人生 > >linux字元裝置驅動開發模板及Makefile

linux字元裝置驅動開發模板及Makefile

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

//=======================字元裝置驅動模板開始 ===========================//
#define CHAR_DEV_DEVICE_NAME   "char_dev"   // 是應當連線到這個編號範圍的裝置的名字,出現在/proc/devices和sysfs中
#define CHAR_DEV_NODE_NAME    "char_dev"   // 節點名,出現在/dev中
#define CHAR_DEV_CLASS_NAME   "char_dev_class"   //出現在/sys/devices/virtual/和/sys/class/中
struct class *char_dev_class;  // class結構用於自動建立裝置結點 
static int major = 0;       // 0表示動態分配主裝置號,可以設定成未被系統分配的具體的數字。
static struct cdev char_dev_cdev;// 定義一個cdev結構

// 進行初始化設定,開啟裝置,對應應用空間的open 系統呼叫 
int char_dev_open(struct inode *inode, struct file *filp)
{
    //  這裡可以進行一些初始化
    printk("char_dev device open.\n");
    return 0;
}
 
// 釋放裝置,關閉裝置,對應應用空間的close 系統呼叫
static int char_dev_release (struct inode *node, struct file *file)
{
    //  這裡可以進行一些資源的釋放
    printk("char_dev device release.\n");
    return 0;
}
// 實現讀功能,讀裝置,對應應用空間的read 系統呼叫
/*__user. 這種註解是一種文件形式, 注意, 一個指標是一個不能被直接解引用的
使用者空間地址. 對於正常的編譯, __user 沒有效果, 但是它可被外部檢查軟體使
用來找出對使用者空間地址的錯誤使用.*/
ssize_t char_dev_read(struct file *file,char __user *buff,size_t count,loff_t *offp)
{
    printk("char_dev device read.\n");
    return 0;
}
// 實現寫功能,寫裝置,對應應用空間的write 系統呼叫
ssize_t char_dev_write(struct file *file,const char __user *buff,size_t count,loff_t *offp)
{
    printk("char_dev device write.\n");
    return 0;
}
 
// 實現主要控制功能,控制裝置,對應應用空間的ioctl系統呼叫
static int char_dev_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{  
    printk("char_dev device ioctl.\n");
    return 0;
}

//  file_operations 結構體設定,該裝置的所有對外介面在這裡明確,此處只寫出了幾常用的
static struct file_operations char_dev_fops = 
{
    .owner = THIS_MODULE,
    .open  = char_dev_open,      // 開啟裝置 
    .release = char_dev_release, // 關閉裝置 
    .read  = char_dev_read,      // 實現裝置讀功能 
    .write = char_dev_write,     // 實現裝置寫功能 
    .ioctl = char_dev_ioctl,     // 實現裝置控制功能 
};

// 裝置建立子函式,被char_dev_init函式呼叫  
static void char_dev_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops)
{
    int err, devno = MKDEV(major, minor);
    cdev_init(dev, fops);//對cdev結構體進行初始化
    dev->owner = THIS_MODULE;
    dev->ops = fops;
    err = cdev_add(dev, devno, 1);//引數1是應當關聯到裝置的裝置號的數目. 常常是1
    if(err)
    {
        printk(KERN_NOTICE "Error %d adding char_dev %d.\n", err, minor);
    }
    printk("char_dev device setup.\n");
}

//   裝置初始化 
static int char_dev_init(void)
{
    int result;
    dev_t dev = MKDEV(major, 0);//將主次編號轉換為一個dev_t型別
    if(major)
    {
        // 給定裝置號註冊
        result = register_chrdev_region(dev, 1, CHAR_DEV_DEVICE_NAME);//1是你請求的連續裝置編號的總數
        printk("char_dev register_chrdev_region.\n");
    }
    else
    {
        // 動態分配裝置號 
        result = alloc_chrdev_region(&dev, 0, 1, CHAR_DEV_DEVICE_NAME);//0是請求的第一個要用的次編號,它常常是 0
        printk("char_dev alloc_chrdev_region.\n");
        major = MAJOR(dev);
    }
    if(result < 0)//獲取裝置號失敗返回
    {
        printk(KERN_WARNING "char_dev region fail.\n");
        return result;
    }
    char_dev_setup_cdev(&char_dev_cdev, 0, &char_dev_fops);
    printk("The major of the char_dev device is %d.\n", major);
    //==== 有中斷的可以在此註冊中斷:request_irq,並要實現中斷服務程式 ===//
    // 建立裝置節點
    char_dev_class = class_create(THIS_MODULE,CHAR_DEV_CLASS_NAME);
    if (IS_ERR(char_dev_class))
    {
        printk("Err: failed in creating char_dev class.\n");
        return 0;
    }
    device_create(char_dev_class, NULL, dev, NULL, CHAR_DEV_NODE_NAME);
    printk("char_dev device installed.\n");
    return 0;
}

// 設備註銷 
static void char_dev_cleanup(void)
{
    device_destroy(char_dev_class,MKDEV(major, 0));
    class_destroy(char_dev_class);
    cdev_del(&char_dev_cdev);//字元裝置的登出
    unregister_chrdev_region(MKDEV(major, 0), 1);//裝置號的登出
    //========  有中斷的可以在此登出中斷:free_irq  ======//
    printk("char_dev device uninstalled.\n");
}

module_init(char_dev_init);//模組初始化介面
module_exit(char_dev_cleanup);//模組登出介面
//所有模組程式碼都應該指定所使用的許可證,該句不能省略,否則模組載入會報錯
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Author");
MODULE_DESCRIPTION("Driver Description");

相關推薦

linux字元裝置驅動開發模板Makefile

#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/device.h> //

Linux 字元裝置驅動開發--記憶體讀寫操作

學習Linux的累計時間已經有兩年多了,工作關係,學習的過程總是斷斷續續的,現在整理一下,下面要分享的是一個簡單的linux驅動程式,將記憶體當作一個虛擬的裝置去讀寫,沒有什麼實際的用處,像hello wold!程式一樣,我們簡單體會一下linux驅動程式的特點,Linux

linux字元裝置驅動一般模板

#include <linux/miscdevice.h> //標頭檔案有很多,可以根據具體的情況新增刪除,這裡給一個例子。 #include <linux/delay.h> #include <asm/irq.h> #include

從零開始寫linux字元裝置驅動程式(一)(基於友善之臂tiny4412開發板)

從這篇博文開始,我將開始手把手教會大家寫linux裝置驅動程式這是開篇,如何來寫第一個字元裝置驅動程式。首先,寫一個最簡單的字元裝置驅動程式需要什麼?或者說我們需要了解什麼?1、每一個字元裝置至少需要有一個裝置號2、裝置號 = 主裝置號 + 次裝置號3、同一類裝置的主裝置號一

Linux 字元裝置驅動結構(三)—— file、inode結構體chardevs陣列等相關知識解析

       先看下面這張圖,這是Linux 中虛擬檔案系統、一般的裝置檔案與裝置驅動程式值間的函式呼叫關係;         上面這張圖展現了一個應用程式呼叫字元裝置驅動的過程, 在裝置驅動程式的設計中,一般而言,會關心 file 和 inode 這兩個結構體  

linux字元裝置驅動模板(新標準)

//////////////gpio驅動模板//////////////////////////////static int major = 0;static void gpio_setup_cdev(struct cdev *dev, int minor, struct f

Linux 字元裝置驅動結構(三)—— file、inode結構體chardevs陣列等相關知識解析[轉載]

       先看下面這張圖,這是Linux 中虛擬檔案系統、一般的裝置檔案與裝置驅動程式值間的函式呼叫關係;        上面這張圖展現了一個應用程式呼叫字元裝置驅動的過程, 在裝置驅動程式的設計中,一般而言,會關心 file 和 inode 這兩個結構體       

Linux字元裝置驅動模型--字元裝置的註冊

當我們編寫字元裝置驅動程式的時候,在進行字元裝置物件cdev的分配、初始化,裝置號的註冊這些初始化階段之後,就可以將它加入到系統中,這樣才能使用這個字元裝置。將一個字元裝置加入到系統中呼叫的函式時cdev_add,核心原始碼如下: int cdev_add(struct cdev *

Linux 字元裝置驅動結構(二)—— 自動建立裝置節點

      上一篇我們介紹到建立裝置檔案的方法,利用cat /proc/devices檢視申請到的裝置名,裝置號。 第一種是使用mknod手工建立:mknod filename type major minor 第二種是自動建立裝置節點:利用u

Linux 字元裝置驅動結構(一)—— cdev 結構體、裝置號相關知識解析

一、字元裝置基礎知識 1、裝置驅動分類       linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。使用驅動程式: 字元裝置:是指只能一個位元組一個位元組讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後資料。

Linux字元裝置驅動註冊三種方法以及核心分析

       Linux驅動是使用者訪問底層硬體的橋樑,驅動有可以簡單分成三類:字元裝置、塊裝置、網路裝置。其中最多的是字元裝置,其中字元裝置的註冊方法主要有三種:雜項設備註冊、早期字元設備註冊、標準字元設備註冊。以及詳細介紹各類方法註冊。 開發環境: PC:WMwork

linux字元裝置驅動模型

一.雜項裝置驅動模型 雜項的主裝置號固定為10,只有255個次裝置號。可以直接生成驅動核心。 1.需要確定每個模型都會用到的檔案操作方法集合指標 2.確定核心的結構體 static struct miscdevice abc 確定三個引數,第一個為次裝置號,第二個是次裝

Linux字元裝置驅動

一、字元裝置基礎 字元裝置:是指只能一個位元組一個位元組進行讀寫操作的裝置,不能隨機讀取裝置中的某一資料、讀取資料要按照先後資料。字元裝置是面向流的裝置,常見的字元裝置有滑鼠、鍵盤、串列埠、控制檯和LED等。 一般每個字元裝置或者塊裝置都會在/dev目錄(可以是任意目錄,這樣是為了統一)下對應一個裝置檔案

1--linux字元裝置驅動

1. 編寫一個簡單的字元裝置框架 *****hello.c***** #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <

Linux 網路裝置驅動開發(三) —— 網路裝置驅動基本原理和框架

一、協議棧層次對比 二、Linux網路子系統     Linux網路子系統的頂部是系統呼叫介面層。它為使用者空間提供的應用程式提供了一種訪問核心網路子系統的方法(socket)。位於其下面是一個協議無關層,它提供一種通用的方法來使用傳輸層協議。然後是具體協議的實現,在Lin

linux字元裝置驅動程式scull例項

這個例子還是比較完整的講述了字元驅動開發的過程,尤其字元驅動程式的設計流程,包括測試在內。 【1.系統環境】 該驅動程式在UBUNTU10.04LTS編譯通過,系統核心為linux-2.6.32-24(可使用uname -r 命令來檢視當前核心的版本號) 由於安裝UBUNTU10.04LTS時,沒有安裝LI

深入理解Linux字元裝置驅動

文章從上層應用訪問字元裝置驅動開始,一步步地深入分析Linux字元裝置的軟體層次、組成框架和互動、如何編寫驅動、裝置檔案的建立和mdev原理,對Linux字元裝置驅動有全面的講解。本文整合之前發表的《L

Linux字元裝置驅動程式的一個簡單示例

一.原始碼: // memdev.c #define MEMDEV_MAJOR 254 /*預設的mem的主裝置號*/ #define MEMDEV_NR_DEVS 2 /*裝置數*/ #define MEMDEV_SIZE 4096 /*mem裝置描述結構體

Linux字元裝置驅動剖析

一、先看看裝置應用程式 1.很簡單,open裝置檔案,read、write、ioctl,最後close退出。如下: intmain(int argc ,char *argv[]){ unsigned char val[1] = 1; int fd =open("/

OpenWRT(七)字元裝置驅動開發

一、字元裝置驅動 我們之前學習過驅動程式的開發,接下來我們接著深入學習字元裝置驅動程式的開發。字元裝置驅動是比較簡單的一種驅動。主要在於實現init、exit、open、read、write等函式。 二、字元裝置驅動例項 1、在package/kern