LINUX IIO子系統分析之四 IIO EVENT設計分析

2020-09-05 jerry的編程路

上一章我們介紹了iio子系統中的iio trigger模塊,本章我們將介紹iio event模塊,iio event主要用於閾值監測、自由落體監測等監測功能。因為IIO EVENT涉及IIO DEVICE字符設備文件操作,因此本章內容主要分為如下幾部分:

一、 IIO DEVICE字符設備文件操作接口

二、IIO EVENT設計分析

三、IIO EVENT相關接口說明

一、 IIO DEVICE字符設備文件操作接口

在IIO 子系統中,每一個IIO DEVICE均會創建一個字符設備文件,名稱為/dev/iio:deviceX,該字符設備文件節點在iio_device_register中調用cdev_init、cdev_add完成字符設備文件節點的創建,且文件操作接口為iio_buffer_fileops(而藉助sysfs的kobject uevent,則會將cdev add的信息發送給應用程式,應用層的mdev/udev接收到cdev add的uevent之後,則會調用mknod完成字符設備文件節點的創建,詳細內容可參考我之前寫的字符設備文件專欄的內容《》)。如下即是/dev/iio:deviceX的訪問流程,應用程式通過open/read/poll/ioctl接口則會調用內核中VFS提供的操作接口,最終則調用iio_buffer_fileops中定義的接口。

iio_buffer_fileops的定義如下

問題來了,iio device對應的字符設備文件節點主要提供哪些服務呢?

主要提供兩方面的內容:

  1. 提供對iio device各通道連續採集數據的讀取操作(前提是該iio device的某些通道提供了iio buffer功能);
  2. 提供創建event數據讀取對應的匿名字符設備文件節點的功能(通過ioctl功能,則創建一個匿名的字符設備文件節點,用於進行iio device各通道相關的event數據的讀取功能)。所謂匿名即該字符設備文件節點並不會顯示在文件系統中(無法在應用層中找到該文件名稱),且一個iio device同一時刻僅可創建一個匿名字符設備文件節點。

二、IIO EVENT設計分析

iio event相關的數據結構

struct iio_event_interface是iio event相關的數據結構,該數據結構的定義如下

