嵌入式Linux驅動程序和QT.ppt
《嵌入式Linux驅動程序和QT.ppt》由會員分享,可在線閱讀,更多相關《嵌入式Linux驅動程序和QT.ppt(47頁珍藏版)》請在裝配圖網上搜索。
嵌入式Linux驅動程序開發(fā),遼寧工程技術大學電信學院,1嵌入式Linux的設備管理,,Linux將設備分成兩大類:一類是塊設備,類似磁盤以記錄塊或扇區(qū)為單位,成塊進行輸入/輸出的設備;另一類是字符設備,類似鍵盤以字符為單位,逐個進行輸入/輸出的設備。網路設備是介于塊設備和字符設備之間的一種特殊設備。塊設備接口僅支持面向塊的I/O操作,所有I/O操作都通過在內核地址空間中的I/O緩沖區(qū)進行,它可以支持隨機存取的功能。文件系統(tǒng)通常都建立在塊設備上。字符設備接口支持面向字符的I/O操作,由于它們不經過系統(tǒng)的快速緩存,所以它們負責管理自己的緩沖區(qū)結構。字符設備接口只支持順序存取的功能,一般不能進行任意長度的I/O請求,而是限制I/O請求的長度必須是設備要求的基本塊長的倍數。處理器與設備間數據交換方式處理器與外設之間傳輸數據的控制方式通常有3種:查詢方式、中斷方式和直接內存存?。―MA)方式。1.查詢方式設備驅動程序通過設備的I/O端口空間,以及存儲器空間完成數據的交換。例如,網卡一般將自己的內部寄存器映射為設備的I/O端口,而顯示卡則利用大量的存儲器空間作為視頻信息的存儲空間。利用這些地址空間,驅動程序可以向外設發(fā)送指定的操作指令。通常來講,由于外設的操作耗時較長,因此,當處理器實際執(zhí)行了操作指令之后,驅動程序可采用查詢方式等待外設完成操作。驅動程序在提交命令之后,開始查詢設備的狀態(tài)寄存器,當狀態(tài)寄存器表明操作完成時,驅動程序可繼續(xù)后續(xù)處理。查詢方式的優(yōu)點是硬件開銷小,使用起來比較簡單。但在此方式下,CPU要不斷地查詢外設的狀態(tài),當外設未準備好時,就只能循環(huán)等待,不能執(zhí)行其他程序,這樣就浪費了CPU的大量時間,降低了處理器的利用率。,2.中斷方式查詢方式白白浪費了大量的處理器時間,而中斷方式才是多任務操作系統(tǒng)中最有效利用處理器的方式。當CPU進行主程序操作時,外設的數據已存入端口的數據輸入寄存器,或端口的數據輸出寄存器已空,此時由外設通過接口電路向CPU發(fā)出中斷請求信號。CPU在滿足一定條件下,暫停執(zhí)行當前正在執(zhí)行的主程序,轉入執(zhí)行相應能夠進行輸入/輸出操作的子程序,待輸入/輸出操作執(zhí)行完畢之后,CPU再返回并繼續(xù)執(zhí)行原來被中斷的主程序。這樣,CPU就避免了把大量時間耗費在等待、查詢外設狀態(tài)的操作上,使其工作效率得以大大提高。中斷方式的原理示意圖如下圖所示。能夠向CPU發(fā)出中斷請求的設備或事件稱為中斷源。中斷源向CPU發(fā)出中斷請求,若優(yōu)先級別最高,則CPU在滿足一定的條件時,可中斷當前程序的運行,保護好被中斷的主程序的斷點及現(xiàn)場信息,然后根據中斷源提供的信息,找到中斷服務子程序的入口地址,轉去執(zhí)行新的程序段,這就是中斷響應。CPU響應中斷是有條件的,如內部允許中斷、中斷未被屏蔽、當前指令執(zhí)行完等。CPU響應中斷以后,就會中止當前的程序,轉去執(zhí)行一個中斷服務子程序,以完成為相應設備的服務。系統(tǒng)引入中斷機制后,CPU與外設處于“并行”工作狀態(tài),便于實現(xiàn)信息的實時處理和系統(tǒng)的故障處理。,3.直接訪問內存(DMA)方式利用中斷,系統(tǒng)和設備之間可以通過設備驅動程序傳送數據,但是,當傳送的數據量很大時,因為中斷處理上的延遲,利用中斷方式的效率會大大降低。而直接內存訪問(DMA)可以解決這一問題。DMA可允許設備和系統(tǒng)內存間在沒有處理器參與的情況下傳輸大量數據。設備驅動程序在利用DMA之前,需要選擇DMA通道并定義相關寄存器,以及數據的傳輸方向,即讀取或寫入,然后將設備設定為利用該DMA通道傳輸數據。設備完成設置之后,可以立即利用該DMA通道在設備和系統(tǒng)的內存之間傳輸數據,傳輸完畢后產生中斷以便通知驅動程序進行后續(xù)處理。在利用DMA進行數據傳輸的同時,處理器仍然可以繼續(xù)執(zhí)行指令。,設備驅動程序的概念,設備驅動程序實際是處理和操作硬件控制器的軟件,從本質上講,是內核中具有最高特權級的、駐留內存的、可共享的底層硬件處理例程。驅動程序是內核的一部分,是操作系統(tǒng)內核與硬件設備的直接接口,驅動程序屏蔽了硬件的細節(jié),完成以下功能:?對設備初始化和釋放;?對設備進行管理,包括實時參數設置,以及提供對設備的操作接口;?讀取應用程序傳送給設備文件的數據或者回送應用程序請求的數據;?檢測和處理設備出現(xiàn)的錯誤。Linux操作系統(tǒng)將所有的設備全部看成文件,并通過文件的操作界面進行操作。對用戶程序而言,設備驅動程序隱藏了設備的具體細節(jié),對各種不同設備提供了一致的接口,一般來說,是把設備映射為一個特殊的設備文件,用戶程序可以像對其他文件一樣對此設備文件進行操作。這意味著:?由于每一個設備至少由文件系統(tǒng)的一個文件代表,因而都有一個“文件名”。?應用程序通??梢酝ㄟ^系統(tǒng)調用open()打開設備文件,建立起與目標設備的連接。?打開了代表著目標設備的文件,即建立起與設備的連接后,可以通過read()、write()、ioctl()等常規(guī)的文件操作對目標設備進行操作。設備文件的屬性由三部分信息組成:第一部分是文件的類型,第二部分是一個主設備號,第三部分是一個次設備號。其中類型和主設備號結合在一起惟一地確定了設備文件驅動程序及其界面,而次設備號則說明目標設備是同類設備中的第幾個。由于Linux中將設備當做文件處理,所以對設備進行操作的調用格式與對文件的操作類似,主要包括open()、read()、write()、ioctl()、close()等。應用程序發(fā)出系統(tǒng)調用命令后,會從用戶態(tài)轉到核心態(tài),通過內核將open()這樣的系統(tǒng)調用轉換成對物理設備的操作。,驅動程序結構,1.自動配置和初始化子程序,用來檢測所需驅動的硬件設備是否工作正常、對正常工作的設備及其相關驅動程序所需要的軟件狀態(tài)進行初始化。2.服務于I/O請求的子程序,該子程序稱為驅動程序的上半部。這部分程序在執(zhí)行時,系統(tǒng)仍認為與進行調用的進程屬于同一個進程,只是由用戶態(tài)變成了核心態(tài),可以在其中調用sleep()等與進程運行環(huán)境有關的函數。3.中斷服務程序,又稱為驅動程序的下半部,由Linux系統(tǒng)來接收硬件中斷,再由系統(tǒng)調用中斷服務子程序。在系統(tǒng)內部,I/O設備的存取通過一組固定的入口點來進行,入口點也可以理解為設備的句柄,就是對設備進行操作的基本函數。字符型設備驅動程序提供如下幾個入口點:?open入口點。打開設備準備I/O操作。對字符設備文件進行打開操作,都會調用設備的open入口點。open子程序必須對將要進行的I/O操作做好必要的準備工作,如清除緩沖區(qū)等。如果設備是獨占的,即同一時刻只能有一個程序訪問此設備,則open子程序必須設置一些標志以表示設備處于忙狀態(tài)。?close入口點。關閉一個設備。當最后一次使用設備完成后,調用close子程序。獨占設備必須標記設備方可再次使用。?read入口點。從設備上讀數據。對于有緩沖區(qū)的I/O操作,一般是從緩沖區(qū)里讀數據。對字符設備文件進行讀操作將調用read子程序。?write入口點。往設備上寫數據。對于有緩沖區(qū)的I/O操作,一般是把數據寫入緩沖區(qū)里。對字符設備文件進行寫操作將調用write子程序。?ioctl入口點。執(zhí)行讀、寫之外的操作。?select入口點。檢查設備,看數據是否可讀或設備是否可用于寫數據。select系統(tǒng)調用在檢查與設備文件相關的文件描述符時使用select入口點。,structfile_operations{structmodule*owner;loff_t(*llseek)(structfile*,loff_t,int);ssize_t(*read)(structfile*,char*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);int(*readdir)(structfile*,void*,filldir_t);unsignedint(*poll)(structfile*,structpoll_table_struct*);int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);int(*mmap)(structfile*,structvm_area_struct*);int(*open)(structinode*,structfile*);int(*flush)(structfile*);int(*release)(structinode*,structfile*);int(*fsync)(structfile*,structdentry*,intdatasync);int(*fasync)(int,structfile*,int);int(*lock)(structfile*,int,structfile_lock*);ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);};?lseek,移動文件指針的位置,只能用于可以隨機存取的設備。?read,進行讀操作,buf為存放讀取結果的緩沖區(qū),count為所要讀取的數據長度。?write,進行寫操作,與read類似。?select,進行選擇操作。?ioctl,進行讀、寫以外的其他操作。?mmap,用于把設備的內容映射到地址空間,一般只有塊設備驅動程序使用。?open,打開設備進行I/O操作。返回0表示成功,返回負數表示失敗。?release,即close操作。,structfile主要用于與文件系統(tǒng)相關的設備驅動程序,可提供關于被打開的文件的信息,定義如下:structfile{structlist_headf_list;structdentry*f_dentry;structvfsmount*f_vfsmnt;structfile_operations*f_op;atomic_tf_count;unsignedintf_flags;mode_tf_mode;loff_tf_pos;unsignedlongf_reada,f_ramax,f_raend,f_ralen,f_rawin;structfown_structf_owner;unsignedintf_uid,f_gid;intf_error;unsignedlongf_version;/*neededforttydriver,andmaybeothers*/void*private_data;/*preallocatedhelperkiobuftospeedupO_DIRECT*/structkiobuf*f_iobuf;longf_iobuf_lock;};在用戶自己的驅動程序中,首先要根據驅動程序的功能,完成file_operations結構中函數的實現(xiàn)。不需要的函數接口可以直接在file_operations結構中初始化為NULL。file_operations中的變量會在驅動程序初始化時,注冊到系統(tǒng)內部。每個進程對設備的操作,都會根據主次設備號,轉換成對file_operations結構的訪問。,2設備驅動程序的開發(fā)過程,由于嵌入式設備由于硬件種類非常豐富,在默認的內核發(fā)布版中不一定包括所有驅動程序。所以進行嵌入式Linux系統(tǒng)的開發(fā),很大的工作量是為各種設備編寫驅動程序。除非系統(tǒng)不使用操作系統(tǒng),程序直接操縱硬件。嵌入式Linux系統(tǒng)驅動程序開發(fā)與普通Linux開發(fā)沒有區(qū)別??梢栽谟布a廠家或者Internet上尋找驅動程序,也可以根據相近的硬件驅動程序來改寫,這樣可以加快開發(fā)速度。實現(xiàn)一個嵌入式Linux設備驅動的大致流程如下。(1)查看原理圖,理解設備的工作原理。一般嵌入式處理器的生產商提供參考電路,也可以根據需要自行設計。(2)定義設備號。設備由一個主設備號和一個次設備號來標識。主設備號惟一標識了設備類型,即設備驅動程序類型,它是塊設備表或字符設備表中設備表項的索引。次設備號僅由設備驅動程序解釋,區(qū)分被一個設備驅動控制下的某個獨立的設備。(3)實現(xiàn)初始化函數。在驅動程序中實現(xiàn)驅動的注冊和卸載。(4)設計所要實現(xiàn)的文件操作,定義file_operations結構。(5)實現(xiàn)所需的文件操作調用,如read、write等。(6)實現(xiàn)中斷服務,并用request_irq向內核注冊,中斷并不是每個設備驅動所必需的。(7)編譯該驅動程序到內核中,或者用insmod命令加載模塊。(8)測試該設備,編寫應用程序,對驅動程序進行測試。,模塊化驅動程序設計,在探討模塊之前,有必要先看一看內核模塊與應用程序之間的區(qū)別。一個應用從頭到尾完成一個任務,而模塊則是為以后處理某些請求而注冊自己,完成這個任務后,它的“主”函數就立即中止了。然而,內核源碼僅能連接編譯到內核模塊中,不像應用那樣有眾多的支持庫,內核能調用的僅是由內核開放出來的那些函數。由于沒有庫連接到模塊中,所以源碼文件不應該模塊化任何常規(guī)頭文件。與內核有關的所有內容都定義在目錄/usr/include/linux和/usr/include/asm下的頭文件中。1.內核空間和用戶空間當談到軟件時,我們通常稱執(zhí)行態(tài)為“內核空間”和“用戶空間”,在Linux系統(tǒng)中,內核在最高級執(zhí)行,也稱為“管理員態(tài)”,在這一級任何操作都可以執(zhí)行。而應用程序則執(zhí)行在最低級,所謂的“用戶態(tài)”,在這一級處理器禁止對硬件的直接訪問和對內存的未授權訪問。模塊是在所謂的“內核空間”中運行的,而應用程序則是在“用戶空間”中運行的。它們分別引用不同的內存映射,也就是程序代碼使用不同的“地址空間”。Linux通過系統(tǒng)調用和硬件中斷完成從用戶空間到內核空間的控制轉移。執(zhí)行系統(tǒng)調用的內核代碼在進程的上下文中執(zhí)行,它執(zhí)行調用進程的操作而且可以訪問進程地址空間的數據。但處理中斷與此不同,處理中斷的代碼相對進程而言是異步的,而且與任何一個進程都無關。模塊的作用就是擴展內核的功能,是運行在內核空間的模塊化的代碼。模塊的某些函數作為系統(tǒng)調用執(zhí)行,而某些函數則負責處理中斷。,各個模塊被分別編譯并鏈接成一組目標文件,這些文件能被載入正在運行的內核,或從正在運行的內核中卸載。必要時內核能請求內核守護進程Kerneld對模塊進行加載或卸載。根據需要動態(tài)載入模塊可以保證內核達到最小,并且具有很大的靈活性。內核模塊一部分保存在Kernel中,另一部分在Modules包中。在項目一開始,很多地方對設備安裝、使用和改動都是通過編譯進內核來實現(xiàn)的,對驅動程序稍微做點改動,就要重新燒寫一遍內核,而且燒寫內核經常容易出錯,還占用資源。模塊采用的則是另一種途徑,內核提供一個插槽,它就像一個插件,在需要時,插入內核中使用,不需要時從內核中拔出。這一切都由一個稱為Kerneld的守護進程自動處理。2.模塊化的優(yōu)缺點內核模塊的動態(tài)加載具有以下優(yōu)點:將內核映像的尺寸保持在最小,并具有最大的靈活性。這便于檢驗新的內核代碼,而不需要重新編譯內核并重新引導。但是,內核模塊的引入也對系統(tǒng)性能和內存的利用有負面影響。裝入的內核模塊與其他內核部分一樣,具有相同的訪問權限,由此可見,差的內核模塊會導致系統(tǒng)崩潰。為了使內核模塊能訪問所有內核資源,內核必須維護符號表,并在加載和卸載模塊時修改這些符號表。由于有些模塊要求利用其他模塊的功能,故內核要維護模塊之間的依賴性。內核必須能夠在卸載模塊時通知模塊,并且要釋放分配給模塊的內存和中斷等資源。內核版本和模塊版本的不兼容也可能導致系統(tǒng)崩潰,因此,嚴格的版本檢查是必需的。盡管內核模塊的引入同時帶來不少問題,但是模塊機制確實是擴充內核功能的一種行之有效的方法,也是在內核級進行編程的有效途徑。,設備注冊和初始化,設備的驅動程序在加載的時候首先需要調用入口函數init_module(),該函數最重要的一個工作就是向內核注冊該設備,對于字符設備調用register_chrdev()完成注冊。register_chrdev的定義為:intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);其中,major是為設備驅動程序向系統(tǒng)申請的主設備號,如果為0,則系統(tǒng)為此驅動程序動態(tài)分配一個主設備號。name是設備名,fops是對各個調用的入口點說明。此函數返回0時表示成功;返回-EINVAL,表示申請的主設備號非法,主要原因是主設備號大于系統(tǒng)所允許的最大設備號;返回-EBUSY,表示所申請的主設備號正在被其他設備程序使用。如果動態(tài)分配主設備號成功,此函數將返回所分配的主設備號。如果register_chrdev()操作成功,設備名就會出現(xiàn)在/proc/dvices文件中。Linux在/dev目錄中為每個設備建立一個文件,用ls–l命令列出函數返回值,若小于0,則表示注冊失?。环祷?或者大于0的值表示注冊成功。注冊以后,Linux將設備名與主、次設備號聯(lián)系起來。當有對此設備名的訪問時,Linux通過請求訪問的設備名得到主、次設備號,然后把此訪問分發(fā)到對應的設備驅動,設備驅動再根據次設備號調用不同的函數。當設備驅動模塊從Linux內核中卸載,對應的主設備號必須被釋放。字符設備在cleanup_module()函數中調用unregister_chrdev()來完成設備的注銷。unregister_chrdev()的定義為:intunregister_chrdev(unsignedintmajor,constchar*name);此函數的參數為主設備號major和設備名name。Linux內核把name和major在內核注冊的名稱對比,如果不相等,卸載失敗,并返回?EINVAL;如果major大于最大的設備號,也返回?EINVAL。,包括設備注冊在內,設備驅動的初始化函數主要完成的功能是有以下5項。(1)對驅動程序管理的硬件進行必要的初始化。對硬件寄存器進行設置。比如,設置中斷掩碼,設置串口的工作方式、并口的數據方向等。(2)初始化設備驅動相關的參數。一般說來,每個設備都要定義一個設備變量,用以保存設備相關的參數。在這一步驟里對設備變量中的項進行初始化。(3)在內核注冊設備。調用register_chrdev()函數來注冊設備。(4)注冊中斷。如果設備需要IRQ支持,則要使用request_irq()函數注冊中斷。(5)其他初始化工作。初始化部分一般還負責給設備驅動程序申請包括內存、時鐘、I/O端口等在內的系統(tǒng)資源,這些資源也可以在open子程序或者其他地方申請。這些資源不用時,應該釋放,以利于資源的共享。若驅動程序是內核的一部分,初始化函數則要按如下方式聲明:int__initchr_driver_init(void);其中__init是必不可少的,在系統(tǒng)啟動時會由內核調用chr_driver_init,完成驅動程序的初始化。當驅動程序是以模塊的形式編寫時,則要按照如下方式聲明:intinit_module(void)當運行后面介紹的insmod命令插入模塊時,會調用init_module函數完成初始化工作。,中斷管理,設備驅動程序通過調用request_irq函數來申請中斷,通過free_irq來釋放中斷。它們在linux/sched.h中的定義如下:intrequest_irq(unsignedintirq,void(*handler)(intirq,voiddev_id,structpt_regs*regs),unsignedlongflags,constchar*device,void*dev_id);voidfree_irq(unsignedintirq,void*dev_id);通常從request_irq函數返回的值為0時,表示申請成功;負值表示出現(xiàn)錯誤。?irq表示所要申請的硬件中斷號。?handler為向系統(tǒng)登記的中斷處理子程序,中斷產生時由系統(tǒng)來調用,調用時所帶參數irq為中斷號,dev_id為申請時告訴系統(tǒng)的設備標識,regs為中斷發(fā)生時寄存器內容。?device為設備名,將會出現(xiàn)在/proc/interrupts文件里。?flag是申請時的選項,它決定中斷處理程序的一些特性,其中最重要的是決定中斷處理程序是快速處理程序(flag里設置了SA_INTERRUPT)還是慢速處理程序(不設置SA_INTERRUPT)。下面的代碼將在SBC-2410X的Linux中注冊外部中斷2。eint_irq=IRQ_EINT2;set_external_irq(eint_irq,EXT_FALLING_EDGE,GPIO_PULLUP_DIS);ret_val=request_irq(eint_irq,eint2_handler,“S3C2410Xeint2”,0);if(ret_valGPIO_MODE_SHIFT)#defineGRAB_PULLUP(x)(((x)2.入口函數模塊的入口函數leds_init(),所做的工作是點亮I/O端口對應的LED,這些二極管可以作為狀態(tài)指示之用。register_chrdev()完成字符設備在系統(tǒng)中的注冊,并建立與文件系統(tǒng)的并聯(lián)。staticint__initleds_init(void){intret;inti;/*在內核中注冊設備*/ret=register_chrdev(LED_MAJOR,DEVICE_NAME,},3.字符設備定義staticdevfs_handle_tdevfs_handle;4.ioctlioctl入口,執(zhí)行讀、寫之外的操作,通過參數cmd設定命令參數。staticintleds_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg){switch(cmd){case0:case1:if(arg>4){return-EINVAL;}write_gpio_bit(led_table[arg],!cmd);default:return-EINVAL;}}5.文件系統(tǒng)接口定義staticstructfile_operationsleds_fops={owner:THIS_MODULE,ioctl:leds_ioctl,};6.模塊化module_init(leds_init);module_exit(leds_exit);用insmod命令加載模塊時,調用module_init();用rmmod命令來卸載模塊時,調用module_exit()函數。,加載運行LED驅動程序,1.應用程序設計#include#include#include#includeintmain(intargc,char**argv){inton;intled_no;intfd;if(argc!=3||sscanf(argv[1],"%d",}該程序首先讀取命令行的參數輸入,其中參數argv[1]賦值給led_no,表示發(fā)光二極管的序號;argv[2]賦值給on。led_no的取值范圍是1~3,on取值為0或1,0表示熄滅LED,1表示點亮LED。參數輸入后通過fd=open("/dev/leds",0)打開設備文件,在保證參數輸入正確和設備文件正確打開后,通過語句ioctl(fd,on,led_no)實現(xiàn)系統(tǒng)調用ioctl,并通過輸入的參數控制LED。在程序的最后關閉設備句柄。,嵌入式圖形用戶界面開發(fā)——Qt/Embedded,,GUI概述,目前的桌面機操作系統(tǒng)大多有著美觀、操作方便、功能齊全的GUI(圖形用戶界面),例如KDE或者GNOME。GUI(圖形用戶界面)是指計算機與其使用者之間的對話接口,可以說,GUI是當今計算機技術的重大成就。它的存在為使用者提供了友好便利的界面,并大大地方便了非專業(yè)用戶的使用,使得人們從繁瑣的命令中解脫出來,可以通過窗口、菜單方便地進行操作。UNIX環(huán)境下的圖形視窗標準為XWindowSystem,Linux是類UNIX系統(tǒng),所以頂層運行的GUI系統(tǒng)是兼容X標準的XFree86系統(tǒng)。X標準大致可以劃分XServer、GraphicLibrary(底層繪圖函數庫)、Toolkits、WindowManager等幾大部分。其好處是具有可擴展性、可移植性等優(yōu)點,但對于嵌入式系統(tǒng)而言無疑太過龐大、累贅、低效。目前流行的嵌入式GUI與X思路不同,這些GUI一般不局限于X標準,更強調系統(tǒng)的空間和效率。,嵌入式GUI的特點,在嵌入式系統(tǒng)中,GUI的地位也越來越重要,但是不同于桌面機系統(tǒng),嵌入式GUI要求簡單、直觀、可靠、占用資源小且反應快速,以適應系統(tǒng)硬件資源有限的條件。另外,由于嵌入式系統(tǒng)硬件本身的特殊性,嵌入式GUI應具備高度可移植性與可裁減性,以適應不同的硬件條件和使用需求。?體積小;?運行時耗用系統(tǒng)資源小;?上層接口與硬件無關,高度可移植;?高可靠性;?在某些應用場合應具備實時性。,Qt/Embedded的特點,MiniGUI(1),提起國內的開源軟件,就肯定會提到MiniGUI,它由魏永明先生和眾多志愿者開發(fā),是一個基于Linux的實時嵌入式系統(tǒng)的輕量級圖形用戶界面支持系統(tǒng)。MiniGUI分為最底層的GAL層和IAL層,向上為基于標準POSIX接口中pthread庫的Mini-thread架構和基于Server/Client的Mini-Lite架構。其中前者受限于thread模式對于整個系統(tǒng)的可靠性——進程中某個thread的意外錯誤可能導致整個進程的崩潰,該架構應用于系統(tǒng)功能較為單一的場合。Mini-Lite應用于多進程的應用場合,采用多進程運行方式設計的Server/Client架構能夠較好地解決各個進程之間的窗口管理、Z序剪切等問題。MiniGUI還有一種從Mini-Lite衍生出的standalone運行模式。與Lite架構不同的是,standalone模式一次只能以窗口最大化的方式顯示一個窗口。這在顯示屏尺寸較小的應用場合具有一定的應用意義。,MiniGUI(2),MiniGUI的IAL層技術SVGAlib、LibGGI、基于framebuffer的native圖形引擎以及啞圖形引擎等,對于Trolltech公司的QVFB在XWindow下也有較好的支持。IAL層則支持Linux標準控制臺下的GPM鼠標服務、觸摸屏、標準鍵盤等。MiniGUI下豐富的控件資源也是MiniGUI的特點之一。MiniGUI免費版本是1.3.3。在該版本的控件中已經添加了窗口皮膚、工具條等桌面GUI中的高級控件支持。對比其他系統(tǒng),“Mini”是MiniGUI的特色,輕量、高性能和高效率的MiniGUI已經應用在電視機頂盒、實時控制系統(tǒng)、掌上電腦等諸多場合。,Microwindows,MicrowindowsOpenSourceProject成立的宗旨在于針對體積小的裝置,建立一套先進的視窗環(huán)境,在Linux桌面上通過交叉編譯可以很容易地制作出Microwindows的程序。Microwindows能夠在沒有任何操作系統(tǒng)或其他圖形系統(tǒng)的支持下運行,它能對裸顯示設備進行直接操作。這樣,Microwindows就顯得十分小巧,便于移植到各種硬件和軟件系統(tǒng)上。然而Microwindows的免費版本進展一直很慢,幾乎處于停頓狀態(tài),而且至今為止,國內沒有任何一家對Microwindows提供全面技術支持、服務和擔保的專業(yè)公司。,常用GUI比較,Qt/Embedded架構,Qt/Embedded以原始Qt為基礎,并做了許多出色的調整以適用于嵌入式環(huán)境。Qt/Embedded通過QtAPI與LinuxI/O設施直接交互,成為嵌入式Linux端口。同Qt/X11相比,Qt/Embedded很省內存,因為它不需要一個X服務器或是Xlib庫,它在底層拋棄了Xlib,采用framebuffer作為底層圖形接口。同時,將外部輸入設備抽象為keyboard和mouse輸入事件。,,Qt/Embedded窗口系統(tǒng),一個Qt/Embedded窗口系統(tǒng)包含了一個或多個進程,其中的一個進程可作為服務器。該服務進程會分配客戶顯示區(qū)域,以及產生鼠標和鍵盤事件。該服務進程還能夠提供輸入方法和一個用戶接口給運行起來的客戶應用程序。該服務進程其實就是一個有某些額外權限的客戶進程??蛻襞c服務器之間的通信使用共享內存的方法實現(xiàn),通信量應該保持最小。這就是Qt/Embedded庫內部層次分明的處理過程。QProcess類提供了另外一種異步的進程間通信機制。它用于啟動一個外部的程序并且通過寫一個標準的輸入和讀取外部程序的標準輸出和錯誤碼來和它們通信。,Qt/Embedded字體(1),Qt/Embedded支持四種不同的字體格式:TrueType字體(TTF),PostscriptType1字體,位圖發(fā)布字體(BDF)和Qt的預呈現(xiàn)(Pre-rendered)字體(QPF)。Qt還可以通過增加QFontFactory的子類來支持其他字體,也可以支持以插件方式出現(xiàn)的反別名字體。每個TTF或者TYPE1類型的字體首次在圖形或者文本方式的環(huán)境下被使用時,這些字體的字形都會以指定的大小被預先呈現(xiàn)出來,呈現(xiàn)的結果會被緩沖。根據給定的字體尺寸(例如10或12點陣)預先呈現(xiàn)TTF或者TYPE1類型的字體文件并把結果以QPF的格式保存起來,這樣可以節(jié)省內存和CPU的處理時間。,Qt/Embedded字體(2),QPF文件包含了一些必要的字體,這些字體可以通過makeqpf工具取得,或者通過運行程序時加上“-savefonts”選項獲取。如果應用程序中使用到的字體都是QPF格式,那么Qt/Embedded將被重新配置,并排除對TTF和TYPE1類型的字體的編譯,這樣就可以減少Qt/Embedded的庫的大小和存儲字體的空間。例如一個10點陣大小的包含所有ASCII字符的QPF字體文件的大小為1300Byte,這個文件可以直接從物理存儲格式映射成為內存存儲格式。Qt/Embedded的字體通常包括Unicode字體的一部分子集,ASCII和Latin-1。,Qt/Embedded輸入設備及輸入法,Qt/Embedded3.0支持幾種鼠標協(xié)議:BusMouse、IntelliMouse,Microsoft和MouseMan.Qt/Embedded還支持NECVr41XX和iPAQ的觸摸屏。通過從QWSMouseHandler或者Qcalibra-tedMouseHandler派生子類,開發(fā)人員可以讓Qt/Embedded支持更多的客戶指示設備。對于非拉丁語系字符(例如阿拉伯,中文,希伯來和日語)的輸入法,需要把它寫成過濾器的方式,并改變鍵盤的輸入。輸入法的作者應該對全部的QtAPI的使用有完整的認識。在一個無鍵盤的設備上,輸入法成了惟一的輸入字符的手段。Qtopia提供了4種輸入方法:筆跡識別器、圖形化的標準鍵盤、Unicode鍵盤和基于字典方式提取的鍵盤。,Qt/Embedded屏幕加速,通過子類化QScreen和QgfxRaster可以實現(xiàn)硬件加速,從而為屏幕操作帶來好處。Troll-tech提供了Mach64和Voodoo3視頻卡的硬件加速的驅動例子,同時可以按照協(xié)議編寫其他的驅動程序。,Qt的支撐工具,Qt包含了許多支持嵌入式系統(tǒng)開發(fā)的工具,有兩個最實用的工具是qmake和Qtdesigner(圖形設計器)。?qmake是一個為編譯Qt/Embedded庫和應用而提供的Makefile生成器。它能夠根據一個工程文件(.pro)產生不同平臺下的Makefile文件。qmake支持跨平臺開發(fā)和影子生成(影子生成是指當工程的源代碼共享給網絡上的多臺機器時,每臺機器編譯鏈接這個工程的代碼將在不同的子路徑下完成,這樣就不會覆蓋別人的編譯鏈接生成的文件。qmake還易于在不同的配置之間切換。)?Qt圖形設計器可以使開發(fā)者可視化地設計對話框而不需編寫代碼。使用Qt圖形設計器的布局管理可以生成能平滑改變尺寸的對話框。qmake和Qt圖形設計器是完全集成在一起的。,Qt/Embedded信號和插槽機制(1),信號和插槽機制是Qt的核心機制,要精通Qt編程就必須對信號和插槽有所了解。信號和插槽是一種高級接口,應用于對象之間的通信,它是Qt的核心特性,也是Qt區(qū)別于其他工具包的重要地方。信號和插槽是Qt自行定義的一種通信機制,它獨立于標準的C/C++語言,必須借助一個稱為moc(MetaObjectCompiler)的Qt工具,該工具是一個C++預處理程序,它為高層次的事件處理自動生成所需要的附加代碼。信號與插槽機制是一種強有力的對象間通信機制,完全可以取代原始的回調和消息映射機制。在Qt中信號和插槽取代了上述這些凌亂的函數指針,使得用戶編寫這些通信程序更為簡潔明了。信號和插槽能攜帶任意數量和任意類型的參數,他們是類型完全安全的,因此不會像回調函數那樣產生coredumps。,Qt/Embedded信號和插槽機制(2),所有從QObject或其子類(例如Qwidget)派生的類都能夠包含信號和插槽。當對象改變狀態(tài)時,信號就由該對象發(fā)射(emit)出去了,這就是對象所要做的全部工作,它不知道另一端是誰在接收這個信號。這就是真正的信息封裝,它確保對象被當作一個真正的軟件組件來使用。插槽用于接收信號,但它們是普通的對象成員函數。一個插槽并不知道是否有任何信號與自己相連接。而且,對象并不了解具體的通信機制。用戶可以將很多信號與單個插槽進行連接,也可以將單個信號與很多插槽進行連接,甚至將一個信號與另外一個信號相連接也是可能的,這時無論第一個信號什么時候發(fā)射,系統(tǒng)都將立刻發(fā)射第二個信號??傊盘柵c插槽構造了一個強大的部件編程機制。,Qt/Embedded信號和插槽機制(3),,信號,當某個信號對其客戶或所有者內部狀態(tài)發(fā)生改變時,信號就被一個對象發(fā)射。只有定義了這個信號的類及其派生類才能夠發(fā)射這個信號。當一個信號被發(fā)射時,與其相關聯(lián)的插槽將被立刻執(zhí)行,就像一個正常的函數調用一樣。信號-插槽機制完全獨立于任何GUI事件循環(huán)。只有當所有的槽返回以后發(fā)射函數(emit)才返回。如果存在多個槽與某個信號相關聯(lián),那么,當這個信號被發(fā)射時,這些槽將會一個接一個地執(zhí)行,但是它們執(zhí)行的順序將會是隨機的、不確定的,用戶不能人為地指定哪個先執(zhí)行、哪個后執(zhí)行。,信號示例:signals:voidmySignal();voidmySignal(intx);voidmySignalParam(intx,inty);,插槽示例:publicslots:voidmySlot();voidmySlot(intx);voidmySignalParam(intx,inty);,插槽,插槽是普通的C++成員函數,可以被正常調用,它們惟一的特殊性就是很多信號可以與其相關聯(lián)。插槽可以有參數,但插槽的參數不能有缺省值。插槽函數也分為3種類型,即publicslots、privateslots和protectedslots。?publicslots:在這個區(qū)內聲明的槽意味著任何對象都可將信號與之相連接。這對于組件編程非常有用,用戶可以創(chuàng)建彼此互不了解的對象,將它們的信號與槽進行連接以便信息能夠正確地傳遞。?protectedslots:在這個區(qū)內聲明的槽意味著當前類及其子類可以將信號與之相連接。這適用于那些槽,它們是類實現(xiàn)的一部分,但是其界面接口卻面向外部。?privateslots:在這個區(qū)內聲明的槽意味著只有類自己可以將信號與之相連接。這適用于聯(lián)系非常緊密的類。,信號與插槽關聯(lián),通過調用QObject對象的connect()函數可以將某個對象的信號與另外一個對象的插槽函數或信號相關聯(lián),當發(fā)射者發(fā)射信號時,接收者的槽函數或信號將被調用。這個函數的作用就是將發(fā)射者sender對象中的信號signal與接收者receiver中的member插槽函數聯(lián)系起來。當指定信號signal時必須使用Qt的宏SIGNAL(),當指定插槽函數時必須使用宏SLOT()。如果發(fā)射者與接收者屬于同一個對象的話,那么在connect()調用中接收者參數可以省略。,boolQObject::connect(constQObject*sender,constchar*signal,constQObject*receiver,constchar*member)[static],解除信號與插槽關聯(lián),當信號與槽沒有必要繼續(xù)保持關聯(lián)時,用戶可以使用disconnect()函數來斷開連接。有3種情況必須使用disconnect()函數。?斷開與某個對象相關聯(lián)的任何對象?斷開與某個特定信號的任何關聯(lián)?斷開兩個對象之間的關聯(lián),boolQObject::disconnect(constQObject*sender,constchar*signal,constObject*receiver,constchar*member)[static],常見通用窗口組合(1),常見通用窗口組合(2),- 配套講稿:
如PPT文件的首頁顯示word圖標,表示該PPT已包含配套word講稿。雙擊word圖標可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設計者僅對作品中獨創(chuàng)性部分享有著作權。
- 關 鍵 詞:
- 嵌入式 Linux 驅動程序 QT
裝配圖網所有資源均是用戶自行上傳分享,僅供網友學習交流,未經上傳用戶書面授權,請勿作他用。
鏈接地址:http://m.jqnhouse.com/p-11531299.html