溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

linux設備節(jié)點的概念是什么

發(fā)布時間:2022-04-19 10:15:07 來源:億速云 閱讀:294 作者:zzz 欄目:建站服務器

這篇文章主要介紹了linux設備節(jié)點的概念是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇linux設備節(jié)點的概念是什么文章都會有所收獲,下面我們一起來看看吧。

linux設備節(jié)點是應用程序和設備驅動程序溝通的一個橋梁;設備節(jié)點被創(chuàng)建在“/dev”,是連接內核與用戶層的樞紐,相當于硬盤的inode一樣的東西,記錄了硬件設備的位置和信息。設備節(jié)點使用戶可以與內核進行硬件的溝通,讀寫設備以及其他的操作。

本教程操作環(huán)境:linux5.9.8系統(tǒng)、Dell G3電腦。

什么是設備節(jié)點

人和人之間溝通橋梁是語言。同樣,應用程序和設備驅動程序溝通也需要一個橋梁。這個橋梁就是設備節(jié)點。

對于Linux系統(tǒng),所有的IO資源都是文件,包括文件、目錄、硬盤、設備等。那么,鍵盤作為計算機系統(tǒng)中的一款輸入設備,操作系統(tǒng)同樣也把它抽象了文件,要想獲取用戶從鍵盤上輸入的數(shù)據(jù)時,只需要讀取鍵盤提供的設備節(jié)點即可。

在Linux系統(tǒng)中,鍵盤作為輸入設備,其對應的設備節(jié)點位于”/dev/input“下。在這個文件夾下有很多以event打頭的文件,這些就是所有input設備的設備節(jié)點。如何確定哪個是鍵盤的設備節(jié)點呢?將鍵盤連接到樹莓派上,打開終端,執(zhí)行“sudo cat /dev/input/event0”,敲擊鍵盤,如果沒有輸出,就換下一個節(jié)點,直到找到有輸出的節(jié)點,那這個節(jié)點就是鍵盤對應的設備節(jié)點。

設備節(jié)點被創(chuàng)建在/dev下,是連接內核與用戶層的樞紐,就是設備是接到對應哪種接口的哪個ID 上。 相當于硬盤的inode一樣的東西,記錄了硬件設備的位置和信息

在Linux中,所有設備都以文件的形式存放在/dev目錄下,都是通過文件的方式進行訪問,設備節(jié)點是Linux內核對設備的抽象,一個設備節(jié)點就是一個文件。應用程序通過一組標準化的調用執(zhí)行訪問設備,這些調用獨立于任何特定的驅動程序。而驅動程序負責將這些標準調用映射到實際硬件的特有操作。

設備節(jié)點的作用

設備節(jié)點使得用戶可以與內核進行硬件的溝通,讀寫設備以及其他的操作

在linux里面設備就像是普通文件一樣的存在,訪問一個設備就好像是訪問一個文件一樣

主設備號代表著一類設備,次設備號代表著同一類設備的不同個體,說到這里也許并不知道設備節(jié)點的存在形式

設備節(jié)點的存在形式

另外在linux里面還有一個概念,就是inode與block,也就是硬盤一面的塊與節(jié)點,硬盤里面的inode就相當于一個文件或者文件夾,它記錄下此文件下面的文件位置所在,文件的位置是以block大小對齊的,例如有些系統(tǒng)就是4K的大小,而inode的大小是有限的,所以就有了單個文件不能超過4G的說法。而在linux的驅動程序里面的節(jié)點在我個人的理解也可以看做是一個類似于硬盤的inode一樣的東西,里面可以記錄硬件設備的位置以及別的一些信息,在用戶需要進行訪問的時候就參照到設備節(jié)點所記錄的信息進行設備的訪問

如何從設備節(jié)點中獲取數(shù)據(jù)

操作系統(tǒng)之所以把IO都抽象成了文件,最大的好處就是可以通過統(tǒng)一的接口來訪問這個文件,從而和不同的設備溝通。這些統(tǒng)一的接口就是操作系統(tǒng)針對文件操作對外提供的一組系統(tǒng)調用:open函數(shù)、read函數(shù)、write函數(shù)等。比如,如果需要從一個設備中獲取數(shù)據(jù),只需要調用read函數(shù)去讀取該設備對應的設備節(jié)點就可以了,當然在read之前,要先調用open函數(shù)打開?,F(xiàn)在以獲取鍵盤輸入為例來介紹。

1、打開設備節(jié)點

在讀取設備節(jié)點的數(shù)據(jù)之前,要先調用open函數(shù)打開設備節(jié)點。open函數(shù)的具體用法可以參考鏈接。簡單描述如下:

函數(shù)聲明:

int open(const char *pathname, int flags);

需要包含的頭文件:

  #include <fcntl.h>

參數(shù):

* 第一個參數(shù)(const char *pathname):表示需要打開的文件路徑