該數據結構主要是對event子模塊的定義,其中:

  1. 等待隊列wait,當應用程式讀取觸發事件信息時,若當前無數據可讀,則將當前進程加入到該等待隊列,待調用iio_push_event將觸發事件信息加入kfifo後,則wakeup該隊列中的進程;
  2. 定義kfifo,存儲所有觸發的事件信息,供應用程式獲取;
  3. 將even子模塊動態定義的event attribute均添加至該鍊表中(屬性名稱格式為{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_{ev_type}_{ev_dir}_{ev_info});
  4. flags標記該event是否已使能(即應用程式是否通過ioctl調用創建一個匿名fd,若使能則置位IIO_BUSY_BIT_POS)

iio event fd創建

IIO event數據信息也是通過字符設備文件節點與應用程式進行交互的,但就像上面所說的,iio event數據讀取對應的字符設備文件節點是一個匿名字符設備文件節點,且必須藉助字符設備文件節點/dev/iio:deviceX的ioctl方可創建。創建流程如下圖所示。藉助字符設備文件/dev/iio:deviceX提供的ioctl,即創建一個匿名的文件節點,並返回該文件節點對應的event detect fd。

而event detect fd的文件操作接口的定義如下,提供event detect信息的讀取及是否可讀監控接口poll。


event 檢測及讀取流程

針對event 信息而言,主要就涉及event檢測、event信息讀取兩部分,這兩部分的關聯如下圖所示:

  1. 應用程式可直接通過read接口讀取event信息(若event信息存在則讀取檢測到的event信息;若event信息不存在且fd設置為阻塞讀方式,則將該讀取進程休眠,加入到event的wait隊列中);
  2. 應用程式可通過select或者epoll檢測event fd是否可讀,最終會調用event fd的poll接口,加入到event的等待隊列中;
  3. 當iio device檢測到某一個事件後,則通過中斷(或其他的方式通知cpu)通知cpu,cpu則調用中斷處理函數處理中斷,在中斷處理函數中讀取檢測到的event,然後調用iio_push_event將event加入到iio device對應event子模塊的kfifo中,並wakeup event的wait隊列,這樣就喚醒了上述1和2中sleep的進程,進程即可進行event事件的讀取操作。



備註:在IIO子系統中,針對iio event,也設計與iio trigger的關聯,即由iio trigger觸發event的detect操作。若將iio event與iiotrigger關聯,則執行的流程大致如下所述:

  1. 為iio event定義中斷處理接口,並賦值給struct iio_dev的pollfunc_event成員(struct iio_poll_func *);
  2. 從iio trigger中申請一個虛擬的irq,並完成對應中斷處理函數的註冊(即上述1中的pollfunc_event);
  3. 註冊一個iio trigger,用於處理iio device檢測的event,則調用iio trigger 提供的iio_trigger_poll接口,由該接口調度iio trigger中所有申請的虛擬irq的中斷處理函數;
  4. pollfunc_event接口中讀取檢測的event接口,然後wakeup event wait隊列。

以下即是使用trigger-event方式的event detect檢測及讀取流程,相比上面的流程而言,則增加了虛擬irq的中斷處理流程,而針對event信息而言,一般也就是出現告警等信息而檢測的,並不像連續的數據採集那樣頻繁讀取,因此這一種方式的event信息檢測及讀取流程並沒有多少iio device driver採用,iio device driver一般使用上面設計的檢測及讀取流程。


三、IIO EVENT相關接口說明

iio event相關的sysfs屬性的創建接口

iio_device_register_eventset接口用於創建iio event相關的event屬性,該接口主要由iio_device_register接口調用,主要是根據struct iio_event_spec *event_spec中定義的變量,創建對應的event屬性,

下面是我實現的虛擬溫度傳感器晶片定義的event信息,其創建了溫度上限告警、溫度下限告警相關的屬性,主要包括溫度上限檢測使能、溫度下限檢測使能、溫度上限告警值設置及讀取、溫度下限告警值設置及讀取等屬性。

event屬性的名稱格式為{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_{ev_type}_{ev_dir}_{ev_info}),針對我們上述定義的event屬性,其生成的屬性文件名稱如下所示,生成的屬性文件也是符合該格式

的。


event push接口

iio_event_poll接口主要實現將event信息放入event的kfifo中,並wakeup event wait queue,然後應用程式即可讀取該event信息。

event chrdev ops

iio_event_chrdev_fileops即為event fd的文件操作接口,我們在上面已經說明,此處不再贅述。

以上即是iio event的主要內容,針對iio device driver而言,僅需要實現struct iio_event_spec *類型的變量定義event的sysfs屬性,並在檢測到event之後,調用iio_event_poll將event信息壓入event kfifo中即可。相對來說這部分驅動實現還是很簡單的,而我們上面介紹的則是iio event內部的設計實現。下一章介紹iio buffer的設計實現。

相關焦點

  • LINUX IIO子系統專欄分析之一 IIO子系統概述
    從本章開始,我們進行IIO子系統專欄的分析文檔,本次IIO子系統專欄分析文檔大概包含如下幾章:一、 IIO子系統概述二、IIO子系統相關數據結構分析三、iio trigger 介紹四、iio event介紹五、iio buffer介紹六、iio device的註冊與註銷介紹七、iio trigger
  • LINUX IIO子系統分析之二 IIO子系統數據結構分析
    基本就是這些內容,iio子系統主要藉助字符設備文件以及sysfs屬性文件實現數據的獲取與參數設定等操作。;available_scan_masks表示當前iio device可使用的channel的掩碼(如當前由8個通道,僅前四個通道可用,則可以設置available_scan_maks值為{0x0F}),而active_scan_mask則表示當前已enable的channelmask,該mask是available_scan_masks的子集scan_bytes
  • LINUX IIO子系統分析之三 IIO trigger分析
    上一章我們分析了IIO子系統的數據結構定義,本章我們主要介紹IIO TRIGGER的設計實現,主要內容如下:一、數據結構簡述 二、設計實現說明 三、提供接口說明一、數據結構簡述irq chip,在trigger內部,當多個trigger consumer註冊時,則trigger內部會為其分配一個虛擬的irq,並根據trigger consumer提供給pollfunc,為該irq註冊中斷處理函數,這樣當該trigger觸發後,則會遍歷所有該trigger上已註冊的虛擬irq,調用其中斷處理函數從而執行trigger consumer提供的處理函數(關於linux中斷子系統的內容可參考我之前寫的中斷子系統專欄
  • LINUX IIO子系統分析之五 iio buffer介紹
    上一章我們介紹了iio子系統中的iio event模塊,本章我們將介紹iio buffer模塊,iio buffer主要用於連續數據採集與緩存功能。而/dev/iio:deviceX主要實現兩個功能:用於讀取iio device緩存的已採集數據,從而讓應用程式對採集的數據進行分析;藉助該字符設備文件的ioctl接口,實現匿名iio event fd的創建,從而讓應用程式藉助select/epoll監控該匿名文件是否有event信息可讀; 如下即是
  • LINUX IIO子系統分析之七 虛擬iio設備驅動實現
    實現說明iio event實現(溫度告警) 基於溫度告警,我們通過在溫度告警中斷處理函數中讀取告警信息,並event信息發送給iio event的kfifo中,接口調度過程如下所示,通過該調度過程,應用程式即可監控到溫度傳感器上報的告警。
  • LINUX IIO子系統分析之六 IIO設備驅動開發流程說明
    前面五章我們基本上把IIO 子系統的內部設計實現均作了說明,本章我們將說明iio device的驅動開發流程,本章的主要內容大致安排如下:一、IIO子系統的關鍵技術點總結 二、IIO DEVICE的註冊與註銷接口說明 三、IIO DEVICE的驅動開發流程
  • Linux regmap子系統分析之三 regmap bus實例分析
    在前面一章我們分析了regmap子系統的數據結構,基本上熟悉了數據結構的關聯,也就大概理解了regmap子系統的實現流程,本章我們簡要介紹下regmap子系統中接口的調用過程,然後介紹下regmap bus的實現及其提供的regmap的創建及註銷接口。
  • Linux input子系統編程、分析與模板
    輸入設備都有共性:中斷驅動+字符IO,基於分層的思想,Linux內核將這些設備的公有的部分提取出來,基於cdev提供接口,設計了輸入子系統,所有使用輸入子系統構建的設備都使用主設備號13,同時輸入子系統也支持自動創建設備文件,這些文件採用阻塞的IO讀寫方式
  • Linux V4l2子系統專欄之一 子系統概述
    本專欄主要分為如下幾章:一、LINUX V4L2子系統概述 二、LINUX V4L2相關數據結構說明 三、LINUX video device分析 四、linux v4l2 device分析 五、linux v4l2 ctrls分析 六、linux
  • Linux regulator子系統分析之一 總體概述
    Linux regulator 子系統主要用於管理電壓、電流電源設備的電壓、電流輸入使能、動態調整電壓、電流等,屬於電源管理的一部分。從本章開始我們分析regulator子系統。主要分為如下幾部分:一、regulator子系統總體概述二、regulator相關數據結構分析三、regulator相關註冊、註銷函數分析四、regulator設備驅動實現本章主要對regulator子系統進行簡要說明。
  • Linux regmap子系統分析之一 系統概述
    本系統專欄主要涉及如下幾個子章節:一、regmap子系統概述二、regmap子系統數據結構分析三、regmap子系統接口說明四、regmap bus實例說明(以i2c為例)本章我們主要對regmap子系統做一個簡單的說明。
  • LINUX CommonClock Framework子系統分析之一 系統概述
    本專欄主要介紹linux的ccf子系統,主要用於系統clock的管理等操作。本專欄我們大概分為如下幾章進行學習:一、CCF子系統概述二、CCF子系統數據結構分析及關聯說明三、CCF子系統的clk註冊與註銷接口實現分析四、虛擬的clk設備驅動實現 本章我們主要進行CCF子系統的概述。
  • Linux regulator子系統分析之三 regulator註冊、註銷接口分析
    在上一章我們介紹了regulator子系統相關的數據結構間的關聯以及每一個數據結構的定義。針對數據結構間的關聯則需要regulator子系統提供的接口實現。而本章我們就說明這些接口。,還涉及如下內容:對regulator dev相關的參數進行合法性檢測,如get_voltage_sel、list_voltage這兩個接口是否只設置一個等;為該regulator_dev創建struct device類型的變量,並註冊到linux設備驅動模型子系統中,並完成與regulator_class的關聯;為該regulator_dev
  • Linux regmap子系統分析之二 從數據結構分析系統實現
    上一章我們簡要分析了regmap子系統,本章我們將從regmap子系統的數據結構介紹regmap子系統的實現。 一、數據結構間的關聯及說明 針對regmap子系統,我們首先要知道regmap子系統要解決的痛點是什麼?
  • Linux regulator子系統分析之四 虛擬regulator device驅動實現
    在前面幾章,我們分析了regulator子系統框架,主要是從數據結構及數據結構間的關聯分析了regulator子系統。為了讓大家對regulator子系統有一個深入的認識,我們本章將實現一個虛擬的regulator device驅動,從而掌握對regulator子系統的開發流程。
  • 「正點原子Linux連載」第五十八章Linux INPUT子系統實驗
    第五十八章Linux INPUT子系統實按鍵、滑鼠、鍵盤、觸控螢幕等都屬於輸入(input)設備,Linux內核為此專門做了一個叫做input子系統的框架來處理輸入事件。輸入設備本質上還是字符設備,只是在此基礎上套上了input框架,用戶只需要負責上報輸入事件,比如按鍵值、坐標等信息,input核心層負責處理這些事件。
  • Linux pinctrl子系統分析之四 pinctrl device的註冊與註銷
    前面我們分析了pinctrl子系統相關的數據結構等內容,本章我們分析pinctrl device的註冊與註銷接口。 針對pinctrl device的註冊與註銷主要涉及pinctrl_register、pinctrl_unregister、devm_pinctrl_register、devm_pinctrl_unregister這幾個接口。
  • 「linux」libevent demo詳細分析(對比epoll)
    有了上面的分析,結合之前做的epoll服務端程序,對於一個伺服器程序,流程基本是這樣的:1. 創建socket,bind,listen,設置為非阻塞模式2.不幸的是,沒有一個有效的接口是一個普遍存在的標準,linux下有epoll,BSDS有kqueue,Solaris 有evport和/dev/poll,等等。沒有任何一個作業系統有它們中所有的,所以如果你想做一個輕便的高性能的異步應用程式,你就需要把這些接口抽象的封裝起來,並且無論哪一個系統使用它都是最高效的。
  • libevent源碼分析之bufferevent使用詳解
    libevent的bufferevent在event的基礎上自己維護了一個buffer,這樣的話,就不需要再自己管理一個buffer了。先看看struct bufferevent這個結構體struct bufferevent {struct event_base *ev_base;const struct bufferevent_ops *be_ops;struct event ev_read;struct event ev_write;
  • 簡單分析「Windows將被微軟放棄淪為Linux子系統」
    昨天看一個消息:有觀點認為Windows將被微軟放棄而淪為Linux子系統 – Windows – cnBeta.COMhttps://www.cnbeta.com/articles/tech/1034593.htmWindows