嵌入式Linux實時操作系統及應用編程代碼與答案_第1頁
嵌入式Linux實時操作系統及應用編程代碼與答案_第2頁
嵌入式Linux實時操作系統及應用編程代碼與答案_第3頁
嵌入式Linux實時操作系統及應用編程代碼與答案_第4頁
嵌入式Linux實時操作系統及應用編程代碼與答案_第5頁
已閱讀5頁,還剩53頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

附錄A習題參考答案

嵌入式Linux實時操作系統及應用編程

第1章

1.嵌入式系統是指操作系統和功能軟件集成于計算機硬件系統之中。簡單的說就是系統

的應用軟件與系統的硬件一體化,類似與BIOS的工作方式。具有軟件代碼小,高度自動化,響

應速度快等特點。特別適合于要求實時的和多任務的體系。根據IEEE(國際電氣和電子」.程

師協會)的定義:嵌入式系統是“用于控制、監視或者輔助操作機器和設備的裝置”(原文為

devicesusedtocontrol,monitor,orassisttheoperationofequipment,machineryorplants)o

簡單地講就是嵌入到對象體中的專用計算機系統。

嵌入式系統一般有3個主要的組成部分:硬件、實時操作系統以及應用軟件。

?硬件:包括處理器、存儲器(ROM、RAM)、輸入輸出設備、其他部分輔助系統等。

?實時操作系統(Real-TimeOperatingSystem,RTOS):用于管理應用軟件,并提供一種機制,

使得處理器分時地執行各個任務并完成一定的時限要求。

?應用軟件:實現具體業務邏輯功能。

2.嵌入式系統的三要素是嵌入、專用、計算機;其中嵌入性指的是嵌入到對象體系中,有對

象環境要求;專用性是指軟、硬件按對象要求裁減;計算機指實現對象的智能化功能。廣義

地說一個嵌入式系統就是一個具有特定功能或用途的計算機軟硬件集合體,即以應用為中心、

以計算機技術為基礎、軟件硬件可裁剪、適應應用系統對功能、可靠性、成本、體積、功耗

嚴格要求的專用計算機系統。

3.嵌入式實時操作系統(Real-TimeOperatingSystem,RTOS)是指操作系統本身要能在一

個固定時限內對程序調用(或外部事件)做出正確的反應,亦即對時序與穩定性的要求十分嚴

格。

Fl前國際較為知名的有:VxWorksNeutrinoRTOS>NucleusPkis^OS/9、VRTX、LynuxOS,

RTLinux、BlueCatRT等。

4.嵌入式系統一般由硬件層、中間層、軟件層和功能層組成。其作用分別如下:

(1)硬件層:由嵌入式微處理器、外圍電路和外設組成。外圍電路有:電源電路、復位

電路、調試接口和存儲器電路,就構成一個嵌入式核心控制模塊。

操作系統和應用程序都可以固化在ROM或者Flash中。為方便使用,有的模塊在此基礎

上增加了LCD.鍵盤、USB接口,以及其他一些功能的擴展電路。

(2)中間層:硬件層與軟件層之間為中間層,也稱為BSP(BoardSupportPackage,板

級支持包)。

作用:將系統軟件與底層硬件部分隔離,使得系統的底層設備驅動程序與硬件無關:

功能:一般應具有相關硬件的初始化、數據的輸入/輸出操作和硬件設備的配置等功能。BSP

是主板硬件環境和操作系統的中間接口,是軟件平臺中具有硬件依賴性的那一部分,主要目

的是為了支持操作系統,使之能夠更好地運行于硬件主板上。

(3)軟件層:主要是操作系統,有的還包括文件系統、圖形用戶接口和網絡系統等。操作

系統是一個標準的內核,將中斷、I/O、定時器等資源都封裝起來,以方便用戶使用。

(4)功能層:由基于操作系統開發的應用程序組成,用來完成對被控對象的控制功能。功

能層是面向被控對象和用戶的,為了方便用戶操作,往往需要具有友好的人機界面。

5.非占先式,調度法也稱作合作型多任務(cooperativemultitasking),各個任務彼此合作共享

一個CPU。中斷服務可以使一個高優先級的任務由掛起狀態變為就緒狀態。但中斷服務以后

控制權還是回到原來被中斷了的那個任務,直到該任務主動放棄CPU的使用權時,那個高優

先級的任務才能獲得CPU的使用權。當系統響應時間很重要時,要使用占先式(preemptive)

內核。最高優先級的任務一旦就緒,總能得到CPU的控制權。當一個運行行的任務使一個比

它優先級高的任務進入了就緒態,當前任務的CPU使用權就被剝奪了,或者說被掛起了,那

個高優先級的任務立刻得到了CPU的控制權。

