日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【Linux】Linux设备驱动开发详解:基于最新的Linux 4.0内核

發布時間:2023/12/31 linux 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux】Linux设备驱动开发详解:基于最新的Linux 4.0内核 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 Linux設備驅動概述及開發環境構建

1.1 設備驅動的作用

  • 驅使硬件設備行動

1.2 無操作系統時的設備驅動

  • 典型架構:一個無限循環中夾雜著對設備中斷的檢測或者對設備的輪詢

1.3 有操作系統時的設備驅動

  • 并發 、內存管理

1.4 Linux 設備驅動

1.4.1 設備的分類及特點

● 字符設備。
● 塊設備。
● 網絡設備。

1.4.2 Linux 設備驅動與整個軟硬件系統的關系

1.4.3 Linux 設備驅動的重點、難點

● 編寫 Linux 設備驅動要求工程師有非常好的硬件基礎,懂得 SRAM、 Flash、 SDRAM、磁盤的讀寫方式,UART、 I2C、 USB 等設備的接口以及輪詢、中斷、 DMA 的原理,PCI 總線的工作方式以及 CPU 的內存管理單元(MMU)等。
● 編寫 Linux 設備驅動要求工程師有非常好的 C 語言基礎,能靈活地運用 C 語言的結構體、指針、函數指針及內存動態申請和釋放等。
● 編寫 Linux 設備驅動要求工程師有一定的 Linux 內核基礎,雖然并不要求工程師對內核各個部分有深入的研究,但至少要明白驅動與內核的接口。尤其是對于塊設備、網絡設備、 Flash 設備、串口設備等復雜設備,內核定義的驅動體系結構本身就非常復雜。
● 編寫 Linux 設備驅動要求工程師有非常好的多任務并發控制和同步的基礎,因為在驅動中會大量使用自旋鎖、互斥、信號量、等待隊列等并發與同步機制。

2 驅動設計的硬件基礎

2.1 處理器

2.1.1 通用處理器

2.1.2 數字信號處理器

2.2 存儲器

2.3 接口與總線

串口 、I2CI2C 、SPI 、USB、以太網 、PCI 和 PCI-E 、SD 和 SDIO

2.4 CPLD 和 FPGA

2.5 原理圖分析

  • 符號 、網絡 、描述

2.6 硬件時序分析

  • 時序分析的意思是讓芯片之間的訪問滿足芯片數據手冊中時序圖信號有效的先后順序、采樣建立時間(Setup Time)和保持時間(Hold Time)的要求

2.7 芯片數據手冊閱讀方法

2.8 儀器儀表使用

  • 萬用表 、示波器 、邏輯分析儀

3 Linux 內核及內核編程

3.1 Linux 內核的發展與演變

  • 表 3.1 Linux 操作系統版本的歷史及特點
版 本時 間特 點
Linux 0.11991 年 10 月最初的原型
Linux 1.01994 年 3 月包含了 386 的官方支持,僅支持單 CPU 系統
Linux 1.21995 年 3 月第一個包含多平臺(Alpha、 Sparc、 MIPS 等)支持的官方版本
Linux 2.01996 年 6 月包含很多新的平臺支持,最重要的是,它是第一個支持 SMP(對稱多處理器)體系的內核版本
Linux 2.21999 年 1 月極大提升 SMP 系統上 Linux 的性能,并支持更多的硬件
Linux 2.42001 年 1 月進一步提升了 SMP 系統的擴展性,同時也集成了很多用于支持桌面系統的特性: USB、 PC 卡(PCMCIA)的支持,內置的即插即用等
Linux 2.6.0 ~ 2.6.392003 年 12 月~2011 年 5 月無論是對于企業服務器還是對于嵌入式系統, Linux 2.6 都是一個巨大的進步。對高端機器來說,新特性針對的是性能改進、可擴展性、吞吐率,以及對 SMP 機器 NUMA 的支持。對于嵌入式領域,添加了新的體系結構和處理器類型。包括對那些沒有硬件控制的內存管理方案的無MMU 系統的支持。同樣,為了滿足桌面用戶群的需要,添加了一整套新的音頻和多媒體驅動程序
Linux 3.0 ~ 3.19、Linux 4.0-rc1 至今2011 年 7 月至今性能優化等 開發熱點聚焦于虛擬化、新文件系統、 Android、新體系結構支持以及

3.2 內核組件

1. 進程調度

2. 內存管理

3. 虛擬文件系統

4. 網絡接口

5. 進程間通信

  • 進程間通信支持進程之間的通信, Linux 支持進程間的多種通信機制,包含信號量、共享內存、消息隊列、管道、 UNIX 域套接字等,這些機制可協助多個進程、多資源的互斥訪問、進程間的同步和消息傳遞。在實際的 Linux 應用中,人們更多地趨向于使用 UNIX 域套接字,而不是 System V IPC 中的消息隊列等機制。 Android 內核則新增了 Binder 進程間通信方式。

4 內核模塊

4.1 模塊簡介

insmod ./hello.ko rmmod hellolsmod /proc/modules /sys/module

4.2 模塊結構

4.2.1 加載函數

static int __init hello_init(void) {...return 0; }module_init(hello_init);

4.2.2 卸載函數

static void __exit hello_exit(void) {... }module_exit(hello_exit);

4.2.3 許可聲明

MODULE_AUTHOR("lin"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("A simple param Module"); MODULE_ALIAS("a simplest module");
  • 模塊參數module_param(var, int, S_IRUGO);
  • 導出符號EXPORT_SYMBOL_GPL(func); (proc/kallsyms)

5 文件系統與設備文件

6 字符設備驅動

6.1 驅動結構

6.1.1 cdev結構體

//生成dev MKDEV(int major, int minor); //major:0-19 minor:20-31 //獲取設備號 MAJOR(dev_t dev) MINOR(dev_t dev) //cdev操作 void cdev_init(struct cdev *, struct file_operations *); struct cdev* cdev_alloc(void); void cdev_put(struct cdev *); int cdev_add(struct cdev *, dev_t, unsigned); void cdev_del(struct cdev *);

6.1.2 設備號分配

int register_chrdev_region(dev_t from, unsigned count, const char *name); int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);int unregister_chrdev_region(dev_t from, unsigned count);

6.1.3 file_operations結構體

7 設備驅動中的并發控制

7.1 并發與競態

  • 臨界區:訪問共享資源的代碼段
  • 互斥:中斷屏蔽、原子操作、自旋鎖、信號量、互斥體

7.2 編譯亂序和執行亂序

  • 表 隔離指令
指令名功能描述
DMB數據存儲器隔離。DMB 指令保證: 僅當所有在它前面的存儲器訪問操作都執行完畢后,才提交(commit)在它后面的存儲器訪問操作。
DSB數據同步隔離。比 DMB 嚴格: 僅當所有在它前面的存儲器訪問操作都執行完畢后,才執行在它后面的指令(亦即任何指令都要等待存儲器訪 問操作——譯者注)
ISB指令同步隔離。最嚴格:它會清洗流水線,以保證所有它前面的指令都執行完畢之后,才執行它后面的指令。

7.3 中斷屏蔽

local_irq_disable() local_irq_enable() //與自旋鎖聯合使用 local_irq_save(flags) local_irq_restore(flags) local_bh_disable() local_bh_enable()

7.4 原子操作

7.4.1 整型原子操作

  • 設置

    void atomic_set(atomic_t *v, int i); atomic_t ATOMIC_INIT(int i);
  • 獲取

    int atomic_read(atomic_t *v);
  • 加減

    void atomic_add(int i, atomic_t *v); void atomic_sub(int i, atomic_t *v);void atomic_inc(atomic_t *v); void atomic_dec(atomic_t *v);
  • 操作后測試(為0返回true,非0返回false)

    int atomic_inc_and_test(atomic_t *v); int atomic_dec_and_test(atomic_t *v); int atomic_sub_and_test(int i, atomic_t *v);
  • 操作后返回新值

    int atomic_add_return(int i, atomic_t *v); int atomic_sub_return(int i, atomic_t *v);int atomic_inc_return(atomic_t *v); int atomic_dec_return(atomic_t *v);

7.4.2 位原子操作

7.5 自旋鎖

7.5.1 自旋鎖

spinlock_t lock; spin_lock_init(lock); spin_lock(lock); spin_trylock(lock); spin_unlock(lock);spin_lock_irq(lock); spin_unlock_irq(lock); spin_lock__irqsave(lock); spin_unlock_irqrestore(lock); spin_lock_bh(lock); spin_unlock_bh(lock);

7.5.2 讀寫鎖

7.5.3 順序鎖

  • 讀執行單元不會被寫執行單元阻塞;但寫執行單元進行寫操作時,其他寫執行單元就會自旋。

7.5.4 讀-復制-更新

  • RCU: Read-Copy-Update

    7.6 信號量

    7.7 互斥體

    7.8 完成量

8 阻塞I/O和非阻塞I/O

8.1 阻塞I/O和非阻塞I/O

fd= open("/dev/ttyS1", O_RDWR | O_NONBLOCK); fcntl(fd, F_SETFL, O_NONBLOCK);

8.1.1 等待隊列

//定義 wait_queue_head_t queue_head; //初始化 init_waitqueue_head(&queue_head); //定義及初始化 DECLARE_WAIT_QUEUE_HEAD(name) //隊列等待元素 DECLARE_WAITQUEUE(name, tsk) //操作 void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); //等待事件 wait_event(queue, condition) wait_event_interruptible(queue, condition) wait_event_timeout(queue, condition, timeout) wait_event_interruptible_timeout(queue, condition, timeout) //喚醒隊列 void wake_up(wait_queue_head_t *q); void wake_up_interruptible(wait_queue_head_t *q); //睡眠 sleep_on(wait_queue_head_t *q); interruptible_sleep_on(wait_queue_head_t *q); static ssize_t xxx_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) {...DECLARE_WAITQUEUE(wait, current);add_wait_queue(&xxx_wait, &wait);/*等待設備緩沖區可寫*/do {avail = device_writable();if (avail < 0) {if (file->f_flags & O_NONBLOCK) {ret = -EAGAIN;goto out;}__set_current_state(TASK_INTERRUPTIBLE);schedule();if (signal_pending(current)) {ret = -ERESTARTSYS;goto out;}}} while (avail < 0);device_write(); out:remove_wait_queue(&xxx_wait, &wait);set_current_state(TASK_RUNNING);reutrn ret; }

8.1.2 支持等待隊列的globalfifo

8.2 輪詢操作

8.2.1 輪詢的概念與作用

9.2.3 信號的釋放

  • 異步通知結構體

    struct xxx_dev{struct cdev cdev;...struct fasync_struct *async_queue; }
  • xxx_fasync
  • static int xxx_fasync(int fd, struct file *filp, int mode) {struct xxx_dev *dev=file->private_data;return fasync_helper(fd, filp, mode, &dev->async_queue); }
  • 釋放讀信號
  • //xxx_write if(dev->async_queue)kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
  • 從異步通知列表刪除filp
  • //xxx_release xxx_fasync(-1, filp, 0);

    9.4 Linux異步I/O

    9.4.1 AIO

    struct aiocb {int aio_fildes;?????????????? // File Descriptorint aio_lio_opcode;?????????? // Valid only for lio_listio (r/w/nop)volatile void *aio_buf;?????? // Data Buffersize_t aio_nbytes;??????????? // Number of Bytes in Data Bufferstruct sigevent aio_sigevent; // Notification Structure/* Internal fields */...}; API 函數說明
    aio_readint aio_read( struct aiocb *aiocbp ); 請求異步讀操作
    aio_errorint aio_error( struct aiocb *aiocbp ); 檢查異步請求的狀態
    aio_returnssize_t aio_return( struct aiocb *aiocbp ); 獲得完成的異步請求的返回狀態
    aio_writeint aio_write( struct aiocb *aiocbp ); 請求異步寫操作
    aio_suspendint aio_suspend( const struct aiocb *const cblist[], int n, const struct timespec *timeout ); 掛起調用進程,直到一個或多個異步請求已經完成(或失敗)
    aio_cancelint aio_cancel( int fd, struct aiocb *aiocbp ); 取消異步 I/O 請求
    lio_listioint lio_listio( int mode, struct aiocb *list[], int nent, struct sigevent *sig ); 發起一系列 I/O 操作

    9.4.2 內核AIO與libaio

    10 中斷與時鐘

    10.1 中斷與定時器

    11 內存與I/O訪問

    17 I2C、SPI、USB驅動架構類比

    18 ARM Linux設備樹

    18.1 ARM設備樹起源

    • 可描述的信息:
      • CPU的數量和類別
      • 內存基地址和大小
      • 總線和橋
      • 外設連接
      • 中斷控制器和中斷使用情況
      • GPIO控制器和GPIO使用情況
      • 時鐘控制器和時鐘使用情況

    18.2 設備樹的組成和結構

    18.2.1 DTS、DTC和DTB

  • .dts:device tree source

    1.1 Soc共用部分:.dtsi (/include/ “s3c24440.dtsi”)

    1.2 模板

    /* root節點 */ / {node1 {a-string-property = "A string";a-string-list-property = "first string", "second string";a-byte-data-property = [0x01 0x23 0x34 0x56];child-node1 {first-child-property;second-child-property = <1>;a-string-property = "Hello, world";};child-node2 {};};node2 {an-empty-property;a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */child-node1 {};}; };
  • .dtc:device tree compiler

  • .dtb:Device Tree Blob

  • 總結

    以上是生活随笔為你收集整理的【Linux】Linux设备驱动开发详解:基于最新的Linux 4.0内核的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。