2023-2023嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)實(shí)驗(yàn)指導(dǎo)書(shū)_第1頁(yè)
2023-2023嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)實(shí)驗(yàn)指導(dǎo)書(shū)_第2頁(yè)
2023-2023嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)實(shí)驗(yàn)指導(dǎo)書(shū)_第3頁(yè)
2023-2023嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)實(shí)驗(yàn)指導(dǎo)書(shū)_第4頁(yè)
2023-2023嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)實(shí)驗(yàn)指導(dǎo)書(shū)_第5頁(yè)
已閱讀5頁(yè),還剩42頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

《嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)》實(shí)驗(yàn)課程指導(dǎo)書(shū)適用專業(yè):計(jì)科、軟件修訂:李社蕾、郭海智審定:郭亮三亞學(xué)院理工學(xué)院2023年8月目錄一、課程基本信息3二、實(shí)驗(yàn)教學(xué)的總體目的和要求3三、實(shí)驗(yàn)教學(xué)內(nèi)容3實(shí)驗(yàn)項(xiàng)目一多文件makefile編寫(xiě)實(shí)驗(yàn)5實(shí)驗(yàn)項(xiàng)目二主機(jī)開(kāi)發(fā)環(huán)境搭建8實(shí)驗(yàn)項(xiàng)目三嵌入式開(kāi)發(fā)環(huán)境搭建12實(shí)驗(yàn)項(xiàng)目四文件讀寫(xiě)及上鎖17實(shí)驗(yàn)項(xiàng)目五嵌入式Linux串口應(yīng)用編程25實(shí)驗(yàn)項(xiàng)目六管道通信實(shí)驗(yàn)34實(shí)驗(yàn)項(xiàng)目七多線程實(shí)驗(yàn)40實(shí)驗(yàn)項(xiàng)目八使用Qt編寫(xiě)“Hello,World”程序47四、考核方式59五、推薦實(shí)驗(yàn)教材和教學(xué)參考書(shū)60TOC\o"1-2"\h\z\u《嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)》實(shí)驗(yàn)課程指導(dǎo)書(shū)一、課程基本信息課程編碼:課程名稱:嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)英文名稱:Embeddedsystemdesignanddevelopment實(shí)驗(yàn)總學(xué)時(shí):16適用專業(yè):計(jì)算機(jī)科學(xué)與技術(shù)、軟件工程課程類別:專業(yè)選修課先修課程:C語(yǔ)言程序設(shè)計(jì)、嵌入式原理與接口技術(shù)等二、實(shí)驗(yàn)教學(xué)的總體目的和要求加深對(duì)嵌入式系統(tǒng)硬件結(jié)構(gòu),硬件驅(qū)動(dòng)層軟件的開(kāi)發(fā),嵌入式系統(tǒng)的操作系統(tǒng)的理解,掌握嵌入式系統(tǒng)的開(kāi)發(fā)調(diào)試軟件的使用,培養(yǎng)學(xué)生嵌入式系統(tǒng)的應(yīng)用開(kāi)發(fā)的能力。增強(qiáng)學(xué)學(xué)生動(dòng)手能力和創(chuàng)新能力。三、實(shí)驗(yàn)教學(xué)內(nèi)容實(shí)驗(yàn)項(xiàng)目與學(xué)時(shí)一覽表項(xiàng)目序號(hào)實(shí)驗(yàn)項(xiàng)目名稱實(shí)驗(yàn)項(xiàng)目類別實(shí)驗(yàn)要求實(shí)驗(yàn)學(xué)時(shí)1多文件makefile編寫(xiě)實(shí)驗(yàn)必做實(shí)驗(yàn)通過(guò)對(duì)包含多文件的makefile的編寫(xiě),熟練Vi編輯器的使用,熟悉各種形式的makefile,并進(jìn)一步加深對(duì)makefile中用戶自定義變量、自動(dòng)變量以及預(yù)定義變量的理解22主機(jī)開(kāi)發(fā)環(huán)境搭建必做實(shí)驗(yàn)了解虛擬機(jī)與Linux操作系統(tǒng)的基礎(chǔ)知識(shí),熟悉虛擬機(jī)的安裝與設(shè)置,掌握在Vmware上安裝RedHatLinux9.0,掌握在Linux環(huán)境下交叉編譯器的使用,超級(jí)終端的使用以及NFS配置23嵌入式開(kāi)發(fā)環(huán)境搭建必做實(shí)驗(yàn)掌握嵌入式開(kāi)發(fā)流程,通過(guò)移植Linux內(nèi)核,熟悉嵌入式開(kāi)發(fā)環(huán)境的搭建和Linux內(nèi)核的編譯配置。通過(guò)創(chuàng)建文件系統(tǒng),熟練掌握使用busybox創(chuàng)建文件系統(tǒng)和如何創(chuàng)建文件系統(tǒng)映像文件24文件讀寫(xiě)及上鎖必做實(shí)驗(yàn)通過(guò)編寫(xiě)文件讀寫(xiě)及上鎖的程序,進(jìn)一步熟悉Linux中文件I/O相關(guān)的應(yīng)用開(kāi)發(fā),并且熟練掌握open()、read()、write()、fcntl()等函數(shù)的使用25嵌入式Linux串口應(yīng)用編程必做實(shí)驗(yàn)通過(guò)編寫(xiě)多路復(fù)用式串口讀寫(xiě),進(jìn)一步理解多路復(fù)用函數(shù)的用法,同時(shí)更加熟練地掌握Linux設(shè)備文件的讀寫(xiě)方法26管道通信實(shí)驗(yàn)必做實(shí)驗(yàn)通過(guò)編寫(xiě)有名管道多路通信實(shí)驗(yàn),進(jìn)一步掌握管道的創(chuàng)建、讀寫(xiě)等操作,同時(shí)復(fù)習(xí)使用select()函數(shù)實(shí)現(xiàn)管道的通信27多線程實(shí)驗(yàn)必做實(shí)驗(yàn)“生產(chǎn)者消費(fèi)者”問(wèn)題是一個(gè)著名的同時(shí)性編程問(wèn)題的集合。通過(guò)學(xué)習(xí)經(jīng)典的“生產(chǎn)者消費(fèi)者”問(wèn)題的實(shí)驗(yàn),讀者可以進(jìn)一步熟悉Linux中的多線程編程,并且掌握用信號(hào)量處理線程間的同步和互斥問(wèn)題28使用Qt編寫(xiě)“Hello,World”程序必做實(shí)驗(yàn)通過(guò)編寫(xiě)一個(gè)跳動(dòng)的“Hello,World”字符串,進(jìn)一步熟悉嵌入式Qt的開(kāi)發(fā)過(guò)程2合計(jì)16實(shí)驗(yàn)項(xiàng)目一多文件makefile編寫(xiě)實(shí)驗(yàn)學(xué)時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、通過(guò)對(duì)編寫(xiě)及調(diào)試程序簡(jiǎn)單程序,熟練掌握Vi編輯器的使用,2、熟練掌握GCC編譯器GDB調(diào)試器及make工程編譯器的使用。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容1、在Linux字符環(huán)境下,練習(xí)使用基本的文件操作命令(cprmmvlsmkdirclearpwdchmod等命令);2、在同一目錄下用Vi編輯makefile,然后用make驗(yàn)證所編寫(xiě)的makefile是否正確。五、實(shí)驗(yàn)設(shè)備安裝Linux虛擬平臺(tái)的計(jì)算機(jī),ARM教學(xué)實(shí)驗(yàn)平臺(tái)。六、實(shí)驗(yàn)步驟1)編輯hello.c打開(kāi)Linux虛擬機(jī),$cd/home;進(jìn)入/home目錄,$mkdirhello;目錄hello$vihello.c;打開(kāi)vi編輯器,編輯hello.c輸入“i”進(jìn)入編輯狀態(tài)編寫(xiě)一個(gè)1+2+…+10的程序按“ESC”,輸入“:”保存退出2)利用GCC編譯生成可執(zhí)行文件hello$gcchello.c–ohello$./hello;輸出結(jié)果3)利用GDB調(diào)試$gcc–ghello.c–ohello$gdbhello$l;查看源代碼$b3;設(shè)置斷點(diǎn)$c;繼續(xù)運(yùn)行4)編寫(xiě)makefile(在/home/maketest)在/home/maketest目錄下,輸入附錄中5個(gè)文件,$vimakefile;打開(kāi)vi編輯器,編輯makefile$make;生成可執(zhí)行文件main$./main;輸出結(jié)果七、思考題1、什么是makefile?為什么編寫(xiě)makefie?附錄:makefile所需代碼/*main.c*/#include"mytool1.h"#include"mytool2.h"intmain(){mytool1_print("hellomytool1!");mytool2_print("hellomytool2!");return0;}/*mytool1.c*/#include"mytool1.h"#include<stdio.h>voidmytool1_print(char*print_str){printf("Thisismytool1print:%s",print_str);}/*mytool1.h*/#ifndef_MYTOOL_1_H#define_MYTOOL_1_Hvoidmytool1_print(char*print_str);#endif/*mytool2.c*/#include"mytool2.h"#include<stdio.h>voidmytool2_print(char*print_str){printf("Thisismytool2print:%s",print_str);}/*mytool2.h*/#ifndef_MYTOOL_2_H#define_MYTOOL_2_Hvoidmytool2_print(char*print_str);#endif參考makefile:main:main.omytool1.omytool2.ogcc-omainmain.omytool1.omytool2.omain.o:main.cmytool1.hmytool2.hgcc-cmain.cmytool1.o:mytool1.cmytool1.hgcc-cmytool1.cmytool2.o:mytool2.cmytool2.hgcc-cmytool2.cclean:rm-f*.omain實(shí)驗(yàn)項(xiàng)目二主機(jī)開(kāi)發(fā)環(huán)境搭建學(xué)時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、了解虛擬機(jī)與Linux操作系統(tǒng)的基礎(chǔ)知識(shí);2、熟悉虛擬機(jī)的安裝與設(shè)置;3、掌握在Vmware上安裝RedHatLinux9.0;4、掌握在Linux環(huán)境下交叉編譯器的使用,超級(jí)終端的使用以及NFS配置。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容1、開(kāi)發(fā)環(huán)境:Linux+minicom2、Linux:定制或全部安裝。下載安裝交叉編譯器3、設(shè)置windows下超級(jí)終端。4、配置網(wǎng)絡(luò):主要是配置NFS,需關(guān)閉iptables。五、實(shí)驗(yàn)設(shè)備安裝Linux虛擬平臺(tái)的計(jì)算機(jī),ARM教學(xué)實(shí)驗(yàn)平臺(tái)。六、實(shí)驗(yàn)步驟1、安裝交叉編譯器點(diǎn)擊“VM”,“setting”打開(kāi)對(duì)話框,選擇option,sharedfolders右上方,選擇“alwaysenabled,然后點(diǎn)擊“ADD”打開(kāi)對(duì)話框選擇共享目錄,然后點(diǎn)next,finished,完成。打開(kāi)共享目錄$cd/mnt/hgfs;即可看到共享目錄。將共享目錄中的交叉編譯壓縮包拷貝到,Linux目錄下$cparm-linux-gcc-.tgz/home/;(以為例)2、安裝交叉編譯器例:arm-linux-gcc-.tgz1)tarxzfvarm-linux-gcc-.tgz-C/2)vi/etc/profile在profile中添加環(huán)境變量exportPATH=/usr/local/arm//bin:$PATH3)最后,是剛才添加的環(huán)境變量生效source/etc/profile3、編寫(xiě)hello.c程序,并進(jìn)行交叉編譯生成嵌入式Linux的可執(zhí)行文件hello。$arm-linux-gcchello.c–ohello4、打開(kāi)超級(jí)終端5、配置nfs(1)關(guān)閉防火墻$/etc/init.d/iptablesstop(2)啟動(dòng)portmap服務(wù)$serviceportmaprestart(3)啟動(dòng)nfs服務(wù)$servicenfsrestart(4)將宿主機(jī)(PC機(jī))和目標(biāo)機(jī)(實(shí)驗(yàn)箱)配置在同一網(wǎng)段(5)兩邊ping通(6)客戶端掛載NFS服務(wù)器中的08:/home/hello目錄$mount08:/home/hello/mnt6、復(fù)制程序并運(yùn)行$cphello/tmp$cd/tmp$./hello;輸出結(jié)果(注:如果nfs配置不通,則通過(guò)超級(jí)終端發(fā)送)發(fā)送步驟如下:1、將要發(fā)送文件放入Windows系統(tǒng)的共享文件夾2、打開(kāi)超級(jí)終端:3、點(diǎn)擊發(fā)送,打開(kāi)“發(fā)送文件”對(duì)話框4、點(diǎn)擊“瀏覽”找到要發(fā)送的文件,點(diǎn)擊發(fā)送即可。)七、思考題1、什么是交叉編譯?為什么要交叉編譯?實(shí)驗(yàn)項(xiàng)目三嵌入式開(kāi)發(fā)環(huán)境搭建學(xué)時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、了解viviBootloader;2、學(xué)習(xí)燒寫(xiě)NandFlash;3、掌握交叉編譯環(huán)境的使用;4、掌握Linux內(nèi)核的配置和裁剪。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容1、安裝vivi,將其燒寫(xiě)到NandFlash;2、掌握交叉編譯環(huán)境的使用;3、配置Linux內(nèi)核,編譯并下載內(nèi)核到NandFlash;4、燒寫(xiě)根文件系統(tǒng)。五、實(shí)驗(yàn)設(shè)備安裝Linux虛擬平臺(tái)的計(jì)算機(jī),ARM教學(xué)實(shí)驗(yàn)平臺(tái)。六、實(shí)驗(yàn)步驟1、vivi燒寫(xiě)1)通過(guò)簡(jiǎn)易仿真器將并口和實(shí)驗(yàn)箱的JTAG口連接起來(lái),簡(jiǎn)易仿真器選擇JP5口(同JTAG板平行的接口)通過(guò)20芯連接線對(duì)NandFlash進(jìn)行燒寫(xiě);2)將啟動(dòng)模式選擇開(kāi)關(guān)SEB1撥為1100,開(kāi)啟實(shí)驗(yàn)箱。3)“D:\嵌入式文件\LINUX軟件開(kāi)發(fā)光盤(pán)4-4V2.0\tools”目錄下的JTAG文件夾復(fù)制到Windowsxp下的目錄,并根據(jù)文件夾中《簡(jiǎn)易JTAG下載器使用說(shuō)明.doc》文檔的要求安裝該設(shè)備;4)將D:\嵌入式文件\LINUX軟件開(kāi)發(fā)光盤(pán)4-4V2.0\linux-2.4\image目錄下的vivi_2.4拷貝到sjf2410的同一目錄下;5)進(jìn)入WindowsXP命令窗口,進(jìn)入sjf2410所在目錄執(zhí)行以下命令:6)選擇0:SMCProg7)輸入燒寫(xiě)塊為0.8)等待燒寫(xiě)結(jié)束,輸入數(shù)字“2”9)完成后將實(shí)驗(yàn)系統(tǒng)斷電,取下JTAG連接線,將實(shí)驗(yàn)箱的串口1與PC機(jī)串口相連,打開(kāi)超級(jí)終端,重啟試驗(yàn)系統(tǒng),串口會(huì)出現(xiàn)如下提示:“PressReturntostarttheLINUXnow,anyotherkeyforvivi”2、編譯LINUX內(nèi)核1)進(jìn)入內(nèi)核原代碼的目錄”/usr/s3c2410/kernel”(源代碼在D:\嵌入式文件\LINUX軟件開(kāi)發(fā)光盤(pán)4-4V2.0\linux-2.6)后輸入以下命令,$makemenuconfig(xconfig)2)進(jìn)入menuconfig配置界面后,上下移動(dòng)光標(biāo),根據(jù)實(shí)際需要配置自己的選項(xiàng),選擇LoadedanAlernateConfigurationFile,回車后,在彈出的對(duì)話框中輸入配置文件路徑arch/arm/def-config/smdk2410;之后推出編輯界面,選擇保存設(shè)置。1)在內(nèi)核源代碼的目錄下,輸入一下命令開(kāi)始編譯內(nèi)核:#makedep;makezImage2)內(nèi)核編譯生成的二進(jìn)制文件為arch/arm/boot/zImage3、燒寫(xiě)kernel映像至實(shí)驗(yàn)箱的NandFlash。下面燒寫(xiě)zImage至NandFlash上,并在實(shí)驗(yàn)箱上試運(yùn)行。1)確保啟動(dòng)模式開(kāi)關(guān)SWB1的狀態(tài)為1:on-2:on-3:off-4off;2)將實(shí)驗(yàn)箱上的串行口1與pc機(jī)上的串口相連;3)配置pc機(jī)上串口中斷程序,將波特率設(shè)置為115200,無(wú)硬件流控,無(wú)校驗(yàn)位:4)開(kāi)啟實(shí)驗(yàn)箱,上次實(shí)驗(yàn)已經(jīng)燒寫(xiě)了vivi開(kāi)始運(yùn)行,按空格鍵出現(xiàn)ZYETARM_2.4>提示符;5)ZYETARM_2.4>提示符輸入以下命令將內(nèi)核燒寫(xiě)到NandFlash上;ZYETARM_2.4>Loadflashkermelx輸入完畢后,啟動(dòng)終端的Xmodem協(xié)議傳送發(fā)貨光盤(pán)的linux-2.6/image/zImage至實(shí)驗(yàn)箱6)在ZYETARM_2.4>提示符下輸入以下命令將Linux文件系統(tǒng)燒寫(xiě)到NandFlash上;ZYETARM_2.4>Loadflashrootx輸入完畢后,啟動(dòng)終端的Xmodem協(xié)議傳送的linux-2.6/inage/root.cramfs至實(shí)驗(yàn)箱。7)燒寫(xiě)完畢后,復(fù)位實(shí)驗(yàn)箱,出現(xiàn)vivi后直接回車啟動(dòng)Linux,此時(shí)可以通過(guò)串口終端操作一個(gè)我們自己配置的嵌入式linux操作系統(tǒng)。七、思考題1)運(yùn)行Linux,并在#提示環(huán)境下輸入Linux常見(jiàn)命令,指出實(shí)驗(yàn)箱上運(yùn)行的Linux命令和PC機(jī)上運(yùn)行的Linux的異同點(diǎn)。實(shí)驗(yàn)項(xiàng)目四文件讀寫(xiě)及上鎖學(xué)時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、通過(guò)編寫(xiě)文件讀寫(xiě)及上鎖的程序,2、熟悉Linux中文件I/O相關(guān)的應(yīng)用開(kāi)發(fā);3、熟練掌握open()、read()、write()、fcntl()等函數(shù)的使用。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容1、在Linux中FIFO是一種進(jìn)程間的管道通信機(jī)制,Linux支持完整的FIFO通信機(jī)制。通過(guò)使用文件操作,仿真FIFO(先進(jìn)先出)結(jié)構(gòu)及生產(chǎn)者—消費(fèi)者運(yùn)行模型。2、本實(shí)驗(yàn)中需要打開(kāi)兩個(gè)虛擬終端,分別運(yùn)行生產(chǎn)者程序(producer)和消費(fèi)者程序(customer),此時(shí)兩個(gè)進(jìn)程同時(shí)對(duì)同一個(gè)文件進(jìn)行讀寫(xiě)操作。因?yàn)檫@個(gè)文件是臨界資源,所以可以使用文件鎖機(jī)制來(lái)保證兩個(gè)進(jìn)程對(duì)文件的訪問(wèn)都是原子操作。3、先啟動(dòng)生產(chǎn)者進(jìn)程,它負(fù)責(zé)創(chuàng)建仿真FIFO結(jié)構(gòu)的文件(其實(shí)是一個(gè)普通文件)并投入生產(chǎn),就是按照給定的時(shí)間間隔,向FIFO文件寫(xiě)入自動(dòng)生成的字符(在程序中用宏定義選擇使用數(shù)字還是使用英文字符),生產(chǎn)周期及要生產(chǎn)的資源數(shù)通過(guò)參數(shù)傳遞給進(jìn)程(默認(rèn)生產(chǎn)周期為1s,要生產(chǎn)的資源總數(shù)為10個(gè)字符,顯然默認(rèn)生產(chǎn)總時(shí)間為10s)。4、后啟動(dòng)的消費(fèi)者進(jìn)程按照給定的數(shù)目進(jìn)行消費(fèi),首先從文件中讀取相應(yīng)數(shù)目的字符并在屏幕上顯示,然后從文件中刪除剛才消費(fèi)過(guò)的數(shù)據(jù)。為了仿真FIFO結(jié)構(gòu),此時(shí)需要使用兩次復(fù)制來(lái)實(shí)現(xiàn)文件內(nèi)容的偏移。每次消費(fèi)的資源數(shù)通過(guò)參數(shù)傳遞給進(jìn)程,默認(rèn)值為10個(gè)字符。五、實(shí)驗(yàn)設(shè)備安裝Linux虛擬平臺(tái)的計(jì)算機(jī),ARM教學(xué)實(shí)驗(yàn)平臺(tái)。六、實(shí)驗(yàn)步驟1、編寫(xiě)代碼。(lock_set.c見(jiàn)附件)本實(shí)驗(yàn)中的生產(chǎn)者程序的源代碼如下所示,lock_set()函數(shù)見(jiàn)附錄/*producer.c*/#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#include"lock_set.c"http://lock_set.c見(jiàn)附件#defineMAXLEN10/*緩沖區(qū)大小最大值*/#defineALPHABET1/*表示使用英文字符*/#defineALPHABET_START'a'/*頭一個(gè)字符,可以用'A'*/#defineCOUNT_OF_ALPHABET26/*字母字符的個(gè)數(shù)*/#defineDIGIT2/*表示使用數(shù)字字符*/#defineDIGIT_START'0'/*頭一個(gè)字符*/#defineCOUNT_OF_DIGIT10/*數(shù)字字符的個(gè)數(shù)*/#defineSIGN_TYPEALPHABET/*本實(shí)例選用英文字符*/constchar*fifo_file="./myfifo";/*仿真FIFO文件名*/charbuff[MAXLEN];/*緩沖區(qū)*//*功能:生產(chǎn)一個(gè)字符并寫(xiě)入到仿真FIFO文件中*/intproduct(void){intfd;unsignedintsign_type,sign_start,sign_count,size;staticunsignedintcounter=0;/*打開(kāi)仿真FIFO文件*/if((fd=open(fifo_file,O_CREAT|O_RDWR|O_APPEND,0644))<0){printf("Openfifofileerror\n");exit(1);}sign_type=SIGN_TYPE;switch(sign_type){caseALPHABET:/*英文字符*/{sign_start=ALPHABET_START;sign_count=COUNT_OF_ALPHABET;}break;caseDIGIT:/*數(shù)字字符*/{sign_start=DIGIT_START;sign_count=COUNT_OF_DIGIT;}break;default:{return-1;}}/*endofswitch*/sprintf(buff,"%c",(sign_start+counter));counter=(counter+1)%sign_count;lock_set(fd,F_WRLCK);/*上寫(xiě)鎖*/if((size=write(fd,buff,strlen(buff)))<0){printf("Producer:writeerror\n");return-1;}lock_set(fd,F_UNLCK);/*解鎖*/close(fd);return0;}intmain(intargc,char*argv[]){inttime_step=1;/*生產(chǎn)周期*/inttime_life=10;/*需要生產(chǎn)的資源總數(shù)*/if(argc>1){/*第一個(gè)參數(shù)表示生產(chǎn)周期*/sscanf(argv[1],"%d",&time_step);}if(argc>2){/*第二個(gè)參數(shù)表示需要生產(chǎn)的資源數(shù)*/sscanf(argv[2],"%d",&time_life);}while(time_life--){if(product()<0){break;}sleep(time_step);}exit(EXIT_SUCCESS);

}本實(shí)驗(yàn)中的消費(fèi)者程序的源代碼如下所示:

/*customer.c*/#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<fcntl.h>#include"lock_set.c"http://lock_set.c見(jiàn)附件#defineMAX_FILE_SIZE100*1024*1024/*100M*/constchar*fifo_file="./myfifo";/*仿真FIFO文件名*/constchar*tmp_file="./tmp";/*臨時(shí)文件名*//*資源消費(fèi)函數(shù)*/intcustoming(constchar*myfifo,intneed){intfd;charbuff;intcounter=0;if((fd=open(myfifo,O_RDONLY))<0){printf("Functioncustomingerror\n");return-1;}printf("Enjoy:");lseek(fd,SEEK_SET,0);while(counter<need){while((read(fd,&buff,1)==1)&&(counter<need)){fputc(buff,stdout);/*消費(fèi)就是在屏幕上簡(jiǎn)單的顯示*/counter++;}}fputs("\n",stdout);close(fd);return0;}/*功能:從sour_file文件的offset偏移處開(kāi)始,將count字節(jié)數(shù)據(jù)復(fù)制到dest_file文件*/intmyfilecopy(constchar*sour_file,constchar*dest_file,intoffset,intcount,intcopy_mode){intin_file,out_file;intcounter=0;charbuff_unit;if((in_file=open(sour_file,O_RDONLY|O_NONBLOCK))<0){printf("Functionmyfilecopyerrorinsourcefile\n");

return-1;}if((out_file=open(dest_file,O_CREAT|O_RDWR|O_TRUNC|O_NONBLOCK,0644))<0){printf("Functionmyfilecopyerrorindestinationfile:");return-1;}

lseek(in_file,offset,SEEK_SET);while((read(in_file,&buff_unit,1)==1)&&(counter<count)){write(out_file,&buff_unit,1);counter++;}close(in_file);close(out_file);return0;}/*功能:實(shí)現(xiàn)FIFO消費(fèi)者*/intcustom(intneed){intfd;/*對(duì)資源進(jìn)行消費(fèi),need表示該消費(fèi)的資源數(shù)目*/

customing(fifo_file,need);if((fd=open(fifo_file,O_RDWR))<0){printf("Functionmyfilecopyerrorinsource_file:");return-1;}/*為了模擬FIFO結(jié)構(gòu),對(duì)整個(gè)文件內(nèi)容進(jìn)行平行移動(dòng)*/lock_set(fd,F_WRLCK);myfilecopy(fifo_file,tmp_file,need,MAX_FILE_SIZE,0);myfilecopy(tmp_file,fifo_file,0,MAX_FILE_SIZE,0);lock_set(fd,F_UNLCK);unlink(tmp_file);close(fd);return0;}intmain(intargc,char*argv[]){intcustomer_capacity=10;if(argc>1)/*第一個(gè)參數(shù)指定需要消費(fèi)的資源數(shù)目,默認(rèn)值為10*/{sscanf(argv[1],"%d",&customer_capacity);}if(customer_capacity>0){custom(customer_capacity);}exit(EXIT_SUCCESS);}2、先在宿主機(jī)上編譯該程序,如下所示:$makeclean;make3、在確保沒(méi)有編譯錯(cuò)誤后,交叉編譯該程序,此時(shí)需要修改Makefile中的變量。CC=arm-linux-gcc/*修改Makefile中的編譯器*/$makeclean;make4、將生成的可執(zhí)行程序下載到目標(biāo)板上運(yùn)行。七、實(shí)驗(yàn)報(bào)告1、列出調(diào)試通過(guò)程序的清單,分析運(yùn)行結(jié)果。2、給出必要的程序設(shè)計(jì)思路和方法(或列出流程圖)。3、總結(jié)上機(jī)調(diào)試過(guò)程中所遇到的問(wèn)題和解決方法及感想。八、思考題1、fcntl函數(shù),除了加鎖、解鎖之外含有什么功能,請(qǐng)?jiān)敿?xì)描述。附錄:/*lock_set.c*/intlock_set(intfd,inttype){ structflockold_lock,lock; lock.l_whence=SEEK_SET; lock.l_start=0; lock.l_len=0; lock.l_type=type; lock.l_pid=-1; /*判斷文件是否可以上鎖*/ fcntl(fd,F_GETLK,&lock); if(lock.l_type!=F_UNLCK) { /*判斷文件不能上鎖的原因*/ if(lock.l_type==F_RDLCK)/*該文件已有讀取鎖*/ { printf("Readlockalreadysetby%d\n",lock.l_pid); } elseif(lock.l_type==F_WRLCK)/*該文件已有寫(xiě)入鎖*/ { printf("Writelockalreadysetby%d\n",lock.l_pid); } } /*l_type可能已被F_GETLK修改過(guò)*/ lock.l_type=type; /*根據(jù)不同的type值進(jìn)行阻塞式上鎖或解鎖*/ if((fcntl(fd,F_SETLKW,&lock))<0) { printf("Lockfailed:type=%d\n",lock.l_type); return1; } switch(lock.l_type) { caseF_RDLCK: { printf("Readlocksetby%d\n",getpid()); } break; caseF_WRLCK: { printf("Writelocksetby%d\n",getpid()); } break; caseF_UNLCK: { printf("Releaselockby%d\n",getpid()); return1; } break; default: break; }/*endofswitch*/ return0;}實(shí)驗(yàn)項(xiàng)目五嵌入式Linux串口應(yīng)用編程學(xué)時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、通過(guò)編寫(xiě)多路復(fù)用式串口讀寫(xiě),進(jìn)一步理解多路復(fù)用函數(shù)的用法;2、更加熟練地掌握Linux設(shè)備文件的讀寫(xiě)方法。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容1、實(shí)現(xiàn)兩臺(tái)機(jī)器(宿主機(jī)和目標(biāo)板)之間的串口通信,而且每臺(tái)機(jī)器均可以發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。除了串口設(shè)備名稱不同(宿主機(jī)上使用串口1:/dev/ttyS0,而在目標(biāo)板上使用串口2:/dev/ttyS1),兩臺(tái)機(jī)器上的程序基本相同。2、程序打開(kāi)串口設(shè)備文件并進(jìn)行相關(guān)配置,調(diào)用select()函數(shù),使它等待從標(biāo)準(zhǔn)輸入(終端)文件中的輸入數(shù)據(jù)及從串口設(shè)備的輸入數(shù)據(jù)。如果有標(biāo)準(zhǔn)輸入文件上的數(shù)據(jù),則寫(xiě)入到串口,使對(duì)方讀取。如果有串口設(shè)備上的輸入數(shù)據(jù),則將數(shù)據(jù)寫(xiě)入到普通文件中。五、實(shí)驗(yàn)設(shè)備安裝Linux虛擬平臺(tái)的計(jì)算機(jī),ARM教學(xué)實(shí)驗(yàn)平臺(tái)。六、實(shí)驗(yàn)步驟1、編寫(xiě)代碼(open_port()和set_com_config()函數(shù)請(qǐng)參照附錄)/*com_host.c*/#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>#include<errno.h>#include"uart_api.h"

intmain(void){intfds[SEL_FILE_NUM],recv_fd,maxfd;charbuff[BUFFER_SIZE];fd_setinset,tmp_inset;structtimevaltv;unsignedloop=1;intres,real_read,i;/*將從串口讀取的數(shù)據(jù)寫(xiě)入到這個(gè)文件中*/if((recv_fd=open(RECV_FILE_NAME,O_CREAT|O_WRONLY,0644))<0){perror("open");return1;}fds[0]=STDIN_FILENO;/*標(biāo)準(zhǔn)輸入*/if((fds[1]=open_port(HOST_COM_PORT))<0)/*打開(kāi)串口*/{perror("open_port");return1;}if(set_com_config(fds[1],115200,8,'N',1)<0)/*配置串口*/{perror("set_com_config");return1;}FD_ZERO(&inset);FD_SET(fds[0],&inset);FD_SET(fds[1],&inset);maxfd=(fds[0]>fds[1])?fds[0]:fds[1];tv.tv_sec=TIME_DELAY;tv.tv_usec=0;printf("Inputsomewords(enter'quit'toexit):\n");while(loop&&(FD_ISSET(fds[0],&inset)||FD_ISSET(fds[1],&inset))){tmp_inset=inset;res=select(maxfd+1,&tmp_inset,NULL,NULL,&tv);switch(res){case-1:/*錯(cuò)誤*/{perror("select");loop=0;}break;case0:/*超時(shí)*/{perror("selecttimeout");loop=0;

}break;default:{for(i=0;i<SEL_FILE_NUM;i++){if(FD_ISSET(fds[i],&tmp_inset)){memset(buff,0,BUFFER_SIZE);/*讀取標(biāo)準(zhǔn)輸入或者串口設(shè)備文件*/real_read=read(fds[i],buff,BUFFER_SIZE);if((real_read<0)&&(errno!=EAGAIN)){loop=0;}elseif(!real_read){close(fds[i]);FD_CLR(fds[i],&inset);}Else{buff[real_read]='\0';if(i==0){/*將從終端讀取的數(shù)據(jù)寫(xiě)入到串口*/write(fds[1],buff,strlen(buff));printf("Inputsomewords(enter'quit'toexit):\n");}elseif(i==1){/*將從串口讀取的數(shù)據(jù)寫(xiě)入到普通文件中*/write(recv_fd,buff,real_read);}if(strncmp(buff,"quit",4)==0){/*如果讀取為quit則退出*/loop=0;}}}/*endofifFD_ISSET*/}/*fori*/}}/*endofswitch*/}/*endofwhile*/close(recv_fd);return0;}2、接下來(lái),將目標(biāo)板的串口程序交叉編譯,再將宿主機(jī)的串口程序在PC上編譯。3、連接PC的串口1和開(kāi)發(fā)板的串口2,然后將目標(biāo)板串口程序下載到開(kāi)發(fā)板上,分別在兩臺(tái)機(jī)器上運(yùn)行串口程序。4、從串口讀取的數(shù)據(jù)(即目標(biāo)板中發(fā)送過(guò)來(lái)的數(shù)據(jù))寫(xiě)入到同目錄下的recv.dat文件中,查看recv.dat文件中內(nèi)容。$catrecv.dat5、與宿主機(jī)上的代碼相同,從串口讀取的數(shù)據(jù)(即目標(biāo)板中發(fā)送過(guò)來(lái)的數(shù)據(jù))寫(xiě)入到同目錄下的recv.dat文件中,查看recv.dat文件中內(nèi)容。$catrecv.dat七、實(shí)驗(yàn)報(bào)告1、列出調(diào)試通過(guò)程序的清單,分析運(yùn)行結(jié)果。2、給出必要的程序設(shè)計(jì)思路和方法(或列出流程圖)。3、總結(jié)上機(jī)調(diào)試過(guò)程中所遇到的問(wèn)題和解決方法及感想。八、思考題1、請(qǐng)讀者用poll()函數(shù)實(shí)現(xiàn)具有以上功能的代碼。附錄:/*uart_api.c*/#include<stdlib.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<termios.h>#include<errno.h>#include"uart_api.h"/*打開(kāi)串口函數(shù)*/intopen_port(intcom_port){ intfd;#if(COM_TYPE==GNR_COM) char*dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};#else char*dev[]={"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2"};#endif if((com_port<0)||(com_port>MAX_COM_NUM)) { return-1; } fd=open(dev[com_port-1],O_RDWR|O_NOCTTY|O_NDELAY); if(fd<0) { perror("openserialport"); return(-1); } /*恢復(fù)串口為阻塞狀態(tài)*/ if(fcntl(fd,F_SETFL,0)<0) { perror("fcntlF_SETFL\n"); } /*測(cè)試是否為終端設(shè)備*/ if(isatty(STDIN_FILENO)==0) { perror("standardinputisnotaterminaldevice"); } returnfd;}intset_com_config(intfd,intbaud_rate,intdata_bits,charparity,intstop_bits){ structtermiosnew_cfg,old_cfg; intspeed; /*保存測(cè)試現(xiàn)有串口參數(shù)設(shè)置,在這里如果串口號(hào)等出錯(cuò),會(huì)有相關(guān)的出錯(cuò)信息*/ if(tcgetattr(fd,&old_cfg)!=0) { perror("tcgetattr"); return-1; } /*設(shè)置字符大小*/ new_cfg=old_cfg; cfmakeraw(&new_cfg); new_cfg.c_cflag&=~CSIZE; /*設(shè)置波特率*/ switch(baud_rate) { case2400: { speed=B2400; } break; case4800: { speed=B4800; } break; case9600: { speed=B9600; } break; case19200: { speed=B19200; } break; case38400: { speed=B38400; } break; default: case115200: { speed=B115200; } break; } cfsetispeed(&new_cfg,speed); cfsetospeed(&new_cfg,speed); /*設(shè)置停止位*/ switch(data_bits) { case7: { new_cfg.c_cflag|=CS7; } break; default: case8: { new_cfg.c_cflag|=CS8; } break; } /*設(shè)置奇偶校驗(yàn)位*/ switch(parity) { default: case'n': case'N': { new_cfg.c_cflag&=~PARENB; new_cfg.c_iflag&=~INPCK; } break;case'o': case'O':{new_cfg.c_cflag|=(PARODD|PARENB);new_cfg.c_iflag|=INPCK;}break; case'e':case'E': { new_cfg.c_cflag|=PARENB; new_cfg.c_cflag&=~PARODD; new_cfg.c_iflag|=INPCK;} break;case's':/*asnoparity*/ case'S':{ new_cfg.c_cflag&=~PARENB; new_cfg.c_cflag&=~CSTOPB; } break; } /*設(shè)置停止位*/ switch(stop_bits) { default: case1: { new_cfg.c_cflag&=~CSTOPB; } break; case2: { new_cfg.c_cflag|=CSTOPB; } } /*設(shè)置等待時(shí)間和最小接收字符*/ new_cfg.c_cc[VTIME]=0; new_cfg.c_cc[VMIN]=1; /*處理未接收字符*/ tcflush(fd,TCIFLUSH); /*激活新配置*/ if((tcsetattr(fd,TCSANOW,&new_cfg))!=0) { perror("tcsetattr"); return-1; } return0;}/*uart_api.h*/#ifndef UART_API_H#define UART_API_H#define GNR_COM 0#define USB_COM 1#define COM_TYPE GNR_COM#define MAX_COM_NUM 3#define HOST_COM_PORT 1#define TARGET_COM_PORT 2#define BUFFER_SIZE 1024intopen_port(intcom_port);intset_com_config(intfd,intbaud_rate,intdata_bits,charparity,intstop_bits);#endif/*UART_API_H*/實(shí)驗(yàn)項(xiàng)目六管道通信實(shí)驗(yàn)學(xué)時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、通過(guò)編寫(xiě)有名管道多路通信實(shí)驗(yàn);2、掌握管道的創(chuàng)建、讀寫(xiě)等操作;3、復(fù)習(xí)使用select()函數(shù)實(shí)現(xiàn)管道的通信。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容1、這里采用管道函數(shù)創(chuàng)建有名管道(并不是在控制臺(tái)下輸入命令),而且使用select()函數(shù)替代poll()函數(shù)實(shí)現(xiàn)多路復(fù)用(使用select()函數(shù)是出于以演示為目的)。2、(附加內(nèi)容,參考代碼見(jiàn)附件)編制一段程序,實(shí)現(xiàn)進(jìn)程的管道通信。使用pipe()建立一條管道線。兩個(gè)子進(jìn)程p1和p2分別向管道各寫(xiě)一句話:

Child1issendingmessage!

Child2issendingmessage!而父進(jìn)程則從管道中讀出來(lái)自于兩個(gè)子進(jìn)程的信息,顯示在屏幕上。3、(附加內(nèi)容)在父進(jìn)程中用pipe()建立一條管道線,往管道里寫(xiě)一句話,兩個(gè)子進(jìn)程接收這句話。五、實(shí)驗(yàn)設(shè)備安裝Linux虛擬平臺(tái)的計(jì)算機(jī),ARM教學(xué)實(shí)驗(yàn)平臺(tái)。六、實(shí)驗(yàn)步驟1、編寫(xiě)代碼:/*pipe_select.c*/#include<fcntl.h>#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<time.h>#include<errno.h>#defineFIFO1"in1"#defineFIFO2"in2"#defineMAX_BUFFER_SIZE1024/*緩沖區(qū)大小*/#defineIN_FILES3/*多路復(fù)用輸入文件數(shù)目*/#defineTIME_DELAY60/*超時(shí)值秒數(shù)*/#defineMAX(a,b)((a>b)?(a):(b))intmain(void){intfds[IN_FILES];charbuf[MAX_BUFFER_SIZE];inti,res,real_read,maxfd;structtimevaltv;fd_setinset,tmp_inset;fds[0]=0;/*創(chuàng)建兩個(gè)有名管道*/if(access(FIFO1,F_OK)==-1){if((mkfifo(FIFO1,0666)<0)&&(errno!=EEXIST)){printf("Cannotcreatefifofile\n");exit(1);}}if(access(FIFO2,F_OK)==-1){if((mkfifo(FIFO2,0666)<0)&&(errno!=EEXIST)){printf("Cannotcreatefifofile\n");exit(1);}}/*以只讀非阻塞方式打開(kāi)兩個(gè)管道文件*/if((fds[1]=open(FIFO1,O_RDONLY|O_NONBLOCK))<0){printf("Openin1error\n");return1;}if((fds[2]=open(FIFO2,O_RDONLY|O_NONBLOCK))<0){printf("Openin2error\n");return1;}/*取出兩個(gè)文件描述符中的較大者*/maxfd=MAX(MAX(fds[0],fds[1]),fds[2]);/*初始化讀集inset,并在讀文件描述符集中加入相應(yīng)的描述集*/FD_ZERO(&inset);for(i=0;i<IN_FILES;i++){FD_SET(fds[i],&inset);}FD_SET(0,&inset);tv.tv_sec=TIME_DELAY;tv.tv_usec=0;/*循環(huán)測(cè)試該文件描述符是否準(zhǔn)備就緒,并調(diào)用select()函數(shù)對(duì)相關(guān)文件描述符做相應(yīng)操作*/while(FD_ISSET(fds[0],&inset)||FD_ISSET(fds[1],&inset)||FD_ISSET(fds[2],&inset)){/*文件描述符集的備份,以免每次都進(jìn)行初始化*/tmp_inset=inset;res=select(maxfd+1,&tmp_inset,NULL,NULL,&tv);switch(res){case-1:{printf("Selecterror\n");return1;}break;case0:/*Timeout*/{printf("Timeout\n");return1;}break;default:{for(i=0;i<IN_FILES;i++){if(FD_ISSET(fds[i],&tmp_inset)){memset(buf,0,MAX_BUFFER_SIZE);real_read=read(fds[i],buf,MAX_BUFFER_SIZE);if(real_read<0){if(errno!=EAGAIN){return1;}}elseif(!real_read){close(fds[i]);FD_CLR(fds[i],&inset);}Else{if(i==0){/*主程序終端控制*/if((buf[0]=='q')||(buf[0]=='Q')){return1;}}Else{/*顯示管道輸入字符串*/buf[real_read]='\0';printf("%s",buf);}}}/*endofif*/}/*endoffor*/}break;}/*endofswitch*/}/*endofwhile*/return0;}2、編譯并運(yùn)行該程序。3、另外打開(kāi)兩個(gè)虛擬終端,分別輸入“cat>in1”和“cat>in2七、實(shí)驗(yàn)報(bào)告1、列出調(diào)試通過(guò)程序的清單,分析運(yùn)行結(jié)果。2、給出必要的程序設(shè)計(jì)思路和方法(或列出流程圖)。3、總結(jié)上機(jī)調(diào)試過(guò)程中所遇到的問(wèn)題和解決方法及感想。八、思考題1、請(qǐng)讀者用poll()函數(shù)實(shí)現(xiàn)具有以上功能的代碼。附件:參考代碼#include<unistd.h>#include<signal.h>#include<stdlib.h>#include<wait.h>#include<stdio.h>intpid1,pid2;main(){

intfd[2];

charOutPipe[100],InPipe[100];

pipe(fd);while((pid1=fork())==-1);if(pid1==0){

lockf(fd[1],1,0);

sprintf(OutPipe,”child1processissendingmessage!”);

write(fd[1],OutPipe,50);

sleep(5);

lockf(fd[1],0,0);

exit(0);}

else

{while((pid2=fork())==-1);if(pid2==0){

lockf(fd[1],1,0);

sprintf(OutPipe,”child2processissendingmessage!”);/*把串放入數(shù)組outpipe中*/

write(fd[1],OutPipe,50);/*向管道寫(xiě)長(zhǎng)為50字節(jié)的串*/

sleep(5);/*自我阻塞5秒*/

lockf(fd[1],0,0);

exit(0);}else{

wait(0);/*同步*/

read(fd[0],InPipe,50);/*從管道中讀長(zhǎng)為50字節(jié)的串*/

printf(“%s\n”,InPipe);

wait(0);

read(fd[0],InPipe,50);

printf(“%s\n”,InPipe);

exit(0);}}}實(shí)驗(yàn)項(xiàng)目七多線程實(shí)驗(yàn)學(xué)時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、通過(guò)學(xué)習(xí)經(jīng)典的“生產(chǎn)者消費(fèi)者”問(wèn)題的實(shí)驗(yàn),熟悉Linux中的多線程編程;2、掌握用信號(hào)量處理線程間的同步和互斥問(wèn)題。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容“生產(chǎn)者—消費(fèi)者”問(wèn)題描述如下。有一個(gè)有限緩沖區(qū)和兩個(gè)線程:生產(chǎn)者和消費(fèi)者。他們分別不停地把產(chǎn)品放入緩沖區(qū)和從緩沖區(qū)中拿走產(chǎn)品。一個(gè)生產(chǎn)者在緩沖區(qū)滿的時(shí)候必須等待,一個(gè)消費(fèi)者在緩沖區(qū)空的時(shí)候也必須等待。另外,因?yàn)榫彌_區(qū)是臨界資源,所以生產(chǎn)者和消費(fèi)者之間必須互斥執(zhí)行。它們之間的關(guān)系如圖9.4所示。圖9.4生產(chǎn)者消費(fèi)者問(wèn)題描述這里要求使用有名管道來(lái)模擬有限緩沖區(qū),并且使用信號(hào)量來(lái)解決“生產(chǎn)者—消費(fèi)者”問(wèn)題中的同步和互斥問(wèn)題。1、用有名管道來(lái)模擬有限緩沖區(qū),用信號(hào)量來(lái)解決生產(chǎn)者消費(fèi)者問(wèn)題之間的同步和互斥問(wèn)題。解決方案:(1)信號(hào)量的考慮

這里使用3個(gè)信號(hào)量,其中兩個(gè)信號(hào)量avail和full分別用于解決生產(chǎn)者和消費(fèi)者線程之間的同步問(wèn)題,mutex是用于這兩個(gè)線程時(shí)間的互斥問(wèn)題。其中avail初始化為N(有界緩沖區(qū)的空單元數(shù)),mutex初始化為1,full初始化為0.(2)流程圖如下。建立有名管道建立有名管道開(kāi)始打開(kāi)有名管道初始化三個(gè)信號(hào)量創(chuàng)建消費(fèi)者和生產(chǎn)著兩個(gè)線程消費(fèi)者線程生產(chǎn)者線程P操作(avail)_P操作(mudex)寫(xiě)管道V操作(full)V操作(mudex)P操作(full)_P操作(mudex)讀管道V操作(avail)V操作(mudex)結(jié)束對(duì)流程圖的分析:這里假設(shè)初始化avail為5,也就是空緩存單元的起始個(gè)數(shù)是5。主函數(shù)創(chuàng)建兩個(gè)線程后,兩個(gè)線程并行執(zhí)行。

剛開(kāi)始的時(shí)候,在生產(chǎn)者線程函數(shù)里,由于要對(duì)緩沖區(qū)寫(xiě)入數(shù)據(jù)(放入產(chǎn)品),因此通過(guò)P操作使avail減1,也使mutex減1,此時(shí)mutex為0。在生產(chǎn)者運(yùn)行的同時(shí),消費(fèi)者也在運(yùn)行,不過(guò)由于full的初始值設(shè)為0,消費(fèi)者對(duì)full的P操作被阻塞,此時(shí)消費(fèi)者線程是被阻塞的。

