基于ARM的多線程應(yīng)用程序設(shè)計_第1頁
基于ARM的多線程應(yīng)用程序設(shè)計_第2頁
基于ARM的多線程應(yīng)用程序設(shè)計_第3頁
基于ARM的多線程應(yīng)用程序設(shè)計_第4頁
基于ARM的多線程應(yīng)用程序設(shè)計_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、開放性實驗報告題目:基于ARM的多線程應(yīng)用程序設(shè)計院系名稱:電氣工程學院專業(yè)班級:自動1302學生姓名:張鵬濤學號:201323020219指導教師:張曉東成績:指導老師簽名: 日期:2017.1.6 目 錄1 系統(tǒng)概述與設(shè)計要求11。1 系統(tǒng)概述11。2 設(shè)計要求22 方案論證22.1 實現(xiàn)方法22.2 線程優(yōu)勢23 硬件設(shè)計33.1 樹莓派接口驅(qū)動LED電路設(shè)計34 軟件設(shè)計44.1 驅(qū)動三色LED燈44.1。1 驅(qū)動實現(xiàn)方法44.1.2 wiringPi庫安裝和軟件編程44。2 服務(wù)器和客戶端54。2。1 服務(wù)器設(shè)計方法54。2.2 客戶端設(shè)計方法55 系統(tǒng)調(diào)試6設(shè)計心得6參考文獻7附錄

2、1(LED驅(qū)動程序)8附錄2(服務(wù)器程序)10附錄3(客戶端程序代碼)161 系統(tǒng)概述與設(shè)計要求1.1 系統(tǒng)概述 本系統(tǒng)設(shè)計是基于樹莓派開發(fā)板上實現(xiàn)的,樹莓派由注冊于英國的慈善組織“Raspberry Pi 基金會”開發(fā),Eben·Upton/埃·厄普頓為項目帶頭人.2012年3月,英國劍橋大學埃本·阿普頓(Eben Epton)正式發(fā)售世界上最小的臺式機,又稱卡片式電腦,外形只有信用卡大小,卻具有電腦的所有基本功能,這就是Raspberry Pi電腦板,中文譯名”樹莓派".它是一款基于ARM的微型電腦主板,以SD/MicroSD卡為內(nèi)存硬盤,卡片主板周

3、圍有1/2/4個USB接口和一個10/100 以太網(wǎng)接口(A型沒有網(wǎng)口),可連接鍵盤、鼠標和網(wǎng)線,同時擁有視頻模擬信號的電視輸出接口和HDMI高清視頻輸出接口,以上部件全部整合在一張僅比信用卡稍大的主板上,具備所有PC的基本功能。而樹莓派2具有900MHz內(nèi)核頻率, 4核 ARM Cortex-A7,1GB 內(nèi)存,帶Micro SD 卡插槽(支持通過它啟動 Linux 操作系統(tǒng),如 Fedora),40PIN接口(可以增加驅(qū)動外設(shè)).本系統(tǒng)設(shè)計正式在樹莓派2環(huán)境下開發(fā)實現(xiàn)多線程設(shè)計,設(shè)計的主要功能就是兩個客戶端通過服務(wù)器互相收發(fā)信息。1。2 設(shè)計要求 要求多個客戶端能夠同時連接服務(wù)器,而服務(wù)器

4、需要創(chuàng)建線程來管理這多個客戶端,并且能夠把一個客戶端發(fā)來的數(shù)據(jù)進行解析,發(fā)給另一個客戶端,實現(xiàn)兩個甚至多個客戶端互相收發(fā)信息.能夠通過驅(qū)動三色燈來發(fā)現(xiàn)系統(tǒng)運行的狀態(tài),紅色說明有錯誤發(fā)生,綠色說明正在正常運行,藍色說明有用戶連接,綠色說明有客戶端互相收發(fā)信息。2 方案論證2。1 實現(xiàn)方法 要實現(xiàn)服務(wù)器同時管理兩個甚至多個客戶端,就必須引入進程或線程。2。2 線程優(yōu)勢 一是和進程相比,它是一種非?!惫?jié)儉”的多任務(wù)操作方式。 進程是系統(tǒng)中程序執(zhí)行和資源分配的基本單位。我們知道,在Linux系統(tǒng)下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的數(shù)據(jù)表來維護它的代碼段、堆棧段和數(shù)據(jù)段,這就導致了

