【linux】驅動-14-異步通知



前言

14. 異步通知

本章內容為驅動基石之一
驅動只提供功能,不提供策略

阻塞與非阻塞是 APP 詢問 驅動設備。
異步通知是 驅動設備 主動通知 APP。

原文:https://www.cnblogs.com/lizhuming/p/14918049.html

14.1 異步通知的一些概念

異步通知:一旦設備就緒,則主動通知APP,這樣APP就不用輪詢查詢設備狀態了。

異步IO:APP 發起 IO 請求后,立即返回。然后再查詢 IO 完成情況,或者 IO 完成后被調回。這個過程叫做 異步IO

14.2 Linux 信號

可以使用 信號 來進行進程間通信(IPC)。

Linux信號表:

  • 路徑參考:include\uapi\asm-generic\signal.h
信號 說明
SIGHUP 1 掛起
SIGINT 2 中斷中斷
SIGQUIT 3 終端退出
SIGILL 4 無效命令
SIGTRAP 5 跟蹤陷阱
SIGABRT 6 異常終止信號,和 SIGIOT 同義
SIGIOT 6 IOT陷阱,和 SIGABRT 同義
SIGBUS 7 BUS錯誤
SIGFPE 8 浮點異常
SIGKILL 9 強制終止
SIGUSR1 10 用戶自定義信號1
SIGSEGV 11 無效的內存段處理
SIGUSR2 12 用戶自定義信號2
SIGPIPE 13 半關閉管道的寫操作
SIGALRM 14 計時器到期
SIGTERM 15 終止
SIGSTKFLT 16 堆棧錯誤
SIGCHLD 17 子進程已經停止或退出
SIGCONT 18 如果停止了,繼續執行
SIGSTOP 19 停止執行
SIGTSTP 20 終端停止信號
SIGTTIN 21 后台進程需要從終端讀取輸入
SIGTTOU 22 后台進程需要從終端寫出
SIGURG 23 緊急的套接字事件
SIGXCPU 24 超額使用CPU分配的時間
SIGXFSZ 25 文件尺寸超額
SIGVTALRM 26 虛擬時鍾信號
SIGPROF 27 時鍾信號描述
SIGWINCH 28 出口尺寸變化
SIGIO 29 I/O
SIGPOLL SIGIO I/O

除了 SIGSTOPSIGKILL 兩個信號外,進程能夠忽略或捕獲其它所有信號。
一個信號被捕獲的意思是當一個信號到達時有相應代碼處理它。
如果一個信號沒有被這進程所捕獲,內核將采取默認行為處理。

14.3 信號接收

14.4 使用流程

14.4.1 參考流程圖

流程圖參考韋東山:

14.4.2 分析&編程步驟

分析中的細節部分會在后本節后面說明
分析:

  • ②:綁定信號與回調函數。使用sighandler_t signal(int signum, sighandler_t handler)

  • ③:把 APP PID 告訴內核。同時,該 PID 會保存到該驅動的內核文件 file 結構體中。

  • ④:讀取該驅動程序文件的 Flag。

  • ⑤:設置 Flag 里面的 FASYNC 位為 1。當 FASYNC 位發生變化時,該驅動會調用驅動操作 drv_fasync 函數。

  • ⑥:驅動開發者實現的函數。主要是調用 fasync_helper 函數。

  • ⑦:調用 fasync_helper() 函數,主要是把 驅動程序內核文件 file 結構體綁定到 button_async->fa_file 中。而 file 包含了 APPPID。所以發送信號時,只需要使用 button_async 作為參數即可。

  • ⑩:發送信號給對應的 APP。參數為 button_async

  • 注:button_async 結構體由驅動開發者創建,維護。

APP 信號編程步驟

  • ①:編寫信號回調函數。
  • ②:綁定信號與回調函數。
  • ③:打開驅動。
  • ④:獲取 PID ,告知內核。
  • ⑤:獲取進程狀態值。
  • ⑥:當前狀態值添加異步功能,觸發調用驅動異步處理函數。

KERNEL 信號編程步驟

  • ①:定義異步結構體。
  • ②:實現異步操作函數,並把該函數填充到設備內核驅動操作結構體中。
    • 該函數內容主要調用 fasync_helper() 函數,初始化異步結構體。(把 file ,內核PID,交給異步結構體
  • ③:發送信號。

14.4.3 使用函數說明

14.4.3.1 相關結構體及參考模型

APP 模型 截段:

......

/* 設置信號 SIGIO 的處理函數 */
signal(SIGIO, sigio_signal_func);

fcntl(fd, F_SETOWN, getpid());     /* 將當前進程的進程號告訴給內核  */ 
flags = fcntl(fd, F_GETFD);           /* 獲取當前的進程狀態 */ 
fcntl(fd, F_SETFL, flags | FASYNC); /* 設置進程啟用異步通知功能。會調用驅動中的 drv_fasync 函數 */

......

fasync_struct

  • (在內核源碼中,目前沒有去找內核文檔該結構體內容的相關信息)
struct fasync_struct {
	rwlock_t		fa_lock;
	int			      magic;
	int			      fa_fd;
	struct fasync_struct	*fa_next; /* singly linked list */
	struct file		*fa_file;
	struct rcu_head		fa_rcu;
};
14.4.3.2 signal 函數

APP 使用

函數原型sighandler_t signal(int signum, sighandler_t handler) :

  • 功能:綁定信號與回調函數。
  • signum:信號類型。除 SIGKILLSIGSTOP 外的任何一種信號。
  • handler:該參數有三種類型。
    • ①:SIG_IGN 類型。表示忽略該信號。
    • ②:SIG_DFL 類型。表示恢復對信號的系統默認處理。
    • ③:sighandler_t 類型的函數指針。即是回調函數。typedef void (*sighandler_t)(int);
  • 注:APP 收到信號執行回調函數時,signum 參數會被傳到回調函數的形參傳遞給回調函數。即是回調函數的形參就是信號類型。
14.4.3.3 kill_fasync 函數

KERNEL 使用

函數原型void kill_fasync(struct fasync_struct **fp, int sig, int band) :

  • 功能:發送信號給 fp 參數綁定的進程。(by PID
  • 參考路徑:linux-5.12.8\fs\fcntl.c
  • fp:需要操作的 fasync_struct
  • sig:信號類型。
  • band:可讀時設置為 POLL_IN;可寫時設置為 POLL_OUT。當然該參數還可以填
    POLL_MSG。以上三個值在應用層接收時,si_code 分別為 0x01、0x02、0x03。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM