
在嵌入式Linux系統(tǒng)開發(fā)中,通過編程控制硬件資源是至關(guān)重要的技能之一,今天跟各位小伙伴分享一篇專注于介紹如何使用C庫(kù)函數(shù)控制ELF 1開發(fā)板LED的學(xué)習(xí)筆記。
希望通過這篇學(xué)習(xí)筆記,讓屏幕前的小伙伴能深入理解Linux內(nèi)核對(duì)于底層硬件資源管理的抽象機(jī)制,為進(jìn)行復(fù)雜的嵌入式系統(tǒng)開發(fā)奠定基礎(chǔ)。
一、系統(tǒng)調(diào)用與庫(kù)函數(shù)
(一)系統(tǒng)調(diào)用
系統(tǒng)調(diào)用(System Call)是操作系統(tǒng)內(nèi)核提供的函數(shù),在內(nèi)核態(tài)運(yùn)行(Kernel Mode),是操作系統(tǒng)為用戶提供的一些接口。它通過軟中斷向內(nèi)核態(tài)發(fā)出一個(gè)明確的請(qǐng)求。有一些任務(wù)需要進(jìn)程跑在內(nèi)核態(tài)才能執(zhí)行,比如和硬件打交道。所以進(jìn)程調(diào)用系統(tǒng)調(diào)用就能讓自己運(yùn)行在內(nèi)核態(tài)從而執(zhí)行這些類似的任務(wù)。系統(tǒng)調(diào)用實(shí)現(xiàn)了用戶態(tài)進(jìn)程和硬件設(shè)備之間的大部分接口。
常見系統(tǒng)調(diào)用
Open, Close, Read, Write, Ioctl,F(xiàn)ork,Clone,Exit,Getpid,Access,Chdir,Chmod,Stat,Brk,Mmap等,需要包含Unistd.h等頭文件。
(二)庫(kù)函數(shù)
庫(kù)函數(shù)位于系統(tǒng)調(diào)用的上層,扮演著封裝和抽象的角色,運(yùn)行在用戶態(tài)(User Mode),旨在為程序員提供一種更為便捷的方式來調(diào)用真正實(shí)現(xiàn)底層功能的系統(tǒng)調(diào)用。這些庫(kù)函數(shù)充當(dāng)了用戶態(tài)服務(wù)的供給者,其功能實(shí)現(xiàn)機(jī)制各異:有的庫(kù)函數(shù)可能整合并包裝了一個(gè)或多個(gè)不同的系統(tǒng)調(diào)用,而有的庫(kù)函數(shù)則能夠直接在用戶態(tài)提供所需服務(wù),無需進(jìn)一步調(diào)用任何系統(tǒng)調(diào)用。
(三)區(qū)別
系統(tǒng)調(diào)用通常不可替換,而庫(kù)函數(shù)通常可替換
普通的庫(kù)函數(shù)調(diào)用由函數(shù)庫(kù)或用戶自己提供,因此庫(kù)函數(shù)是可以替換的。例如,對(duì)于存儲(chǔ)空間分配函數(shù)malloc,如果不習(xí)慣它的操作方式,我們完全可以定義自己的malloc函數(shù)。
系統(tǒng)調(diào)用通常提供最小接口,而庫(kù)函數(shù)通常提供較復(fù)雜功能
例如sbrk系統(tǒng)調(diào)用分配一塊空間給進(jìn)程,而malloc則在用戶層次對(duì)這以空間進(jìn)行管理。
系統(tǒng)調(diào)用運(yùn)行在內(nèi)核空間,而庫(kù)函數(shù)運(yùn)行在用戶空間
因?yàn)橄到y(tǒng)調(diào)用屬于內(nèi)核,和庫(kù)函數(shù)不屬于內(nèi)核。因此,如果當(dāng)用戶態(tài)進(jìn)程調(diào)用一個(gè)系統(tǒng)調(diào)用時(shí),CPU需要將其切換到內(nèi)核態(tài),并執(zhí)行一個(gè)內(nèi)核函數(shù)。
內(nèi)核調(diào)用都返回一個(gè)整數(shù)值,而庫(kù)函數(shù)并非一定如此
在內(nèi)核中,整數(shù)或0表示系統(tǒng)調(diào)用成功結(jié)束,而負(fù)數(shù)表示一個(gè)出錯(cuò)條件。而出錯(cuò)時(shí),內(nèi)核不會(huì)將其設(shè)置在errno,而是由庫(kù)函數(shù)從系統(tǒng)調(diào)用返回后對(duì)其進(jìn)行設(shè)置或使用。
POSIX 標(biāo)準(zhǔn)針對(duì)庫(kù)函數(shù)而不是系統(tǒng)調(diào)用
判斷一個(gè)系統(tǒng)是否與POSIX需要看它是否提供一組合適的應(yīng)用程序接口,而不管其對(duì)應(yīng)的函數(shù)是如何實(shí)現(xiàn)的。因此從移值性來講,使用庫(kù)函數(shù)的移植性較系統(tǒng)調(diào)用更好。
系統(tǒng)調(diào)用運(yùn)行時(shí)間屬于系統(tǒng)時(shí)間,庫(kù)函數(shù)運(yùn)行時(shí)間屬于用戶時(shí)間
調(diào)用系統(tǒng)調(diào)用開銷相對(duì)庫(kù)函數(shù)來說更大
很多庫(kù)函數(shù)本身都調(diào)用了系統(tǒng)調(diào)用,這得益于雙緩沖的實(shí)現(xiàn),在用戶態(tài)和內(nèi)核態(tài),都應(yīng)用了緩沖技術(shù),對(duì)于文件讀寫來說,調(diào)用庫(kù)函數(shù),可以大大減少調(diào)用系統(tǒng)調(diào)用的次數(shù)。而用戶進(jìn)程調(diào)用系統(tǒng)調(diào)用需要在用戶空間和內(nèi)核空間進(jìn)行上下文切換,開銷較大。如此以來,庫(kù)函數(shù)的開銷也就會(huì)比直接調(diào)用系統(tǒng)調(diào)用小了。另外一方面,庫(kù)函數(shù)同樣會(huì)對(duì)系統(tǒng)調(diào)用的性能進(jìn)行優(yōu)化。
二、使用C庫(kù)函數(shù)控制LED
(一)實(shí)驗(yàn)代碼
參考3.2.1.2 文件 I/O 的方式控制 LED的例程將使用系統(tǒng)調(diào)用的部分改為使用庫(kù)函數(shù)來實(shí)現(xiàn)。代碼如下:
#include #include #include #define LED1_BRIGHTNESS "/sys/class/leds/led1/brightness" #define LED2_BRIGHTNESS "/sys/class/leds/led2/brightness" #define LED3_BRIGHTNESS "/sys/class/leds/led3/brightness" int main() { FILE *fd1, *fd2, *fd3; fd1 = fopen(LED1_BRIGHTNESS, "w"); if(fd1 < 0) { printf("Fail to Open %s device\n", LED1_BRIGHTNESS); exit(1); } fd2 = fopen(LED2_BRIGHTNESS, "w"); if(fd2 < 0) { printf("Fail to Open %s device\n", LED2_BRIGHTNESS); exit(1); } fd3 = fopen(LED3_BRIGHTNESS, "w"); if(fd3 < 0) { printf("Fail to Open %s device\n", LED3_BRIGHTNESS); exit(1); } while(1) { fwrite("1",3,1,fd1); fflush(fd1); sleep(1); fwrite("0",1,1,fd1); fflush(fd1); fwrite("1",3,1,fd2); fflush(fd2); sleep(1); fwrite("0",1,1,fd2); fflush(fd2); fwrite("1",3,1,fd3); fflush(fd3); sleep(1); fwrite("0",1,1,fd3); fflush(fd3); } fclose(fd1); fclose(fd2); fclose(fd3); return 0; }
(二)編譯、測(cè)試將代碼編譯后拷貝到ELF 1開發(fā)板進(jìn)行測(cè)試。

執(zhí)行LED2,查看結(jié)果

可以看到LED按照預(yù)期循環(huán)點(diǎn)亮

三、總結(jié)
本次實(shí)驗(yàn)使用C庫(kù)函數(shù)實(shí)現(xiàn)了對(duì)LED的控制,通過一個(gè)簡(jiǎn)單的示例來感受系統(tǒng)調(diào)用與庫(kù)函數(shù)的區(qū)別。但是代碼中還有需要注意的地方。
代碼中調(diào)用fwrite函數(shù)寫入內(nèi)容時(shí),它可能只是把內(nèi)容保存到了C庫(kù)的緩沖區(qū),并沒有執(zhí)行真正的系統(tǒng)調(diào)用write函數(shù)把內(nèi)容寫入到設(shè)備文件,這種情況下LED燈的狀態(tài)是不會(huì)被改變的,代碼中在fwrite函數(shù)后調(diào)用了fflush要求立刻把緩沖區(qū)的內(nèi)容寫入到文件,確保 執(zhí)行了相應(yīng)的操作。在實(shí)驗(yàn)時(shí)可以嘗試把代碼中的fflush都注釋掉,這種情況下有極大的幾率是無法正常改變LED燈狀態(tài)的。
如果不考慮操作的時(shí)間開銷,其實(shí)控制硬件更推薦的做法是,每次控制LED燈都使用fopen—fwrite—fclose的流程,這樣就不需要考慮flseek、fflush的問題了,但最推薦的還是直接通過系統(tǒng)調(diào)用來控制硬件的方式。
-
嵌入式
+關(guān)注
關(guān)注
5141文章
19537瀏覽量
315140 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7630瀏覽量
140453 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5532瀏覽量
102429
發(fā)布評(píng)論請(qǐng)先 登錄
學(xué)習(xí)筆記分享|ElfBoard開發(fā)板初識(shí)
嵌入式學(xué)習(xí)-ElfBoard ELF 1板卡-使用C庫(kù)函數(shù)控制ELF1開發(fā)板的LED
I.MX6ULL-ElfBoard ELF1板卡- 使用C庫(kù)函數(shù)控制開發(fā)板的LED
嵌入式學(xué)習(xí)-ElfBoard ELF 1開發(fā)板-共創(chuàng)官學(xué)習(xí)筆記分享|將Go程序編譯到ELF 1開發(fā)板
STM32F103學(xué)習(xí)筆記分享
【ELF 1開發(fā)板試用】+ RGB LED及按鍵的控制
【ELF 1開發(fā)板試用】板載資源測(cè)試1:點(diǎn)亮LED燈
ALIENTEK MiniSTM32開發(fā)板例程-庫(kù)函數(shù)版本
ALIENTEK MiniSTM32開發(fā)板例程(庫(kù)函數(shù)版本)
Alientek MiniSTM32開發(fā)板例程庫(kù)函數(shù)版本資料合集免費(fèi)下載

STM32庫(kù)函數(shù)開發(fā)-GPIO

關(guān)于ELF1/ELF1S開發(fā)板的音頻接口,你需要知道的都在這!

ELF 1技術(shù)貼|在NXP源碼基礎(chǔ)上適配ELF 1開發(fā)板的LED功能

評(píng)論