* 第二個參數(shù)(int flags):表示打開文件的方式,比如,”O(jiān)_RDONLY” ——只讀打開;”O(jiān)_WRONLY”——只寫打開;”O(jiān)_RDWR”——讀、寫打開,等。

返回值:

 如果打開成功,則返回該文件的文件描述符,以供read,write等函數(shù)使用。否則,返回-1。

那么,要打開鍵盤的設備文件(假設是”/dev/input/even10“),則需要以下代碼:

  int keys_fd;
    keys_fd = open("/dev/input/even10", O_RDONLY);
    if(keys_fd <= 0)
    {
        printf("open /dev/input/event10 device error!\n");
        return -1;
    }

2 、讀取設備節(jié)點的數(shù)據(jù)

讀取設備節(jié)點需要使用read函數(shù),具體使用方法可以參考鏈接。簡單介紹如下:

函數(shù)聲明:

  ssize_t read(int fd, void *buf, size_t count);

需要包含的頭文件:

  #include <unistd.h>

參數(shù):

* 第一個參數(shù)(int fd):要打開文件的文件描述符,來源一般是上述open函數(shù)的返回值。

* 第二個參數(shù)(void *buf):讀取到的數(shù)據(jù)存放的起始位置指針

* 第三個參數(shù)(size_t count):要讀取的數(shù)據(jù)字節(jié)數(shù)

返回值:

* 如果讀取成功,則返回實際讀取到的字節(jié)數(shù)

* 如果讀取失敗,則返回-1

* 如果返回值小于第三個參數(shù)count,則表示已經讀取到文件結尾,返回值表示實際讀取的字節(jié)數(shù)。

在讀取鍵盤的例子中,我們循環(huán)讀取鍵盤設備的文件節(jié)點,并將設備保存到一個char buf[24]的數(shù)組中去。具體代碼如下:

char buf[24];
while(1)
{
    if(read(keys_fd, buf, 24) == 24)
    {
        // 成功的從設備節(jié)點中獲取到了24個字節(jié)
        ...
    }
}

根據(jù)read函數(shù)用法,當要讀取24個字節(jié),且read函數(shù)的返回值是24時,表示成功的從設備節(jié)點中獲取到了24個字節(jié)。

3、分析從設備節(jié)點獲取的數(shù)據(jù)

為什么這里要從鍵盤的設備驅動獲取24個字節(jié)呢?這是因為正常情況下,從鍵盤設備節(jié)點獲取的數(shù)據(jù)實際上是一個struct input_event結構。其定義為:

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

顯然,上述結構體的大小為24。

  這里需要理解的是:設備節(jié)點是設備驅動程序提供的,且設備節(jié)點的數(shù)據(jù)是設備驅動寫入的,而且寫入時,是以上述結構的規(guī)則寫入的,這是雙方通過<linux/input.h>約定好的,那么應用程序去設備節(jié)點中讀取數(shù)據(jù)之后,也需要按照上述結構去解析數(shù)據(jù)。那這個結構具體是什么意思呢?

* struct timeval time:其大小為16個字節(jié),具體意義暫時不考慮。

* __u16 type:其大小為2個字節(jié),表示input設備的類型,比如:EV_KEY表示上報的是鍵盤類型的數(shù)據(jù),EV_REL表示相對路徑,鼠標就屬于這種類型,還是其他等等。

* __u16 code:其大小為2個字節(jié),表示事件的代碼。比如,如果type為EV_KEY,那么該代碼code為設備鍵盤代碼。code值實際上是應用程序和驅動程序約定好的一些固定的值,它可取的值位于include/uapi/linux/input-event-codes.h中。舉例來講,根據(jù)Linux源碼下的include/uapi/linux/input-event-codes.h文件的第91行#define KEY_Q 16,如果鍵盤上按下或松開了Q鍵,那么鍵盤的驅動程序上報的code值應該是16;反之,如果應用程序獲取到的值是19,那么,表示用戶按下或松開了鍵盤上的Q鍵。

* __s32 value:其大小為4個字節(jié),事件的值。如果事件的類型代碼是EV_KEY,當按鍵按下時值為1,松開時值為0;

根據(jù)上述解釋,我們可以添加以下代碼來解析從設備節(jié)點中獲取的數(shù)據(jù)。

if(t.type == EV_KEY)                // 我們只關心input event類型為EV_KEY(按鍵)的消息
    if(t.value == 0 || t.value == 1)
    {
        printf("key %d %s\n", 
        t.code,                     // t.code表示按下或松開了哪個按鍵
        (t.value) ? "Pressed" : "Released");   // t.value表示按下還是松開了相應的按鍵
    }

4、關閉設備節(jié)點

在從設備節(jié)點獲取數(shù)據(jù)完成后,務必調用close函數(shù),來關閉設備節(jié)點。即

close(keys_fd);

關于“l(fā)inux設備節(jié)點的概念是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“l(fā)inux設備節(jié)點的概念是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI