




免費預覽已結束,剩余12頁可下載查看
下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
開放性實驗報告題 目: 基于ARM的多線程應用程序設計 院系名稱: 電氣工程學院 專業班級: 自動1302 學生姓名: 張鵬濤 學 號: 201323020219 指導教師: 張曉東 成績:指導老師簽名: 日期:2017.1.6 目 錄1 系統概述與設計要求11.1 系統概述11.2 設計要求22 方案論證22.1 實現方法22.2 線程優勢23 硬件設計33.1 樹莓派接口驅動LED電路設計34 軟件設計44.1 驅動三色LED燈44.1.1 驅動實現方法44.1.2 wiringPi庫安裝和軟件編程44.2 服務器和客戶端54.2.1 服務器設計方法54.2.2 客戶端設計方法55 系統調試6設計心得6參考文獻7附錄1(LED驅動程序)8附錄2(服務器程序)10附錄3(客戶端程序代碼)161 系統概述與設計要求1.1 系統概述 本系統設計是基于樹莓派開發板上實現的,樹莓派由注冊于英國的慈善組織“Raspberry Pi 基金會”開發,EbenUpton/埃厄普頓為項目帶頭人。2012年3月,英國劍橋大學埃本阿普頓(Eben Epton)正式發售世界上最小的臺式機,又稱卡片式電腦,外形只有信用卡大小,卻具有電腦的所有基本功能,這就是Raspberry Pi電腦板,中文譯名樹莓派。它是一款基于ARM的微型電腦主板,以SD/MicroSD卡為內存硬盤,卡片主板周圍有1/2/4個USB接口和一個10/100 以太網接口(A型沒有網口),可連接鍵盤、鼠標和網線,同時擁有視頻模擬信號的電視輸出接口和HDMI高清視頻輸出接口,以上部件全部整合在一張僅比信用卡稍大的主板上,具備所有PC的基本功能。而樹莓派2具有900MHz內核頻率, 4核 ARM Cortex-A7,1GB 內存,帶Micro SD 卡插槽(支持通過它啟動 Linux 操作系統,如 Fedora),40PIN接口(可以增加驅動外設)。本系統設計正式在樹莓派2環境下開發實現多線程設計,設計的主要功能就是兩個客戶端通過服務器互相收發信息。1.2 設計要求 要求多個客戶端能夠同時連接服務器,而服務器需要創建線程來管理這多個客戶端,并且能夠把一個客戶端發來的數據進行解析,發給另一個客戶端,實現兩個甚至多個客戶端互相收發信息。能夠通過驅動三色燈來發現系統運行的狀態,紅色說明有錯誤發生,綠色說明正在正常運行,藍色說明有用戶連接,綠色說明有客戶端互相收發信息。2 方案論證2.1 實現方法 要實現服務器同時管理兩個甚至多個客戶端,就必須引入進程或線程。2.2 線程優勢 一是和進程相比,它是一種非常節儉的多任務操作方式。 進程是系統中程序執行和資源分配的基本單位。我們知道,在Linux系統下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的數據表來維護它的代碼段、堆棧段和數據段,這就導致了進程在進行切換等操作起到了現場保護作用, 這是一種昂貴的多任務工作方式。 但是為了進一步減少處理機的空轉時間支持多處理器和減少上下文切換開銷,進程演化中出現了另外一個概念,這就是線程,也被人稱為輕量級的進程。它是一個進程內的基本調度單位。線程是在共享的內存空間中并發的多道執行路徑,它們共享一個進程的資源,比如文件描述符和信號處理等。因此,大大減少了上下文切換的開銷。 二是線程間方便的通信機制。 對不同進程來說,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由于同一進程下的線程之間共享數據空間,所以一個線程的數據可以直接為其它線程所用,這不僅快捷,而且方便。當然,數據的共享也帶來其他一些問題,有的變量不能同時被兩個線程所修改,有的子程序中聲明為static的數據更有可能給多線程程序帶來災難性的打擊,這些正是編寫多線程程序時最需要注意的地方。3 硬件設計3.1 樹莓派接口驅動LED電路設計圖 3.1 從圖3.1可以知道,要想讓三色燈的紅色亮起來,首先控制樹莓派GPIO.27引腳輸出低電平,同理可以控制GPIO.28、GPIO29引腳電瓶來控制綠、藍LED的啟動和關閉。樹莓派開發板上的相關引腳如圖3.2。圖 3.24 軟件設計4.1 驅動三色LED燈4.1.1 驅動實現方法 控制引腳電瓶的高低就能實現控制LED燈的變化,實際上三色LED可以顯示無數種顏色,要想超過三種顏色的顯示實現,就必須引入PWM。PWM是模擬脈寬調制來控制輸出引腳的實際輸出電瓶大小,此系統可以控制引腳從03.3V變化來顯示不同的顏色。wiringPi適合那些具有C語言基礎,在接觸樹莓派之前已經接觸過單片機或者嵌入式開發的人群。wiringPi的API函數和arduino非常相似,這也使得它廣受歡迎。作者給出了大量的說明和示例代碼,這些示例代碼也包括UART設備,I2C設備和SPI設備等。4.1.2 wiringPi庫安裝和軟件編程 首先需要在樹莓派上安裝wiringPi庫,我們選擇直接在網上下載安裝源碼,輸入命令:cd 進入根目錄下,輸入命令:git clone git://wiringPi 從網上下載源碼包,輸入命令cd wiringPi 進入安裝包目錄下,依次輸入命令:configure make make install來配置、編譯和安裝,最后輸入命令sudo ./build 來執行編譯之后生成的可執行文件,完成安裝。最后輸入命令:gpio readall會出來引腳圖來確定已經安裝成功。 接下來就需要運用庫的軟件編程來驅動led燈啦,在寫C文件時首先要加入庫的頭文件:#include 和C語言必要的頭文件:#include ,然后還需要加入實現軟件PWM的頭文件:#include 。接下來我們就需要運用庫的API函數wiringPiSetup()初始化wiringPi,若初始化失敗會返回-1;然后運用庫的API函數softPwmCreate()創建軟件PWM,此函數有3個輸入參數,分別是控制引腳號,PWM最小值,PWM最大值;運用庫的API函數softPwmWrite()寫PWM的值,此函數有2個輸入參數,分別是控制那個引腳號,寫入的PWM的值,此值需要在最小最大值之間。 完整代碼如附錄1。4.2 服務器和客戶端4.2.1 服務器設計方法 為了方便起見,我們把服務器和客戶端都定義在本地IP上進行測試,服務器端的話,首先我們需要把主函數傳入的端口號記錄下來,并且利用C語言標準函數atoi轉換成整型值。接著我們定義兩個整型數組來存放兩個客戶端的套接字,然后我們根據端口去創建服務器,創建服務器需要幾個函數來實現,第一個就是socket()函數來創建一個服務器的套接字,此函數有3個輸入參數,我們選擇ipv4協議族,流式Socket,TCP協議類型。然后根據端口號和本地IP配置服務器,之后就是調用綁定bind(),監聽listen()函數來完成服務器的創建。之后就是根據創建的套接字來進行循環,如果有客戶端連接,就保存客戶端套接字創建一個線程去處理,此處我們以兩個客戶端為例來進行操作。若是套接字編號0發來消息,我們就轉發給套接字編號1,若是超過2個的客戶端連接進來我們直接關閉創建的線程就行,之后要是有客戶端掉線,就把線程和客戶端一塊銷毀。 具體代碼實現見附錄24.2.2 客戶端設計方法 首先我們封裝三個函數,分別是連接、讀數據、寫數據,開始就調用連接函數,在連接函數里我們創建客戶端并通過輸入的服務器ip和端口去連接服務器,然后我們創建兩個線程分別是讀和寫,在讀函數里我們不間斷讀鍵盤數據并發送給服務器,在寫函數里不間斷的讀服務器發來的數據并顯示在屏幕上。 具體代碼實現見附錄3。5 系統調試 此系統的調試,我們選擇Linux虛擬機模擬調試,首先運行服務器和兩個客戶端,然后客戶端連接服務器,之后兩個客戶端互相收發數據。為了方便起見,我在PC機上運行和仿真,首先安裝虛擬機VMware8.0,然后安裝VMware Tools,虛擬機的工具是為了共享電腦上的文件,這樣可以在電腦上編寫代碼,在虛擬機上編譯運行。 編譯服務器的代碼,輸入命令gcc server.c -o server.exe -lpthread,回車之后會生成server.exe可執行文件,之后我們運行服務器,輸入命令./server.exe 6789,運行服務器,其中6789為輸入的端口號。之后編譯客戶端代碼,輸入命令gcc client.c -o client.exe -lpthread,回車之后會生成client.exe可執行文件,我們事先查看虛擬機ip,輸入命令ifconfig回車就能看到虛擬機本機ip,為我們客戶端連接服務器所用。之后我們運行客戶端一,輸入命令./client.exe 09 6789,回車,然后用同樣的命令運行客戶端二,之后我們在一個客戶端輸入信息回車,在另一個客戶端就能接收到,具體運行結果如圖5.1,5.2,5.3。圖 5.1圖5.2圖5.3設計心得 此次開發性試驗設計讓我收獲甚多。一是要有一個積極的心態,獨立解決問題的意識,培養扎實基礎的認識。不要什么東西都感覺跟簡單(很多東西可能是看似簡單)就不去做了或者不屑一做,以至于性網上搜搜就可以了,這樣很不好。有自己的東西有自己的付出才會有程序運行成功時的喜悅和小自豪,這樣也有助于培養自己的興趣。要時刻牢記態度決定一切。其次是興趣,感覺學習工作中興趣很關鍵,只是一個引發人積極性的問題,有了興趣就自覺了,效率自然就高了。再次要敢于嘗試和挑戰。不要安于現成的程序,而且不要害怕失敗,在程序調試的過程中這點尤為重要,“發現出問題然后解決問題”是一個積累經驗的過程,而且很高效。最后要不懈追求。對于源代碼進行不斷的完善,要盡可能的實現課題所要求的功能。對于初學者或者開發較少的人來說,大量大寫程序還是有必要的,但同時要注意思考,理解其實現的內在意義。還可以自己添加一些有意義的功能來實現。當看到自己編寫的程序正常運行時,興趣也會隨之而來,樂此不疲,形成一個良性循環。 短短一周的開放性ARM多線程設計很快結束了,我發現我對嵌入式這個方向、對嵌入式技術、對Linux都有了新的認識。通過這次的編程,我了解到,要真真正正的掌握計算機程序還不是一件簡單容易的事兒,但真正掌握后,它帶給我們的將是無窮的便捷與科技,我喜歡高端便捷的生活。我希望我能做計算機這個萬能機器人的主人而不是奴隸,我會努力加油的!參考文獻1徐千洋.LinuxC函數庫參考手冊.M中國青年出版社.20022馬忠梅,馬廣云,徐英慧,田譯.ARM嵌入式處理結構與應用基礎M.北京航空航天大學出版社.20023鄒思鐵.嵌入式Linux設計與應用M.北京清華大學出版社.20024杜春雷.ARM體系結構與編程M.清華大學出版社.20035田澤.嵌入式系統開發與應用M.北京航空航天大學出版社.200511陳鑫.嵌入式軟件技術的現狀與發展動向M.軟件世界.20016田澤.嵌入式系統開發與應用實驗教程M.北京航空航天大學出版社.20047AlessandroRubini,JonathanCorbet.Linux設備驅動程序M.中國電力出版社.2002附錄1(LED驅動程序)#include #include #include #define uchar unsigned char#define LedPinRed 27#define LedPinGreen 28#define LedPinBlue 29void ledInit(void) softPwmCreate(LedPinRed, 0, 100); softPwmCreate(LedPinGreen,0, 100); softPwmCreate(LedPinBlue, 0, 100);void ledColorSet(uchar r_val, uchar g_val, uchar b_val) softPwmWrite(LedPinRed, r_val); softPwmWrite(LedPinGreen, g_val); softPwmWrite(LedPinBlue, b_val);int main(void) int i; if(wiringPiSetup() = -1) printf(setup wiringPi failed !); return 1; ledInit(); while(1) ledColorSet(0xff,0x00,0x00); /red delay(500); ledColorSet(0x00,0xff,0x00); /green delay(500); ledColorSet(0x00,0x00,0xff); /blue delay(500); return 0;附錄2(服務器程序)#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BUFSIZE 1024 int socket_client2; int socket_create(int port) int st = socket(AF_INET, SOCK_STREAM, 0); int on = 1; if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) = -1) printf(setsockopt is failed %sn, strerror(errno); return 0; struct sockaddr_in addr; memset(&addr, 0, sizeof(addr); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(st, (struct sockaddr *) &addr, sizeof(addr) = -1) printf(zhang.pt:bind is failed %sn, strerror(errno); return 0; if (listen(st, 300) = -1) printf(zhang.pt:listen is failed %sn, strerror(errno); return 0; return st; void deliver(int index, const char *buf, ssize_t len) ssize_t rc = 0; if(index = 0) if (socket_client1 = 0) printf(%d:user not onlinen, index); else rc = send(socket_client1, buf, len, 0); printf(send:%s,send:%u bytesn, buf, rc); if (rc = 0) if (rc = 0) printf(zhang.pt:send failed, disconnection,n); else printf(zhang.pt:send failed, %sn, strerror(errno); if(index = 1) if(socket_client0 = 0) printf(%d:user not onlinen, index); else rc = send(socket_client0, buf, len, 0); printf(send:%s,send:%u bytesn, buf, rc); if(rc = 0) if (rc = 0) printf(zhang.pt:send failed, disconnection,n); else printf(zhang.pt:send failed, %sn, strerror(errno); void socket_work(int index) char bufBUFSIZE; ssize_t rc = 0; while(1) memset(buf, 0, sizeof(buf); rc = recv(socket_clientindex, buf, sizeof(buf), 0); if (rc sin_addr.s_addr); sprintf(IPAddr, %u.%u.%u.%u, p0, p1, p2, p3); void socket_accept(int st) pthread_t thr_d; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); struct sockaddr_in client_addr; socklen_t len = sizeof(client_addr); while(1) memset(&client_addr, 0, sizeof(client_addr); int client_st = accept(st, (void *)&client_addr, &len); if(client_st = -1) printf(zhang.pt:accept failed %sn, strerror(errno); break; else char sIP32; memset(sIP, 0, sizeof(sIP); sockaddr_toa(&client_addr, sIP); printf(zhang.pt:accept by %sn, sIP); int *tmp = malloc(sizeof(int); *tmp = client_st; pthread_create(&thr_d, &attr, socket_handle, tmp); pthread_attr_destroy(&attr); int main(int arg, char *args) if(arg 2) printf(zhang.pt:server port error!n); return 0; int iport = atoi(args1); if(iport = 0) printf(zhang.pt:port %d is invalid!n, iport); return 0; printf(zhang.pt:server is begin*v*!n); memset(socket_client, 0, sizeof(socket_client); int st = socket_create(iport); if(st = 0) return 0; socket_accept(st); close(st); printf(zhang.pt:server is endn); return 0; 附錄3(客戶端程序代碼)#include #include #include #include #include #include #include #include #include #define BUFSIZE 1024 void *socket_read(void *arg) int st = *(int *)arg; char bufBUFSIZE; while(1) memset(buf, 0, sizeof(buf); ssize_t rc = recv(st, buf, sizeof(buf), 0); if(rc = 0) printf(zhang.pt:recv failed, %sn, strerror(errno); break; else printf(zhang.pt:recv:%s,recv:%u byten, buf, rc); return NULL; void *socket_write(void *arg) int st = *(int *)arg; char bufBUFSIZE; while(1) memset(buf, 0, sizeof(buf); read(STDIN_FILENO, buf, sizeof(buf); int ilen = strlen(buf); if(bufilen - 1 = n) bufilen - 1 = 0; ssize_t rc = send(st, buf, sizeof(buf), 0); printf(zhang.pt:send:%s,send:%u byten, buf, rc); if(rc = 0) printf(zhang.pt:
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- led大屏日常管理制度
- 春節放假值班管理制度
- 監督所文明單位管理制度
- 景區多人吸氧管理制度
- 大公司自助設備管理制度
- mtm藥物治療管理制度
- 景區設施使用管理制度
- 對外包保安公司管理制度
- 旅游公司保安管理制度
- 學生辦公室設備管理制度
- 國內外高等教育教材比較研究課題
- 浙江省紹興市諸暨市2023-2024學年五年級下學期期末數學試卷
- 重慶市大足縣2023-2024學年四年級數學第二學期期末聯考試題含解析
- 煤礦調度智能化培訓課件
- 基于PLC的啤酒發酵自動控制系統
- 重慶市沙坪壩區2022-2023學年八年級下學期期末英語試題
- 思辨與創新智慧樹知到期末考試答案章節答案2024年復旦大學
- 手術室-標準側臥位擺放
- (正式版)JBT 9229-2024 剪叉式升降工作平臺
- 合伙人退出協議書
- (高清版)DZT 0208-2020 礦產地質勘查規范 金屬砂礦類
評論
0/150
提交評論