6.在實時系統中,如果系統在指定的時間內未能實現某個確定的任務,會導致系統的全面失

敗,這樣的系統被稱為強實時系統或硬實時系統。強實時系統響應時間一般在亳秒或微秒級。

在弱實時系統中,雖然響應時間同樣重要,但是超時卻不會發生致命的錯誤。其系統響應時間

在亳秒至秒的數量級上,其實時性的要求比強實時系統要差一些。

7.嵌入式系統的設計步驟及各部分的主要工作如下。

(1)需求分析階段,羅列出用戶的需求;

(2)體系結構設計階段,描述系統的功能如何實現;

(3)詳細設計階段,進行硬件系統與軟件系統的分類劃分,以決定哪些功能用硬件實現,哪些

用軟件實現;

(4)系統集成,把系統的軟件、硬件和執行裝置集成在一起,進行調試,發現并改進在設計過

程中的錯誤;

(5)系統測試,對設計好的系統進行測試,看其是否滿足給定的要求。

8.Linux作為嵌入式操作系統的優勢主要有以下幾點:

(1)可應用于多種硬件平臺。Linux已經被移植到多種硬件平臺,這對于經費,時間

受限制的研究與開發項目是很有吸引力的。原型可以在標準平臺上開發后移植到具體的硬件

上,加快了軟件與硬件的開發過程。Linux采用一個統一的框架對硬件進行管理,從一個硬件

平臺到另一個硬件平臺的攻動與上層應用無關。

(2)Linux的高度模塊化使添加部件非常容易。本身內置網絡支持,而目前嵌入式系統

對網絡支持要求越來越高,

(3)Linux是一個和Unix相似、以內核為基礎的、具有完全的內存訪問控制,支持大量

硬件(包括X86,Alpha、ARM和Motorola等現有的大部分芯片)等特性的一種通用操作系統。

(4)Linux可以隨意地配置,不需要任何的許可證或商家的合作關系。其程序源碼全部

公開,任何人可以修改并在GUN通用公共許可證(GNUGeneralPublicLicense)下發行。這樣,

開發人員可以對操作系統進行定制,適應其特殊需要。

(5)Linux帶有Unix用戶熟悉的完善的開發工具,幾乎所有的Unix系統的應用軟件都已移

植到了Linux」:。其強大的語言編譯器GCC,C++等也可以很容易得到,不但成熟完善,而且

使用方便。

9.(參考答案)Linux執號進程調度一般是在以下情況發生的:

(1)正在執行的進程運行完畢;

(2)正在執行的進程調用阻塞原語將自己阻塞起來進入等待狀態;

(3)正在執行的進程調用了P原語操作,從而因資源不足而被阻塞;或調用了V原語操作激

活了等待資源的進程隊列;

(4)執行中的進程提出UO請求后被阻塞;

(5)系統分配的時間片已經用完;

以上都是CPU為不可剝奪方式下的引起進程調度的原區。在CPU方式是可剝奪時,還有下面

的原因:

(6)就緒隊列中的某個進程的優先級變得高于當前運行進程的優先級,從而也將引起

進程調度。

嵌入式Linux實時操作系統及應用編程

第2章

一.填空題:

1.改變目錄位置至用戶的工作目錄

2.改變目錄位置至相對路徑user的目錄下

3.查看當前目錄下的文件

4.查看文件.bash_profile的內容

5.分頁查看inittab文件內容

6.將目錄/tmp下的文件filel復制到當前目錄下,文件名為file2

7、將文件filel移到目錄dirl下,文件名仍為filel

8、建立一新目錄dir1

9、刪除目錄dirl,但dirl下必須沒有文件存在,否則無法刪除

10、刪除文件名中有五個字符且前四個字符為file的所有文件

11.文件config的內容依次顯示到屏幕卜

12.以分頁方式查看文件名filel的內容

13.以分頁方式查看文件名filel的內容

14.顯示目錄dirl的總容量

15.對于目錄dir1,設定成任何使用者皆有讀取及執行的權利,但只有所有者可做修改

16、對于文件fi1e1,設定只有所有者可以讀、寫和執行的權利。

17、將文件file4鏈接至文件fi1e3o

18、尋找文件fi1e1中包含字符串abc所在行的文本內容。

19、自根目錄下尋找文件filel的路徑。

20、比較目錄dir1與dir2內各文件的不同之處。

二、單項選擇題

1.A2.B3.D4.C5.B

6.C7.A8.C9.D10.B

11.A12.D13.D14.B15.B

16.B17.A18.DI9.B20.B

嵌入式Linux實時操作系統及應用編程

第3章

一.填空題:

1.next

2.命令模式

3.預處理、編譯、匯編和連接

4.stepnext

5.末行模式

6.預處理鏈接

7.匯編

8.wtest,txt