生產(chǎn)者將數(shù)據(jù)寫(xiě)入緩沖區(qū)后,對(duì)full進(jìn)行V操作,full置為1,此時(shí)消費(fèi)者對(duì)full的P操作可以執(zhí)行了,但對(duì)mutex進(jìn)行P操作時(shí)又被阻塞,因?yàn)樯a(chǎn)者還對(duì)mutex進(jìn)行V操作(mutex保證了當(dāng)前只有一個(gè)線程對(duì)緩沖區(qū)進(jìn)行操作)。在生產(chǎn)者完成對(duì)mutex的V操作后,消費(fèi)者才能繼續(xù)執(zhí)行,P操作mutex,讀取緩沖區(qū)中的數(shù)據(jù)(此時(shí)生產(chǎn)者就被mutex阻塞了),消費(fèi)者讀取數(shù)據(jù)后,V操作avail,使空緩沖區(qū)個(gè)數(shù)加1,V操作mutex,解除生產(chǎn)者的阻塞狀態(tài)。如此循環(huán)。五、實(shí)驗(yàn)設(shè)備安裝Linux虛擬平臺(tái)的計(jì)算機(jī),ARM教學(xué)實(shí)驗(yàn)平臺(tái)。六、實(shí)驗(yàn)步驟1、編寫(xiě)代碼:/*producer-customer.c*/#include<time.h>#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<fcntl.h>#include<pthread.h>#include<errno.h>#include<semaphore.h>#include<sys/ipc.h>#include<string.h>

#defineBUFFER_SIZE

5//availinitalvalue

#defineTIME_SIZE30intpipe_fd[2];inti=0,j=0;char*t;time_ttimer;sem_tmutex,full,avail;void*producer(void*arg){

intreal_write;

while(i<10)

{sem_wait(&avail);

sem_wait(&mutex);

/*getsecondssince1970*/

timer=time(0);

/*calculatecurrenttime(structtmtype)*/

structtm*currtime=localtime(&timer);

/*changetimetype:structtmtoASCIIcode*/

t=asctime(currtime);

printf("\nProducer:ID=%d\n",i);

if((real_write=write(pipe_fd[1],t,TIME_SIZE))==-1)

{

if(errno==EAGAIN)

{

printf("TheFIFOhasnotbeenreadyet.Pleasetrylater\n");

}

}

else

{

printf("WritetimetotheFIFO\n");

}

sem_post(&full);

sem_post(&mutex);

i++;sleep(3);

}

pthread_exit(NULL);}void*customer(void*arg){

charc[TIME_SIZE];

intreal_read;

while(j<10)

{sem_wait(&full);

sem_wait(&mutex);

memset(c,0,sizeof(c));

printf("\nCustomer:ID=%d\n",j);

if((real_read=read(pipe_fd[0],c,sizeof(c)))==-1)

{

if(errno==EAGAIN)

{

printf("Nodatayet\n");

}

}

printf("Readcurrenttime%sfromFIFO\n",c);

sem_post(&avail);

sem_post(&mutex);

j++;

}

pthread_exit(NULL);}intmain(){

pthread_tthrd_prd_id,thrd_cst_id;

pthread_tmon_th_id;

intret;

if(pipe(pipe_fd)<0)

{

printf("pipecreateerror\n");

exit(1);

}

ret=sem_init(&mutex,0,1);

ret+=sem_init(&avail,0,BUFFER_SIZE);

ret+=sem_init(&full,0,0);

if(ret!=0)

{

printf("Anysemaphoreinitializationfailed\n");

returnret;

}

ret=pthread_create(&thrd_prd_id,NULL,producer,NULL);

if(ret!=0)

{

printf("Createproducerthreaderror\n");

returnret;

}

ret=pthread_create(&thrd_cst_id,NULL,customer,NULL);

if(ret!=0)

{

printf("Createcustomerthreaderror\n");

returnret;

}pthread_join(thrd_prd_id,NULL);

pthread_join(thrd_cst_id,NULL);

close(pipe_fd[0]);

close(pipe_fd[1]);

return0;}2、在終端編譯程序#gcc-lpthreadproducer-customer.c–oproducer-customer(注意:在對(duì)線程程序編譯時(shí),需要使用鏈接庫(kù)“-lpthread”。)3、運(yùn)行并分析結(jié)果。七、實(shí)驗(yàn)報(bào)告1、列出調(diào)試通過(guò)程序的清單,分析運(yùn)行結(jié)果。2、給出必要的程序設(shè)計(jì)思路和方法(或列出流程圖)。3、總結(jié)上機(jī)調(diào)試過(guò)程中所遇到的問(wèn)題和解決方法及感想。八、思考題實(shí)驗(yàn)項(xiàng)目八使用Qt編寫(xiě)“Hello,World”程序?qū)W時(shí):2實(shí)驗(yàn)要求(選做/必做):必做實(shí)驗(yàn)地點(diǎn):實(shí)驗(yàn)室6B105一、實(shí)驗(yàn)?zāi)康?、通過(guò)編寫(xiě)一個(gè)跳動(dòng)的“Hello,World”字符串,進(jìn)一步熟悉嵌入式Qt的開(kāi)發(fā)過(guò)程。二、實(shí)驗(yàn)條件:實(shí)驗(yàn)中心擁有針對(duì)該課程的實(shí)驗(yàn)室一間(6B105),可同時(shí)容納10個(gè)組進(jìn)行實(shí)驗(yàn)。安裝Linux虛擬平臺(tái)的電腦10臺(tái),ARM9實(shí)驗(yàn)開(kāi)發(fā)平臺(tái)10套。三、實(shí)驗(yàn)性質(zhì):設(shè)計(jì)性四、實(shí)驗(yàn)內(nèi)容1、生成一個(gè)工程文件(.pro文件)。2、新建一個(gè)窗體。3、生成Hello窗體類的頭文件和實(shí)現(xiàn)文件。4、編寫(xiě)主函數(shù)main()。5、編輯工程文件文件。6、

溫馨提示

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

評(píng)論

0/150

提交評(píng)論