5、進程在進行切換等操作起到了現(xiàn)場保護作用, 這是一種”昂貴"的多任務(wù)工作方式。 但是為了進一步減少處理機的空轉(zhuǎn)時間支持多處理器和減少上下文切換開銷,進程演化中出現(xiàn)了另外一個概念,這就是線程,也被人稱為輕量級的進程。它是一個進程內(nèi)的基本調(diào)度單位。線程是在共享的內(nèi)存空間中并發(fā)的多道執(zhí)行路徑,它們共享一個進程的資源,比如文件描述符和信號處理等.因此,大大減少了上下文切換的開銷. 二是線程間方便的通信機制。 對不同進程來說,它們具有獨立的數(shù)據(jù)空間,要進行數(shù)據(jù)的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由于同一進程下的線程之間共享數(shù)據(jù)空間,所以一個線程的數(shù)據(jù)可以直接

6、為其它線程所用,這不僅快捷,而且方便。當然,數(shù)據(jù)的共享也帶來其他一些問題,有的變量不能同時被兩個線程所修改,有的子程序中聲明為static的數(shù)據(jù)更有可能給多線程程序帶來災難性的打擊,這些正是編寫多線程程序時最需要注意的地方。3 硬件設(shè)計3。1 樹莓派接口驅(qū)動LED電路設(shè)計圖 3。1 從圖3.1可以知道,要想讓三色燈的紅色亮起來,首先控制樹莓派GPIO.27引腳輸出低電平,同理可以控制GPIO。28、GPIO29引腳電瓶來控制綠、藍LED的啟動和關(guān)閉。樹莓派開發(fā)板上的相關(guān)引腳如圖3。2.圖 3。24 軟件設(shè)計4。1 驅(qū)動三色LED燈4。1。1 驅(qū)動實現(xiàn)方法 控制引腳電瓶的高低就能實現(xiàn)控制LED燈

7、的變化,實際上三色LED可以顯示無數(shù)種顏色,要想超過三種顏色的顯示實現(xiàn),就必須引入PWM.PWM是模擬脈寬調(diào)制來控制輸出引腳的實際輸出電瓶大小,此系統(tǒng)可以控制引腳從03.3V變化來顯示不同的顏色。wiringPi適合那些具有C語言基礎(chǔ),在接觸樹莓派之前已經(jīng)接觸過單片機或者嵌入式開發(fā)的人群。wiringPi的API函數(shù)和arduino非常相似,這也使得它廣受歡迎.作者給出了大量的說明和示例代碼,這些示例代碼也包括UART設(shè)備,I2C設(shè)備和SPI設(shè)備等.4。1.2 wiringPi庫安裝和軟件編程 首先需要在樹莓派上安裝wiringPi庫,我們選擇直接在網(wǎng)上下載安裝源碼,輸入命令:cd 進入根目錄

8、下,輸入命令:git clone git://wiringPi 從網(wǎng)上下載源碼包,輸入命令cd wiringPi 進入安裝包目錄下,依次輸入命令:configure make make install來配置、編譯和安裝,最后輸入命令sudo 。/build 來執(zhí)行編譯之后生成的可執(zhí)行文件,完成安裝。最后輸入命令:gpio readall會出來引腳圖來確定已經(jīng)安裝成功。 接下來就需要運用庫的軟件編程來驅(qū)動led燈啦,在寫C文件時首先要加入庫的頭文件:#include wiringPi。h>和C語言必要的頭文件:include stdio。h,然后還需要加入實現(xiàn)軟

9、件PWM的頭文件:#include softPwm.h。接下來我們就需要運用庫的API函數(shù)wiringPiSetup()初始化wiringPi,若初始化失敗會返回1;然后運用庫的API函數(shù)softPwmCreate()創(chuàng)建軟件PWM,此函數(shù)有3個輸入?yún)?shù),分別是控制引腳號,PWM最小值,PWM最大值;運用庫的API函數(shù)softPwmWrite()寫PWM的值,此函數(shù)有2個輸入?yún)?shù),分別是控制那個引腳號,寫入的PWM的值,此值需要在最小最大值之間。 完整代碼如附錄1。4.2 服務(wù)器和客戶端4。2。1 服務(wù)器設(shè)計方法 為了方便起見,我們把服務(wù)器和客戶端都定義在本地IP上進行測試,服務(wù)器端的話,首先

10、我們需要把主函數(shù)傳入的端口號記錄下來,并且利用C語言標準函數(shù)atoi轉(zhuǎn)換成整型值。接著我們定義兩個整型數(shù)組來存放兩個客戶端的套接字,然后我們根據(jù)端口去創(chuàng)建服務(wù)器,創(chuàng)建服務(wù)器需要幾個函數(shù)來實現(xiàn),第一個就是socket()函數(shù)來創(chuàng)建一個服務(wù)器的套接字,此函數(shù)有3個輸入?yún)?shù),我們選擇ipv4協(xié)議族,流式Socket,TCP協(xié)議類型。然后根據(jù)端口號和本地IP配置服務(wù)器,之后就是調(diào)用綁定bind(),監(jiān)聽listen()函數(shù)來完成服務(wù)器的創(chuàng)建。之后就是根據(jù)創(chuàng)建的套接字來進行循環(huán),如果有客戶端連接,就保存客戶端套接字創(chuàng)建一個線程去處理,此處我們以兩個客戶端為例來進行操作.若是套接字編號0發(fā)來消息,我們就轉(zhuǎn)

11、發(fā)給套接字編號1,若是超過2個的客戶端連接進來我們直接關(guān)閉創(chuàng)建的線程就行,之后要是有客戶端掉線,就把線程和客戶端一塊銷毀。 具體代碼實現(xiàn)見附錄24.2。2 客戶端設(shè)計方法 首先我們封裝三個函數(shù),分別是連接、讀數(shù)據(jù)、寫數(shù)據(jù),開始就調(diào)用連接函數(shù),在連接函數(shù)里我們創(chuàng)建客戶端并通過輸入的服務(wù)器ip和端口去連接服務(wù)器,然后我們創(chuàng)建兩個線程分別是讀和寫,在讀函數(shù)里我們不間斷讀鍵盤數(shù)據(jù)并發(fā)送給服務(wù)器,在寫函數(shù)里不間斷的讀服務(wù)器發(fā)來的數(shù)據(jù)并顯示在屏幕上。 具體代碼實現(xiàn)見附錄3.5 系統(tǒng)調(diào)試 此系統(tǒng)的調(diào)試,我們選擇Linux虛擬機模擬調(diào)試,首先運行服務(wù)器和兩個客戶端,然后客戶端連接服務(wù)器,之后兩個客戶端互相收發(fā)

12、數(shù)據(jù).為了方便起見,我在PC機上運行和仿真,首先安裝虛擬機VMware8。0,然后安裝VMware Tools,虛擬機的工具是為了共享電腦上的文件,這樣可以在電腦上編寫代碼,在虛擬機上編譯運行. 編譯服務(wù)器的代碼,輸入命令gcc server。c o server。exe lpthread,回車之后會生成server。exe可執(zhí)行文件,之后我們運行服務(wù)器,輸入命令。/server.exe 6789,運行服務(wù)器,其中6789為輸入的端口號。之后編譯客戶端代碼,輸入命令gcc client。c -o client。exe lpthread,回車之后會生成client.exe可執(zhí)行文件,我們事先查看

13、虛擬機ip,輸入命令ifconfig回車就能看到虛擬機本機ip,為我們客戶端連接服務(wù)器所用.之后我們運行客戶端一,輸入命令。/client。exe 192.168.20。109 6789,回車,然后用同樣的命令運行客戶端二,之后我們在一個客戶端輸入信息回車,在另一個客戶端就能接收到,具體運行結(jié)果如圖5。1,5。2,5。3。圖 5。1圖5。2圖5。3設(shè)計心得此次開發(fā)性試驗設(shè)計讓我收獲甚多.一是要有一個積極的心態(tài),獨立解決問題的意識,培養(yǎng)扎實基礎(chǔ)的認識.不要什么東西都感覺跟簡單(很多東西可能是看似簡單)就不去做了或者不屑一做,以至于性網(wǎng)上搜搜就可以了,這樣很不好。有自己的東西有自己的付出才會有程序