二、綜合題

1.參考答案:

prl:prog,osubr.o

gcc-oprlprog,osubr.o

prog,o:prog,cprog,h

gcc-c-oproR.oprog,c

subr.o:subr.csubr.h

gcc-c-osubr.osubr.c

2.(1)

hello:main,olist,osymbol,otable,o

gcc-oprogmain.olist,osymbol,otable,o

main,o:main,ctable,hsymbol,hlist,h

gcc-c-omain,omain,c

list,o:list,clist,h

gcc-c-olist.olist.c

symbol,o:symbol.csymbol,h

gcc-c-osymbol,osymbol,c

table,o:table,ctable,hsymbol,hlist,h

gcc-c-otable,otable,c

clean:

rmhello*.o

(2)mount-tnfs-onoclock192.168.0.10:/home/armtest/hello/mnt

3.

hello,c:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include"hello,h”

intmain(intargc,char*argv[])

(

printf(^HelloWorld!\n,");

message();

return0;

)

hello.h:

voidmessage(void);

message,c:

#include<stdio.h>

voidmessage(void){

prinlf("Thisisamessage!\nz,);

)

三.選擇題

1.C2.A3.B4.B5.B6.C

7.C8.D9.D10.A11.A

嵌入式Linux實時操作系統及應用編程

第4章

選擇題

LA2.C3.D4.1)5.C

6.B7,C8.A9.D10.D

11.D12.D13.D14.B15.D

16.B17.A18.C19.C20.C

二.簡答題

LLinux內核的編譯菜單有好幾個版本,運行:

(1)makeconfig:進入命令行,可以一行一行的配置,但使用不十分方便。

(2)makemenuconfig:大多數開發人員使用的Linux內核編譯菜單,使用方便。

(3)iiuikcxcunGg:在2.4.X以及以前版本中xcunfig菜單是基丁TCL/TK的圖形庫的。

2.在完成內核的裁減之后,內核的編譯就只要執行以下幾條命令:

makeclean編譯內核之前先把環境給清理干凈。有時你也可以用makercalclcan或make

mrproper來徹底清除相關依賴,保證沒有不正確的.。文件存在。

makedep編譯相關依賴文件

makezlmage創建內核鏡像文件

makemodules創建內核模塊,若不創建內核模塊,這步可以不要。

makeinstall把相關文件拷貝到默認的目錄。在給嵌入式設備編譯時這步可以不耍,因為

具體的內核安裝還需要你手進行。

3.此命令是裝載壓縮映像工件zlmage到flash存儲器中,地址是kemel分區,并采用xmodem傳輸

協議。

4.此命令是設置網卡1的地址,掩碼為255.255.255Q不寫netmask參數則默認為

5.此命令將nfs服務的共享目錄sharedir加載到/mnt/nfs。

6、此命令是裝載根文件系統root.cramfs到flash存儲器中,地址是根文件系統分區,并

采用xmodem傳輸協議。

7、這個命令的操作同時進行了分區和格式化,0?128K存放vivi,128K?192K存放VIVI

控制臺指令,192K-1216K存放kernel,1216K-4288K存放root,其余部分存放應用程序。

嵌入式Linux實時操作系統及應用編程

第5章

一.選擇題

1.B2.C3.C4.C5.D6.C

二.綜合應用題

1.

Tomismyfriend

Jackismyfriend

Harryismyfriend

2.

(1)程序注釋

#!/bin/sh定義實用的shell

#

n/etc/rc.d/rc.httpd注釋行,凡是以星號開始的行均為注釋行。

#

#Start/stop/restarttheApachewebserver.

#

#TomakeApachestartautomaticallyatboot,makethis

#fileexecutable:chmod755/etc/rc.d/rc.httpd

#

casew$rin枇ase結構開始,判斷“位置參數”決定執行的操作。本程序攜帶一個“位置

參數”,即$1

,start,)#若位置參數為start

/usr/sbin/apachec11start;;#啟動httpd進程

'stop')#若位置參數為stop

/usr/sbin/apachect1stop;;#關閉httpd進程

'restart*)#若位置參數為stop

/usr/sbin/apachect1restart;;#重:新啟動httpd進程

*)#若位置參數不是start、stop或restart時

echo"usage$0startstop|restart;;#顯示命令提示信息:程序的調用方法

esacrtcase結構結束

(2)程序的功能是啟動,停止或重新啟動httpd進程

(3)程序的調用方式有三種:啟動,停止和重新啟動。

3.

#!/bin/sh

FILENAME:

echo**Inputfilename:"

readFILENAME

