Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 字元裝置驅動開發基礎:從檔案操作介面到完整程式範本

編輯:Linux 教學

字元裝置驅動是 Linux 驅動開發的入門基礎。本文系統介紹裝置驅動角色、字元/區塊裝置差異、裝置檔案與主/次裝置號、file_operations 統一 I/O 介面,並提供完整的三個檔案範本(test.h、test.c、ledtest.c)實作 LED 控制驅動與用戶測試程式。

一、核心概念

  • 裝置驅動:核心與硬體間介面,為應用層屏蔽硬體細節
  • 字元裝置:位元組流、循序存取、通常無緩衝(如序列埠、LCD、鍵盤)
  • 區塊裝置:固定大小區塊、隨機存取、有緩衝(如硬碟)
  • 裝置檔案:/dev/xxx,應用程式以檔案操作存取硬體
  • 主/次裝置號:主號區分裝置類型,次號區分同類多裝置

二、file_operations 統一介面


struct file_operations {
    struct module *owner;
    loff_t (*llseek)(struct file *, loff_t, int);
    ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
    int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
    int (*open)(struct inode *, struct file *);
    int (*release)(struct inode *, struct file *);
    // ... 其他操作
};

不同檔案類型實作不同 file_operations,應用程式統一呼叫 open/read/write/ioctl/close,VFS 自動分派至對應驅動。

三、驅動生命週期與應用程式互動

  1. 系統載入驅動(insmod)
  2. 應用程式 open() → 驅動 open()
  3. 應用程式 ioctl()/read()/write() → 驅動對應函數
  4. 應用程式 close() → 驅動 release()
  5. 系統卸載驅動(rmmod)

四、完整程式範本

1. test.h — 共用標頭


#ifndef __CONFIG_H
#define __CONFIG_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define LED_MAJOR_NR 231
#define DEVICE_NAME "led"
#define SET_LED_OFF 0
#define SET_LED_ON  1

#endif

2. test.c — 核心模組驅動


#include "test.h"

static int led_open(struct inode *inode, struct file *filp) {
    // 初始化硬體、模組計數器+1
    MOD_INC_USE_COUNT;
    return 0;
}

static int led_release(struct inode *inode, struct file *filp) {
    // 清理硬體、模組計數器-1
    MOD_DEC_USE_COUNT;
    return 0;
}

static int led_ioctl(struct inode *inode, struct file *filp,
                     unsigned int cmd, unsigned long arg) {
    switch (cmd) {
        case SET_LED_ON:
            // 寫入暫存器點亮 LED
            break;
        case SET_LED_OFF:
            // 寫入暫存器熄滅 LED
            break;
        default:
            return -EINVAL;
    }
    return 0;
}

static struct file_operations led_fops = {
    .owner   = THIS_MODULE,
    .open    = led_open,
    .release = led_release,
    .ioctl   = led_ioctl,
};

int init_module(void) {
    int result = register_chrdev(LED_MAJOR_NR, DEVICE_NAME, &led_fops);
    if (result < 0) return result;
    printk("LED driver loaded\n");
    return 0;
}

void cleanup_module(void) {
    unregister_chrdev(LED_MAJOR_NR, DEVICE_NAME);
    printk("LED driver unloaded\n");
}

3. ledtest.c — 用戶空間測試程式


#include 
#include 
#include 
#include "test.h"

int main() {
    int fd = open("/dev/led", O_RDWR);
    if (fd < 0) {
        perror("open /dev/led");
        return 1;
    }

    printf("Turn ON LED\n");
    ioctl(fd, SET_LED_ON, 0);
    sleep(2);

    printf("Turn OFF LED\n");
    ioctl(fd, SET_LED_OFF, 0);

    close(fd);
    return 0;
}

編譯:gcc ledtest.c -o ledtest,執行前需 mknod /dev/led c 231 0 建立裝置節點。

五、關鍵點提醒

  • 核心空間用 printk,用戶空間用 printf
  • 用戶緩衝區存取必須用 copy_to_user/copy_from_user
  • 暫存器操作參考具體晶片資料手冊(如 S3C44B0)
  • 2.6 核心模組計數器改用 try_module_get()/module_put()
Copyright © Windows教程網 All Rights Reserved