14、運行成功時的喜悅和小自豪,這樣也有助于培養(yǎng)自己的興趣。要時刻牢記態(tài)度決定一切。其次是興趣,感覺學習工作中興趣很關(guān)鍵,只是一個引發(fā)人積極性的問題,有了興趣就自覺了,效率自然就高了。再次要敢于嘗試和挑戰(zhàn)。不要安于現(xiàn)成的程序,而且不要害怕失敗,在程序調(diào)試的過程中這點尤為重要,“發(fā)現(xiàn)出問題然后解決問題”是一個積累經(jīng)驗的過程,而且很高效.最后要不懈追求.對于源代碼進行不斷的完善,要盡可能的實現(xiàn)課題所要求的功能.對于初學者或者開發(fā)較少的人來說,大量大寫程序還是有必要的,但同時要注意思考,理解其實現(xiàn)的內(nèi)在意義.還可以自己添加一些有意義的功能來實現(xiàn).當看到自己編寫的程序正常運行時,興趣也會隨之而來,樂此不疲,

15、形成一個良性循環(huán)。  短短一周的開放性ARM多線程設(shè)計很快結(jié)束了,我發(fā)現(xiàn)我對嵌入式這個方向、對嵌入式技術(shù)、對Linux都有了新的認識。通過這次的編程,我了解到,要真真正正的掌握計算機程序還不是一件簡單容易的事兒,但真正掌握后,它帶給我們的將是無窮的便捷與科技,我喜歡高端便捷的生活.我希望我能做計算機這個萬能機器人的主人而不是奴隸,我會努力加油的!參考文獻1徐千洋.Linux C函數(shù)庫參考手冊.M中國青年出版社。2002  2馬忠梅,馬廣云,徐英慧,田譯。ARM嵌入式處理結(jié)構(gòu)與應(yīng)用基礎(chǔ)M。北京航空航天大學出版社。2002 3鄒思鐵.嵌入式Linu

16、x設(shè)計與應(yīng)用M.北京清華大學出版社。2002 4杜春雷。ARM體系結(jié)構(gòu)與編程M.清華大學出版社。2003 5田澤。嵌入式系統(tǒng)開發(fā)與應(yīng)用M.北京航空航天大學出版社.2005 11陳鑫.嵌入式軟件技術(shù)的現(xiàn)狀與發(fā)展動向M.軟件世界.2001 6田澤。嵌入式系統(tǒng)開發(fā)與應(yīng)用實驗教程M.北京航空航天大學出版社。2004 7Alessandro Rubini,Jonathan Corbet.Linux設(shè)備驅(qū)動程序M。中國電力出版社.2002附錄1(LED驅(qū)動程序)include wiringPi.h>include softPwm。

17、h>include stdio.h>#define uchar unsigned chardefine LedPinRed 27define LedPinGreen 28define 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) softPwmWrit

18、e(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); ledColor

19、Set(0x00,0x00,0xff); /blue delay(500); return 0;附錄2(服務(wù)器程序)include <stdio。h include <stdlib.h> include string。h #include <signal。h #include <unistd.h include error。h include errno。h> include <fcntl。h> include <sys/types.h> include sys/socket。h> include sys/epoll.h>

20、 include <netinet/in.h> include <arpa/inet。h #include pthread。h 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”, strer

21、ror(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);

22、 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,

23、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)

24、; 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

25、= recv(socket_clientindex, buf, sizeof(buf), 0); if (rc = 0) if (rc = 0) printf("%d:recv disconnectionn", index); else printf(”d:recv failed, %sn”, index, strerror(errno); close(socket_clientindex); socket_clientindex = 0; break; else printf(”d:recv:s,recv:u bytesn”, index, buf, rc); deliv

26、er(index, buf, rc); void socket_handle(void arg) int client_st = (int )arg; free(int )arg); printf(”zhang。pt:handle_thread is beginn”); int index = 0; if (socket_client0 = 0) socket_client0 = client_st; else if (socket_client1 = 0) socket_client1 = client_st; index = 1; else close(client_st); return

27、 NULL; socket_work(index); printf("zhang.pt:handle_thread is endn"); return NULL; void sockaddr_toa(const struct sockaddr_in addr, char IPAddr) unsigned char p = (unsigned char *)(addrsin_addr。s_addr); sprintf(IPAddr, ”u。u.%u。%u”, p0, p1, p2, p3); void socket_accept(int st) pthread_t thr_d

28、; 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); i

29、f(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)

30、; 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(s

31、ocket_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 <stdio。h> include <stdlib。h include <string。h> include <errno。h include unistd.h include arpa/inet.h> include &

32、lt;sys/types。hinclude sys/socket.h include <pthread。h 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 = s

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論