if[-c-FILENAME"]

then

cp$FILENAME/dev

fi

4.

#/bin/bash

typesetfirstsecond

read-p"Inputthefirstnumber:*first

read-p"Inputthesecondnumber:second

result=$[$first+$second]

echo"resultis:Sresult*

exit0

5.

#!/bin/sh

i=l

while[i-le50]

do

if[-d/userdata];then

mkdir-p/userdata/user$i

chmod754/userdata/user$i

echo"user$i”

let=i+1〃(或i=$(($i+l))

else

mkdir/userdata

mkdir-p/userdata/user$i

chmod754/userdata/user$i

echo'user$i”

let"i=i+1"(或i=$(($i+l))

fi

done

嵌入式Linux實時操作系統及應用編程

第6章

一.簡答題

1.使用虛擬地址尋址整個系統的主存和輔存的方式在現代操作系統中被稱為虛擬內存。MMU

便是實現虛擬內存的必要條件。嵌入式處理器如果存在MMU,由于在MUU具備內存地址映射

和尋址功能,操作系統會使用它完成從虛擬地址到物理地址的轉換,所有的應用程序只需

要使用虛擬地址尋址數據,

虛擬內存的管理方法使系統既可以運行體積比物理內存還要大的應用程序,也可以實現

“按需調頁”策略,既滿足了程序的運行速度,又節約了物理內存空間。

2.進程內存區域涉及到5種數據段,即:

①代碼段:代碼段是用來存放可執行文件的操作指令,也就是說是它是可執行程序在內存

中的鏡像。

②數據段:數據段用來存放可執行文件中已初始化全局變量,換句話說就是存放程序靜態

分配的變量和全局變量。

③BSS段:BSS段包含了程序中未初始化的全局變量,在內存中BSS段全部置零。

④堆(heap):堆是用于存放進程運行中被動態分配的內存段,它的大小并不固定,可動

態擴張或縮減。當進程調用malloc等函數分配內存時;新分配的內存就被動態添加到堆上(堆

被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)

⑤棧:棧是用戶存放程序臨時創建的局部變量,也就是說函數括弧“{}”中定義的變量(但

不包括static聲明的變量,static意味著在數據段中存放變量)。除此以外,在函數被調用

時,其參數也會被壓入發起調用的進程棧中,并且待到調用結束后,函數的返回值也會被存

放回棧中。

3.在Linux系統中,內核在最高級執行,也稱為“系統態”,在這一級任何操作都可以執行。

而應用程序則執行在最低級,即所謂的“用戶態”。在這一級處理器禁止對硬件的直接訪問

和對內存的未授權訪問。模塊是在所謂的“內核空間”中運行的,而應用程序則是在“用戶

空間”中運行的。它們分別引用不同的內存映射,也就是程序代碼使用不同的“地址空間”。

4.共享內存區域是被多個進程共享的一部分物理內存。如果多個進程都把該內存區域映射到

自己的虛擬地址空間,則這些進程就都可以直接訪問該共享內存區域,從而可以通過該區域

進行通信。共享內存是進程間共享數據的一種最快的方法,一個進程向共享內存區域寫入了

數據,共享這個內存區域的所有進程就可以立刻看到其中的內容。這塊共享虛擬內存的頁面,

出現在每一個共享該頁面的進程的頁表中。但是它不需要在所有進程的虛擬內存中都有相同

的虛擬地址。

5.內存管理利用虛擬文件系統支持交換,交換進程(sw叩d)定期由調度程序調度,這也是內存

管理依賴于進程調度的唯--原因。當一個進程存取的內存映射被換例時,內存管理向文件系統

發出請求,同時,掛起當前正在運行的進程。

二.編程題

1.參考程序:

#include<stdlib.h>

structtest

(

inta[10];

charb[20];

)

intmain()

{

structtest*ptr=calloc(sizeof(structtest),10);

)

2.參考程序:

#include<sys/types.h>

#include<sys/stat.h>

??include<fcntl.h>

#include<unistd.h>

#include<sys/mman.h>

main()

{

intfd;

void*start;

structstatsb;

fd=open(<Vetc/passwd,>,0RDONLY);/*打開/etc/passwd*/

fstat(fd,&sb);/*取得文件大小*/

start=mmap(NULL,sb.st_size,PROT_READ,M/\P_PRIVATE,fd,0);

if(start==MAP_FAILED)/*判斷是否映射成功*/

return;

printf("%s”,start);

munma(start,sb.st_size);/*解除映射*/

closed(fd);

)

嵌入式Linux實時操作系統及應用編程

第7章

一、單項選擇題

1.A2.B3.A4.D5.6.A7.C

二.編程題

1.

(1)

Voidmain(void)

(

intfid;

fid=open(/test.txtw,O_RDWR10_CREAT);

if(fid=-l)

(

Printf("openorcreateerror'n");

exit(0);

)

Close(fid);

)

(2)

objects=main.o

exec=main

all:$(objects)

gcc-o$(exec)$(objects)

main.o:main.c

gcc-cmain,c

c1ean:

rm-r$(exec)$(objects)

2.參考程序:

#include<sys/types.h>

#inclu(le<sys/stat.h>

#include<fcntl.h>

/include<stdlib.h>

#include<unistd.h>

#include<stdio.h>

#defineBUFFER_SIZE1024

intmain(intargc.char**argv)

intfrom_fd,to_fd;

intbytcs_rcad,byles_wriic;

charbuffer[BUFFER_SIZE];

char*ptr;

if(argc!=3){

fprinll'(stderr,"Usage:%sfromfilctofile\n\a",argvlOJ);

exit(l);

)

/*打開源文件*/

if((frotn_fd=open(argv[1],O_RDONLY))==-1){

fprintf(stderr."Open%sEiTor:%s\n".argv|1|,strerror(emio);;

exit(l);

)

/*創建目的文件*/

if((to_fd=open(argv⑵,O_WRONLY|O_CREAT.S」RUSR|S」WUSR))==-1){

fprintf(stdcrr,"Opcn%sError:%s\n",argv[2],strcrror(eirno));

cxit(l);

)

/*以下代碼是一個經典的拷貝文件的代碼*/

whilc(byics_rcad=rcad(from_fd,buffer,BUFFER_SIZE)){

if((bytes_read==-1)&&(errno!=EINTR))break:/*發生讀錯誤,退出循環*/

elseif(bylcs_read>O){

pti-buffer:

while(by(es_write=wrile(to_fd,ptr,bytes_read)){

it((bytes_wnte=-l)&<&(errno!=fclNIK))break:/*若寫錯誤,退出循環*/

/*寫完了所有讀的字節*/

elseif(bytes_write==bytes_read)break;/*讀寫字節不等退出循環*/

elseif(bytes_write>O){/*只寫了一部分,繼續寫*/

ptr+=b>/tcs_wrilc;

bytes_read-=bytes_write:

)

)

if(bytes_wri:e==-1)break;/*寫的時候發生的致命借誤*/

)

}

close(from_fd);

close(to_fd);

exit(O);

I

3.參考程序:

#include<stdio.h>

structstudent{

charname[10];

intage;

);

intmain。

(

FILE*fp;

inii;

structstudentboya[2],boyb[2],*pp.*qq:

if((fp=fopcn("7-6.txt"."w+,,))==NULL)〃打開文件

|

printf("Cannotopenfile,exit

return-1;

I

pp=boya;

qq=boyb;

prinlf("plcaseinputdala:\n");〃輸入學生信息

for(i=0;i<2;i++,pp++)

scanf("%s%d",pp->naine,&pp->age);

pp=boya;

fwrite(pp,sizeof(struccstudent),2,fp);〃把學生信息寫入文件

rewind(fp);〃重定位文件

fread(qq,sizeof(structstudent),2,fp);〃從文件中讀取學生信息

prin(f("namc\l\tagc\n"i;

for(i=0;i<2;i++,qq++)

printf("%s\t\t%d\n",qq->name,qq->age);

fclose(fp);

return0;

4.參考程序如下:

嵌入式Linux實時操作系統及應用編程

第8章

一、單項選擇題

1.B

2.A

3.A

4.D

5.C

6.D

7、C

8、I)

9、C

10、B

二.閱讀程序題

1.答案要點:

(1)將數據緩沖區清0

(2)創建管道

(3)創建子進程

(4)關閉子進程寫描述符

(5)子進程讀取管道內容

(6)關閉子進程讀描述符

(7)父進程運行控制語句

(8)關閉父進程的讀描述符

(9)將數據寫入緩沖區

(10)關閉父進程寫描述符

三.程序設計

1.參考程序如下:

voidmain(){

kcytuniquekey;/*定義一個IPC關鍵字*/

intid;

structsembuflock_it;

unionsemunoptions;

inti;

unique_key=ftoka');/*生成關鍵字,字符'a'是一個隨機種子*/

/*創建一個新的信號量集合*/

id=semget(unique_key,1,IPC_CREAT|IPC_EXCL|0666);

printf(?,semaphoreid=%d\n”,id);

options,val=1;/*設置變量值*/

semctl(id,0,SETVAL,options);/*設置索引0的信號量*/

/*打印出信號量的值"

i=scmctl(id,0,GETVAL,0);

printf("valueofsemaphoreatindex0is%d\n/,,i);

/*下面重新設置信號量*/

lock_it.sem_num=設置哪個信號量*/

lockit.scmop=~1;/*定義操作*/

lock_it.sem_flg=IPC_NOWAIT;/*操作方式*/

if(semop(id,&lock_it,1)==-1){

printf(*cannotlocksemaphore.\n");

exit(1);

)

i=semctKid,0,GETVAL,0);

printf("valueofsemaphoreatindex0is%d\n',i);

/*清除信號量*/

semctl(id,0,1PC_RMID,0);

)

2.參考程序:

(1)init.c清單

#include<unistd.h>

#include<signal,h>

#include<sys/param.h>

^include<sys/types.h>

#include<sys/stat.h>

voidinit_daemon(void)

intpid;

inti;

if(pid=fork())

exitS);〃是父進程,結束父進程

elseif(pid<0)

exit(1);〃fork失敗,退出

〃是第一子進程,后臺繼續執行

setsidO;

〃第一子進程成為新的會話組長和進程組長并與控制終端分離

if(pid=fork0)

exit(0);〃是第一子進程,結束第一子進程

elseif(pid<0)

exit(1);〃fork失敗,退出

〃是第二子進程,繼續

〃第二子進程不再是會話組長

for(i=0;i<N0FILE;++i)〃關閉打開的文件描述符

close(i);

chdir("/tmp");〃改變工作目錄到/tmp

umask(0);//重設文件創建掩模

return;

)

(2)test,c清單

#include<stdio.h>

#include<time,h>

voidinit_daemon(void);〃守護進程初始化函數

main()

(

FILE*fp;

time_tt;

initdaemon。;〃初始化為Daemon

while(l)〃每隔一分鐘向test,log報告運行狀態

(

sleep(60);//睡眠一分鐘

if((fp=fopen("test,log","a"))>=0)

(

t=time(0);

reat%s\nv,asetime(localtime(&t)));

fclose(fp);

}

}

)

以上程序在RedHaiUnux6.0下編譯通過。步驟如下:

編譯:gcc-g-otestinit.ctest,c

查看進程:ps-ef

程的各種特性滿足上面的要求。

3.參考程序:

ttdefineINPUT0

^defineOUTPUT1

voidmain(){

intfile?descriptors[2];

/*定義子進程號*/

pid_tpid;

charbuf[256];

intreturnedcount;

/*創建無名管道*/

pipe(filedcscriptors);

/*創建子進程*/

if((pid=forkO)==-1){

printf(''Errorinfork\n");

exit(1);

)

/*執行子進程*/

if(pid==0){

printf(^inthespawned(child)process…\n");

/*子進程向父進程寫數據,關閉管道的讀端*/

close(file_descriptors[INPUT]);

write(filedescriptors[OUTPUT],“testdata”,strlen(^testdata"));

exit(0);

)else{

/*執行父進程*/

printfC*inthespawning(parent)process...\n*);

/*父進程從管道讀取子進程寫的數據,關閉管道的寫端*/

close(file_descriptors[OUTPUT]);

returncdcount=read(filedescriptors[INPUT],buf,sizeof(buf));

printf(,z%dbytesofdatareceivedfromspawnedprocess:%s\n”,

returnedcount.buf);

)

)

在Linux系統下,有名管道可由兩種方式創建:命令行方式mknod系統調用和函數mkfifo。

下面的兩種途徑都在當前目錄下生成了一個名為myfifo的有名管道:

方式一:mkfifo("myfifo","rw");

方式二:mknodmyfifop

生成了有名管道后,就可以使用一般的文件I/O函數如open、closerread,write等來對它

進行操作。下面即是一個同單的例子,假設我們已經創建了一個名為myfifo的有名管道。

/*進程一:讀有名管道*/

^include

ttinclude

voidniain(){

FILE*in_file;

intcount=1;

charbuf[80];

infile=fopen(mypipe,r);

if(infile==NULL){

printf("Errorinfdopen.\n?,);

exit(1);

}

while((count=fread(buf,1,80,infile))>0)

printf("receivedfrompipe:%s\n”,buf);

fclose(infile);

)

/*進程二:寫有名管道*/

#include

^include

voidmain(){

FILE*out.file;

intcount=1;

charbuf[80];

out_file=fopen(,zmypipe*,"w");

if(out_file--NULL){

printf(z,Erroropeningpipe.");

exit(1);

)

sprintf(buf,z,thisistestdataforthenamedpipeexample'd');

fwrite(buf,1,80,out_file);

fclose(outfile);

)

嵌入式Linux實時操作系統及應用編程

第9章

一、簡答題

1.參考答案:

Mutex互斥量,用于操作某個臨界資源時對該資源上鎖,以實現互斥地對獨占資源的使用。(3

分)

Scmophorc信號燈,信號燈內有一計數器,可以用于對多個同類資源的分配。當資源用完時,

申請資源的線程會在信號量上睡眠,有線程釋放資源時,再將該線程喚醒繼續運行。(3分)

Condition條件變量,條件變量用于等待信號。當?個線程需要等待某個信號時,就可到條件變

量上等待,當信號具備時,系統會喚醒該線程繼續運行。(4分)

2.參考答案:

本地:共享內存+信號量,適合于大展數據傳輸。Linux支持系統V和POSIX的共享內存和

信號量。(5分)

遠程:Sockcl+應用協議。適合于跨網絡的(大量)數據傳輸。Linux支持BSD的socket。應用

層協議需要自行設計。(5分)

3.答案要點:程序是編譯后形成的可執行代碼,是靜止的。進程是程序的?次執行,是活動

的。線程是進程的可執行單元,同一進程的不同線程共享進程的資源和地址空間。

4.兩種實現方法,一種是繼承Thread,另外一種是實現接口Runnable。

同步的實現方法有兩種,分別是synchronized,wait與notify。用synchronized可以對一段代碼、

一個對象及一個方法進行加鎖。用wait與notify可以使穴■象處于等待及喚醒方式導致同步,因

為每個對象都直接或間接的繼承了Object類。

5.參考答案:(每小點1分)

Linux執行進程調度一般是在以卜情況發生的:

(1)正在執行的進程運行完畢;

(2)正在執行的進程調用阻塞原語將自己阻塞起來進入等待狀態:

(3)正在執行的進程調用了P原語操作,從而因資源不足而被阻塞;或調用了V原語快作激

活了等待資源的進程隊列;

(4)執行中的進程提出UO請求后被阻塞;

(5)系統分配的時間片已經用完;

以上都是CPU為不可剝奪方式下的引起進程調度的原因。在CPU方式是可剝奪時,還有下面

的原因:

(6)就緒隊列中的某個進程的優先級變得高于當前運行進程的優先級,從而也將引起進程調

度。

二.編程題

參考程序:

/*數據寫入緩沖區*/

voidput(structprodcons*b,intdata)

{pthrcad_mutcx_lock(&b->lock);/*獲得互斥鎖*/

while((b->wrilepos+1)%BUFFER_SIZE==b->readpos){

printf(uwaitfornotfull\n");

pthread_cond_\vait(&b->notfull,&b->lock);

/*等待b->notfull,不滿則跳出阻塞力

}

b->buffer[b->writepos]=data;/*寫入數據*/

b->writepos++;

if(b->vvritepos>=BUFFER_SIZE)b->writepos=0;

pthread_cond_signal(&b->notempty);/*設置狀態變量

pthread_mutex_unlock(&b->lock);/*釋放互斥鎖*/

}

/*從緩沖區中讀出數據*/

intgel(struc(prodcons*b)

(

intdata;

pthread_mutex_lock(&b->lock);/*獲得互斥鎖*/

while(b->writcpos==b->rcadpos){

printf("waitfornotempty\nn);

pthrcad_cond_\vait(&b->notempty,&b->lock);

/*等待不空則跳出阻塞*/

}

data=b->buffer[b->readpos];/*讀出數據*/

b->readpos++;

if(b->rcadpos>=BUFFER_SIZE)b->readpos=0;

pthread_cond_signal(&b->notfull);/*設置狀態變量*/

pthread_inutex_unlock(&b->lock);/*釋放互斥鎖*/

returndata;

}

/*生產者進程*/

void*producedvoid*data)

intn;

for(n=0;n<1000;n++){

printf("put—>%d\n,'?n);

pul(&buffer,n);

put(&buffer,OVER);

printf("producerstopped!\nH);

returnNULL;

/*消費者進程*/

void*consuiner(void*data)

{intd;

while(1){

d=gct(&buffcr);

if(d==OVER)break;

printf("%d->get\nd);

piintf("consumcrstoppcd!\n");

returnNULL;

/*主函數*/

intmain(void)

{pthread_tth_a,th_b;

void*rctval;

init(&buffer);

pthrcad_crcatc(&th_a,NULL,producer,0);

pthread_create(&th_b,NULL,consumer,0);

/*等待生產者和消費者結束*/

pthreadjoin(th_a,&retval);

pthreadjoin(th_b,&retval);

return0;

第10章

一、單項選擇題

LB2.B3.C4.A5.B6.C7、C8、B9、A10、B

二.編程題

1.參考程序:

#includo<stdio.h>

#include<stdlib.h>

#include<errno.h>

#include<string.h>

^include<sys/types.h>

"include<netinet/in.h>

^include<sys/socket.h>

#include<sys/wait.h>

Jtinclude<unistd.h>

#include<arpa/inet.h>

intmain(intargc,char**argv)

(

intsockfd;

structsockaddrinmyaddr;

unsignedintmyport,1isnum;

if(argv[l])

myport=atoi(argvfl]);

else

myport=7838;

if(argv[2])

lisnum=atoi(argv[2]);

else

lisnum=2;

if((sockfd=socket(PF_INET,SOCK_STREAM,0))==-1){

perror("socket");

exit(1);

)

elseprintfCsockelcreated\nw);

bzero(&my_addr,sizeof(myaddr));

myaddr.sin_family=PFINET;

myaddr.sinport=htons(mypoi't);

if(argv[3])my_addr.sin_addr.s_ciddr=inet_addr(argv[3]);

elsemyaddr.sinaddr.s_addr=INADDRANY;

if(bind(sockfd,(structsockaddr*)&myaddr,sizeof(structsockaddr))==-1)

{

perror("bind");

exit(1);

)

elseprintf("binded'n");

if(listen(sockfd,lisnum)==-1){

perror("listen");

exit(1);

)

elseprintf("beginlisten\n,/);

sleep(100);

close(sockfd);

return0;

}

編譯程序用下列命令:

gcc-Wa11simple-listen,c

運行程序用如下命令:

./a.out78382

這將在你自己主機的所有IP地址是等待客戶端連接。比如你的網卡lo的IP地址127.0.0.1,

又比如你的網卡ethO的IP地址192.168.0.100

如果要指定只在某個地址是開啟監聽服務,可以用下面的命令:

./a.out78382127.0.0.1

這樣,客戶端只能通過127.0.0.1的7838端口連接你的程序。

你可以開啟?個終端輸入telnet127.0.0.17838米測試是否能連接成功。

同時可以用netstat-angrep7838命令來查看網絡是否連接正常

2.參考程序:

"include<stdio.h>

#includc<stdlib.h>

include<errno.h>

#include<string.h>

#include<sys/types.h>

#include<netinet/in.h>

#includc<sys/sockot.h>

#include<sys/wait.h>

#includo<unistd.h>

#include<arpa/inet.h>

/************關于本文檔********************************************

"filename:simple-accept.c

?purpose:演示最基本的網絡編程步驟,開啟服務端的監聽,并接收每個客戶端的連接請求

?wroteby:zhoulifa(zhoulifa@163.com)周立發(http:〃zhoulifa.bokcc.com)

Linux愛好者Linux知識傳播者SOHO族開發者最擅長C語言

?datetime:2007-01-2412:41

*Note:任何人可以任意復制代碼并運用這些文檔,當然包括你的商業用途

*但請遵循GPL

*Hop。:希望越來越多的人貢獻自己的力量,為科學技術發展出力

*科技站在巨人的肩膀上進步更快!感謝有開源前輩的貢獻!

intmain(intargc,char**argv)

intsockfd,new_fd;

socklentlen;

structsockaddr_inmy_addr,their_addr;

unsignedintmyport,lisnum;

if(argv[1])

myport=atoi(argv[l]);

else

myport=7838;

if(argv[2])

1isnum=atoi(argv⑵);

else

lisnum=2;

if((sockfd=socket(PF_INET,SOCK_STREAM,0))==-1){

perror("socket");

exit(1);

)

elseprintf("socketcreated\n/,);

bzei'o(&my_ciddr,sizeof(my_addr));

myaddr.sinfamily=PFINET;

my_addr.sin_port=htons(myport);

if(argv[3])myaddr.sinaddr.s_addr=inetaddr(argv[3]);

elsemyaddr.sinaddr.saddr=INADDRANY;

if(bind(sockfd,(structsockaddr*)&my_addr,sizeof(structsockaddr))==-1)

{

perror("bind");

exit(1);

)

elseprintf("binded'n");

if(listen(sockfd,lisnum)==-1){

perror("listen");

exit(1);

)

elseprintf(''begin1isten\n,/);

while(l){

len=sizeof(structsockaddr);

if((newfd=accept(sockfd,(structsockaddr*)&their_addr,&lcn))==-1)

(

pcrror("accept");

exit(errno);

)

elseprintf("server:gotconnectionfrom%s,port%d,

socket%d\n,/,inetntoa(theiraddr.sinaddr),

ntohs(theiraddr.sinport),newfd);

)

close(sockfd);

return0;

}

編譯程序用下列命令:

gcc-Wallsimple-acccpt.c

運行程序用如下命令:

./a.out78381127.0.0.1

另外開多幾個客戶端程療連接上來,

程序輸出結果如下:

server:gotconnectionfrom127.0.0.1,port15949,socket4

server:gotconnectionfrom127.0.0.1,port15950,socket5

server:gotconnectionfrom127.0.0.1,port15951,socket6

server:gotconnectionfrom127.0.0.1,port15952,socket7

3.參考程序:

服務器:

??include<sys/types.h>

#include<sys/socket.h>

#include<string.h>

#include<netinet/in.h>

^include<st

溫馨提示

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

評論

0/150

提交評論