版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、第7章 嵌入式uClinux及其應(yīng)用開發(fā)(2)7.3.2 uClinux針對硬件的改動目前,uClinux已被成功移植到S3C4510B及其他多款A(yù)RM芯片上,但由于嵌入式操作系統(tǒng)的運行是與嵌入式系統(tǒng)的硬件密切相關(guān)的,而硬件的設(shè)計則會因為使用場合的不同而千差萬別,因此,在uClinux內(nèi)核源代碼中和硬件緊密相關(guān)的部分就應(yīng)該針對特定的硬件作出適當(dāng)?shù)男薷?,由于uClinux內(nèi)核源代碼包含很大一部分的硬件驅(qū)動程序,不可能一一列舉,在此,就基于S3C4510B的最小系統(tǒng)的設(shè)計與運行相關(guān)的部分作簡單的介紹,希望對讀者有所啟發(fā)。uClinux內(nèi)核源代碼中對S3C4510B片內(nèi)特殊功能寄存器以及其他相關(guān)硬件
2、信息的定義位于uClinux-SamsungLinux-2.4.xincludeasm-armnommuarch-samsunghardware.h文件中,其中有幾個地方值得注意:/* * define S3C4510b CPU master clock */#define MHz#define fMCLK_MHz(50 * MHz)#define fMCLK(fMCLK_MHz / MHz)#define MCLK2(fMCLK_MHz / 2)以上定義了系統(tǒng)工作的主時鐘頻率為50MHz,若用戶系統(tǒng)的工作頻率不同,應(yīng)在此處修改,若串行口采用內(nèi)部時鐘信號用于波特率生成,該頻率同時還與串行通信波
3、特率有關(guān)。/*/* System Memory Control Register */*/#define DSR0(20)/* ROM Bank0 */#define DSR1(02)/* 0: Disable, 1: Byte, 2: Half-Word, 3: Word */#define DSR2(04)#define DSR3(06)#define DSR4(08)#define DSR5(010)#define DSD0(212) /* RAM Bank0 */#define DSD1(014)#define DSD2(016)#define DSD3(018)#define DSX
4、0(020)/* EXTIO0 */#define DSX1(022)#define DSX2(024)#define DSX3(026)#define rEXTDBWTH(DSR0|DSR1|DSR2|DSR3|DSR4|DSR5 | DSD0|DSD1|DSD2|DSD3 | DSX0|DSX1|DSX2|DSX3)以上定義了系統(tǒng)存儲器控制寄存器,按照以上定義,ROM/SRAM/FLASH Bank0定義為16位數(shù)據(jù)寬度(事實上,ROM/SRAM/FLASH Bank0的數(shù)據(jù)寬度由B0SIZE1:0的狀態(tài)決定),而ROM/SRAM/FLASH Bank1ROM/SRAM/FLASH Ban
5、k5禁用;DRAM/SDRAM Bank0定義為16位數(shù)據(jù)寬度,DRAM/SDRAM Bank1DRAM/SDRAM Bank3禁用;外部I/O組全部禁用;若用戶系統(tǒng)的存儲器系統(tǒng)配置不同,應(yīng)在此處修改。之后還做了其他一些改動,包括對ROM/SRAM/FLASH Bank0控制寄存器的設(shè)置,F(xiàn)lash容量的設(shè)置,DRAM/SDRAM Bank0控制寄存器的設(shè)置,SDRAM容量的設(shè)置等,這些設(shè)置均應(yīng)該與用戶系統(tǒng)對應(yīng)。7.3.3 編譯uClinux內(nèi)核作為操作系統(tǒng)的核心,uClinux內(nèi)核負(fù)責(zé)管理系統(tǒng)的進(jìn)程、內(nèi)存、設(shè)備驅(qū)動程序、文件系統(tǒng)和網(wǎng)絡(luò)系統(tǒng),決定著系統(tǒng)的各種性能。uClinux內(nèi)核的源代碼是完
6、全公開的,任何人只要遵循GPL,就可以對內(nèi)核加以修改并發(fā)布給他人使用,因此,在廣大編程人員的支持下,uClinux的內(nèi)核版本不斷更新,新的內(nèi)核修改了舊的內(nèi)核的缺陷,并增加了許多新的特性,用戶如果想在自己的系統(tǒng)中使用這些新的特性,或想根據(jù)自己的系統(tǒng)量身定制更高效、更穩(wěn)定可靠的內(nèi)核,就需要重新編譯內(nèi)核。一般說來,更新的內(nèi)核版本會支持更多的硬件,具有更好的進(jìn)程管理能力,運行速度會更快、更穩(wěn)定,并且一般都會修復(fù)舊版本中已發(fā)現(xiàn)的缺陷等,因此,經(jīng)常選擇升級更新的系統(tǒng)內(nèi)核是必要的。uClinux內(nèi)核采用模塊化的組織結(jié)構(gòu),通過增減內(nèi)核模塊的方式來增減系統(tǒng)的功能,因此,正確合理的設(shè)置內(nèi)核的功能模塊,從而只編譯系
7、統(tǒng)所需功能的代碼,會對系統(tǒng)的運行進(jìn)行如下幾個方面的優(yōu)化: 用戶根據(jù)自身硬件系統(tǒng)的實際情況定制編譯的內(nèi)核因為具有更少的代碼,一般會獲得更高的運行速度。 由于內(nèi)核代碼在系統(tǒng)運行時會常駐內(nèi)存,因此,更短小的內(nèi)核會獲得更多的用戶內(nèi)存空間。 減少內(nèi)核中不必要的功能模塊,可以減少系統(tǒng)的漏洞,從而增加系統(tǒng)的穩(wěn)定性和安全性。uClinux的內(nèi)核源代碼可以從許多網(wǎng)站上免費下載,內(nèi)核的發(fā)布一般有兩種形式,一種是完整的內(nèi)核版本,完整的內(nèi)核版本一般是.tar.gz文件,使用時需要解壓。另一種是通過對舊的版本發(fā)布補(bǔ)丁(patch),達(dá)到升級的效果。本例所采用的在Linux下使用的交叉編譯器和uClinux-Samsun
8、g-.tar.gz源碼均來自網(wǎng)站.tw/。在準(zhǔn)備好uClinux的內(nèi)核源代碼后,利用交叉編譯器就可以編譯生成運行在硬件目標(biāo)板上的uClinux內(nèi)核。從.tw/上下載uClinux內(nèi)核源代碼uClinux-Samsung-.tar.gz,保存到宿主機(jī)的用戶目錄。運行解壓命令:tar xzvf uClinux-Samsung-.tar.gz解壓完畢后,就會在用戶目錄下生成uClinux-Samsung目錄,以下命令進(jìn)入到該目錄中:$ cd uClinux-Samsung 1. 鍵入命令:make menuconfi
9、g內(nèi)核配置。該命令執(zhí)行完畢后生成文件.config,它保存這個配置信息。下一次再做make menuconfig的時候?qū)a(chǎn)生新的.config文件,原來的.config被改名為.config.old。此時會出現(xiàn)菜單配置對話框,要求進(jìn)行目標(biāo)平臺的選擇,如圖7.6所示,輸入回車后,出現(xiàn)供選擇的具體的供應(yīng)商和產(chǎn)品列表,在這里我們選擇:Samsung/4510B,如圖7.7所示,在庫的選擇上,我們選擇uC-libc,其他選項暫時不用修改,保存好設(shè)置后,存盤退出。圖7.6 目標(biāo)平臺配置圖7.7 選擇合適的產(chǎn)品類型2鍵入命令:make dep該命令用于尋找依存關(guān)系。3. 鍵入命令:make clean該命
10、令清除以前構(gòu)造內(nèi)核時生成的所有目標(biāo)文件,模塊文件和一些臨時文件。1 鍵入命令:make lib_only該命令編譯庫文件。2 鍵入命令:make user_only該命令編譯用戶應(yīng)用程序文件。3 鍵入命令:make romfs該命令生成romfs文件系統(tǒng)。4 鍵入命令:make image注意做到這一步的時候可能會出現(xiàn)錯誤的信息提示,類似于:arm-elf-objcopy: /home/nie/uClinux-Samsung/linux-2.4.x/linux: No such file or directorymake1: * image Error 1make1: Leaving dire
11、ctory /home/nie/uClinux-Samsung/vendors/Samsung/4510Bmake: * image Error 2這是因為第一次編譯時還沒有romfs.o,所以出錯,等romfs.o編譯好了以后,如果再進(jìn)行內(nèi)核的編譯,就不會出現(xiàn)這個錯誤信息了。它完全不影響內(nèi)核的編譯,可以完全不必理會這個錯誤信息。繼續(xù)進(jìn)行編譯工作。5 鍵入命令:make通過各個目錄的Makefile文件進(jìn)行,會在各目錄下生成一大堆目標(biāo)文件。上述步驟完成后,就完成了對uClinux源碼的編譯工作。整個編譯過程視計算機(jī)運行速度而定,大約需要十幾分鐘左右。在編譯內(nèi)核的時,建議在Linux平臺下進(jìn)行。
12、7.3.4 內(nèi)核的加載運行當(dāng)內(nèi)核的編譯工作完成之后,會在/ uClinux-Samsung/images目錄下看到兩個內(nèi)核文件:image.ram和image.rom,其中,可將image.rom燒寫入ROM/SRAM/FLASH Bank0對應(yīng)的Flash存儲器中,當(dāng)系統(tǒng)復(fù)位或上電時,內(nèi)核自解壓到SDRAM,并開始運行。image.ram可直接在系統(tǒng)的SDRAM中運行,使用ADS(或SDT)集成開發(fā)環(huán)境將系統(tǒng)的SDRAM映射到起始地址為0x0處,并將image.ram載入從0x8000開始的SDRAM中,加載完畢后,修改PC指針寄存器的值為0x8000并執(zhí)行。注意該內(nèi)核默認(rèn)串行口COM1為輸
13、入輸出控制臺,波特率為19200,8個數(shù)據(jù)位,1個停止位,無校驗。7.4 在uClinux下開發(fā)應(yīng)用程序當(dāng)完成了上述所有工作后,一個嵌入式應(yīng)用開發(fā)平臺就已經(jīng)搭建好了,在這個平臺之上,就可以根據(jù)不同需要開發(fā)嵌入式應(yīng)用了。圖7.8所示為一個基于uClinux 的嵌入式系統(tǒng)典型框架結(jié)構(gòu),下面將向讀者介紹如何將自己開發(fā)的應(yīng)用程序添加到目標(biāo)板上運行。圖7.8 基于uClinux嵌入式系統(tǒng)框圖基于uClinux系統(tǒng)的應(yīng)用程序的開發(fā)通常是在標(biāo)準(zhǔn)Linux平臺上(本書已經(jīng)介紹了適用于Windows環(huán)境的交叉編譯器,所以也可以在Windows平臺)用交叉編譯工具來完成。由于uClinux是為沒有內(nèi)存管理單元(M
14、MU)的處理器和控制器而設(shè)計的,并做了較大幅度的精簡,所以可能出現(xiàn)這樣的情況:在標(biāo)準(zhǔn)Linux下可以使用的某些函數(shù)在uClinux下卻用不了,這個時候,就需要用戶編寫相應(yīng)的庫函數(shù)了。當(dāng)然絕大多數(shù)的函數(shù)它們都還是通用的。除此以外,在x86版本的gcc編譯器下編譯通過的軟件,通常不需要做太大的改動就可以用剛才我們建立的交叉編譯工具編譯成可以在uClinux上運行的文件格式。因此開發(fā)在uClinux 下運行的程序,基本上就和開發(fā)在Linux下運行的程序是一樣的,關(guān)于Linux下的編程,讀者可以參考其他更詳細(xì)的資料,以下就一個簡單的例子,描述其基本開發(fā)過程。考慮一個定時中斷的例子,文件名為lednxy
15、.c,其源代碼如下:/* * Institute of Automation, Chinese Academy of Sciences * File Name: lednxy.c * Description: timing interrupt * Author:Xueyuan Nie * Date: */#include #include #define IOPMOD (*(volatile unsigned *)0x3ff5000)#define IOPDATA (*(volatile unsigned *)0x3ff5008)int i=0;static void sig_alarm(in
16、t signumber) if(i=3) i=0; IOPDATA=i+; alarm(2);int main(void)IOPMOD=0xff;if(signal(SIGALRM,sig_alarm)=SIG_ERR)printf(“some error occursn”); return 1;alarm(2);while(1);return 0;在代碼中,SIGALRM為系統(tǒng)定義的信號的名字,在頭文件里被定義為一個正整數(shù),用戶自定義函數(shù)sig_alarm()為信號處理函數(shù), 系統(tǒng)函數(shù)alarm()用來設(shè)定一個2秒的定時器,當(dāng)定時器時間片終止的時候,進(jìn)程將會產(chǎn)生SIGALRM信號,在程序中用
17、函數(shù)signal()實現(xiàn)了信號SIGALRM和信號處理函數(shù)sig_alarm()的連接,這樣,當(dāng)用alarm()函數(shù)設(shè)置時鐘的時間段終止時,就會有SIGALRM信號產(chǎn)生,程序就會轉(zhuǎn)而執(zhí)行函數(shù)sig_alarm(),從而實現(xiàn)每隔2秒鐘,I/O口數(shù)據(jù)寄存器的值發(fā)生一次變化,達(dá)到控制LED等的目的。有關(guān)signal()函數(shù)和alarm()函數(shù)的使用,讀者可以查閱有關(guān)在Linux上的C編程方面的內(nèi)容,本書在此不作詳述。該程序達(dá)到的效果就是,讓目標(biāo)硬件上的P0和P1口的兩個LED顯示器按照P0亮,P1亮,P0、P1全亮的順序,每隔2秒實現(xiàn)其中的一種狀態(tài)。在裝有標(biāo)準(zhǔn)Linux的宿主機(jī)(或裝有Cygwin的
18、windows的PC機(jī))上,用前面已經(jīng)建立好的交叉編譯工具編譯源文件,在該程序所在的目錄下鍵入如下命令:arm-elf-gcc Wall O2 Wl,-elf2flt o lednxy lednxy.c仍然在該目錄下,鍵入命令:ls可以查看到在該目錄下生成了文件名為lednxy的文件。在鍵入的編譯命令中,選項 :-Wall 指定產(chǎn)生全部的警告信息;-O2 是一個二級優(yōu)化選項,它表示告訴編譯器產(chǎn)生盡可能小和盡可能快的代碼;-Wl 的一般用法是-Wl,option 就是把它后面的選項傳遞給鏈接器,在本命令中就是把- elf2flt 傳給鏈接器;-elf2flt 指定自動調(diào)用elf轉(zhuǎn)換flat格式的
19、工具;之所以要使用該選項是因為,由于GNU工具本身并不支持flat格式的二進(jìn)制文件,然而,uClinux目前只支持flat格式的可執(zhí)行文件,因此必須使用相應(yīng)的二進(jìn)制工具進(jìn)行格式轉(zhuǎn)換。flat格式是對elf格式的很大的文件頭和一些段信息做了簡化的文件格式。編譯成功后得到的lednxy就可以在uClinux環(huán)境上運行了。關(guān)于如何將生成的可執(zhí)行代碼加入到uClinux,將在后面的章節(jié)講述。除了以命令行的形式進(jìn)行代碼編譯外,我們還可以利用前面提到的makefile的知識,用makefile文件實現(xiàn)代碼編譯的功能。下面給出本例相應(yīng)的makefile文件(該文件名為makefile)。CFLAGS = -
20、Wall Os Dlinux D_linux_ -Dunix D_uClinux_ -DEMBEDLDFLAGS = -Wl,-elf2fltCC = arm-elf-gccLD = arm-elf-gccTARGT = lednxyOBJ = $(TARGT).oSRC = $(TARGT).call: $(TARGT)%.o : %.c $(CC) $(CFLAGS) c $ -o $(TARGT): $(OBJ) $(CC) $(CFLAGS) $(LDFLAGS) o $ $(OBJ) 整個編譯過程如下:nieuClinux usr$ make arm-elf-gcc Wall Os
21、Dlinux D_linux_ -Dunix D_uClinux_ -DEMBED -c lednxy.c o lednxy.oarm-elf-gcc Wall Os Dlinux D_linux_ -Dunix D_uClinux_ -DEMBED -Wl,-elf2flt o lednxy lednxy.o 可以用工具arm-elf-flthdr查看生成的lednxy的格式,它是一個能夠操作和顯示flat格式文件的頭信息的可執(zhí)行程序。在生成lednxy的當(dāng)前路徑下鍵入命令:arm-elf-flthdr lednxy后,可以看到以下對該文件頭描述的信息,lednxyMagic: bFLTRe
22、v: 4Build Date: Thu Jun 19 10:31:14 2003Entry: 0x50Data Start: 0x1c80Data End: 0x2010BSS End: 0x22a0Stack Size: 0x1000Reloc Start: 0x2010Reloc Count: 0x4fFlags: 0x1 ( Load-to-Ram )從顯示的信息,可以看出文件lednxy的確是一個flat格式的文件,是可以在uClinux環(huán)境下運行的。7.4.1 串行通信所謂串行通信就是在傳輸數(shù)據(jù)的時候每次只傳輸一位,其傳輸?shù)乃俾释ǔS谩拔?秒”來表示,即通常所說的“波特率”。Linu
23、x對所有各類設(shè)備文件的輸入輸出操作,看上去就像對普通文件的輸入輸出一樣,所以Linux對串口的操作,也是通過設(shè)備文件訪問的。為了訪問串口,只需要打開相應(yīng)的設(shè)備文件即可。設(shè)備文件/dev/ttyS*是用于掛起Linux終端的文件。默認(rèn)地,在Linux下,串行口COM1和COM2對應(yīng)的設(shè)備分別為/dev/ttyS0和/dev/ttyS1。在程序中,很容易配置串口的屬性,這些屬性定義在結(jié)構(gòu)體struct termios中。為在程序中使用該結(jié)構(gòu)體,需要包含文件,該頭文件定義了結(jié)構(gòu)體struct termios。#define NCCS 19struct termios tcflag_t c_iflag
24、; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ cc_t c_line; /* line discipline */ cc_t c_ccNCCS; /* control characters */;下面對結(jié)構(gòu)體中的各個成員做一個簡單介紹。在c_iflag中的輸入模式標(biāo)志符控制所有的輸入處理過程,就是說,從設(shè)備發(fā)送的字符在被read函數(shù)讀取之前要
25、經(jīng)過處理。類似的,成員c_oflag控制輸出處理過程,c_cflag包含對端口的設(shè)置,如,波特率,字符位數(shù),停止位等。存儲在成員c_lflag的本地模式標(biāo)志符決定是否顯示字符,是否發(fā)送信號到應(yīng)用程序等。數(shù)組c_cc包含了控制字符的定義和超時參數(shù)。成員c_line在POSIX(Portable Operating System Interface for UNIX)系統(tǒng)中不使用。下面結(jié)合一個簡單的實例,說明如何對串口進(jìn)行讀寫操作。/* * Institute of Automation, Chinese Academy of Sciences * File Name: serialcomm.c
26、* Description:communication with serial * Author:Xueyuan Nie * Date: */#include #include #include #include #include #define BAUDRATE B19200 #define SERIALDEVICE /dev/ttyS0int main() int fd,ncount; struct termios oldtio,newtio; char buf=This is a simple application for serial communicationrn;fd = ope
27、n(SERIALDEVICE, O_RDWR | O_NOCTTY ); if (fd 0) perror(SERIALDEVICE); exit(-1); tcgetattr(fd,&oldtio); bzero(&newtio, sizeof(newtio); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR | ICRNL; newtio.c_oflag = 0; newtio.c_lflag = ICANON; tcflush(fd, TCIFLUSH); fcntl(fd,F_SETFL
28、,0); tcsetattr(fd,TCSANOW,&newtio); ncount=write(fd,buf,sizeof(buf); printf(the bytes written to serial is %dn,ncount);printf(character to send is: %sn,buf); perror(write); tcsetattr(fd,TCSANOW,&oldtio); close (fd); return 0;程序首先為波特率常數(shù)定義了宏值,為設(shè)備文件定義了設(shè)備名常數(shù)。有關(guān)波特率常數(shù)的定義可參見(該頭文件包含在termios.h中)。對于普通用戶而言,是不允
29、許訪問設(shè)備文件的,如果要訪問,要么以root賬號登錄,要么需要改變文件的訪問屬性。假定設(shè)備文件是可以訪問的,用open函數(shù)打開設(shè)備文件,返回一個文件描述符(file descriptors,fd),通過文件描述符來訪問文件。O_RDWR標(biāo)志表示對該文件可讀可寫,O_NOCTTY表示該程序不會成為控制終端,這樣就避免了當(dāng)在鍵盤輸入類似ctrl+c的命令后,終止程序的運行。然后用tcgetattr保存串口的當(dāng)前設(shè)置,給端口設(shè)置新的屬性,通過對c_cflag的賦值,設(shè)置波特率,字符大小(CS8表示8位數(shù)據(jù)位,1位停止位,沒有奇偶校驗位),使能本地連接,使能串行口驅(qū)動讀取輸入數(shù)據(jù)。通過設(shè)置c_ifla
30、g ,控制端口對字符的輸入處理過程,IGNPAR符號常量表示忽略奇偶性錯誤的字節(jié),并不對輸入數(shù)據(jù)進(jìn)行任何校驗,ICRNL 將回車符映射為換行符。設(shè)置原始數(shù)據(jù)輸出,使能規(guī)范輸入。在對struct termios結(jié)構(gòu)體的各個成員賦值完畢后,調(diào)用tcsetattr函數(shù)選擇新的設(shè)置,常數(shù)TCSANOW表示新設(shè)置立即生效。調(diào)用write函數(shù)往串口發(fā)送數(shù)據(jù),此時如果打開超級終端應(yīng)該可以看到寫入的字符串。對串口操作結(jié)束后,恢復(fù)原有的端口設(shè)置,關(guān)閉打開的設(shè)備文件。以上是一個簡單的對串口進(jìn)行寫操作的程序,因為通過超級終端來顯示,所以沒有調(diào)用read函數(shù),如果接收數(shù)據(jù)的一端是其他設(shè)備的話,有可能需要讀者再編寫一個
31、接收數(shù)據(jù)的程序,運行發(fā)送和接收程序的兩臺設(shè)備通過串行口進(jìn)行連接。也可以將接收和發(fā)送的程序在同一臺設(shè)備上運行,通過一根交叉線(就是將 TXD數(shù)據(jù)傳輸信號和另一個端口的 RXD 接收數(shù)據(jù)信號相連起來)將兩個串口接在一起。下面就針對上述提到的情況,再舉一個有關(guān)接收和發(fā)送數(shù)據(jù)的程序,通過串口交叉線的連接運行在不同設(shè)備(也可以是同一臺設(shè)備)上的例子。假設(shè)接收程序readtest.c運行在裝有標(biāo)準(zhǔn)Linux的PC機(jī)上,發(fā)送程序writetest.c運行在目標(biāo)板S3C4510B上,兩臺設(shè)備的串口通過交叉線連接在一起。接收程序readtest.c的源碼如下:/* * Institute of Automati
32、on, Chinese Academy of Sciences * File Name: readtest.c * Description: receive data from the serial * Author:Xueyuan Nie * Date: */#include #include #include #include #include #include #include #include #include math.hint spfd;int main() char fname16,hd16,*rbuf; int retv,i,ncount=0; struct termios o
33、ldtio; int realdata=0; spfd=open(/dev/ttyS1,O_RDWR|O_NOCTTY); perror(open /dev/ttyS1); if(spfd0) return -1; tcgetattr(spfd,&oldtio); cfmakeraw(&oldtio); cfsetispeed(&oldtio,B19200); cfsetospeed(&oldtio,B19200); tcsetattr(spfd,TCSANOW,&oldtio); rbuf=hd;printf(ready for receiving data.n); retv=read(sp
34、fd,rbuf,1); if(retv=-1) perror(read); while(*rbuf!=0) ncount+=1; rbuf+; retv=read(spfd,rbuf,1); printf(the number received is %dn,retv); if(retv=-1) perror(read); for(i=0;incount;i+) realdata+=(hdi-48)*pow(10,ncount-i-1); printf(complete receiving the data %dn,realdata); close(spfd); return 0;發(fā)送程序wr
35、itetest.c的源碼如下:/* * Institute of Automation, Chinese Academy of Sciences * File Name: writetest.c * Description: send data to serial * Author:Xueyuan Nie * Date: */#include #include #include #include #include #include #include #include int spfd;int main(int argc, char *argv) char fname16,*sbuf; int
36、sfd,retv,i; struct termios oldtio; spfd=open(/dev/ttyS1,O_RDWR|O_NOCTTY);if(spfd ./writetestready for sending data.the number of char sent is 4這里所舉的例子比較簡單,旨在為讀者介紹最基本的串行通信的步驟,讀者可以此為基礎(chǔ),開發(fā)出滿足自己需求的應(yīng)用程序來。7.4.2 socket編程uClinux本身就是一個網(wǎng)絡(luò)的產(chǎn)物,它可以從網(wǎng)上供人們自由免費的下載,正是通過很多愛好者利用網(wǎng)絡(luò)修改,改善Linux,才得到我們現(xiàn)在的uClinux,所以沒有網(wǎng)絡(luò)可以說就看
37、不到今天的uClinux。因此,在學(xué)習(xí)uClinux的時候,就不能不涉及到網(wǎng)絡(luò),而要掌握在uClinux下設(shè)計用戶應(yīng)用程序,就必須要學(xué)習(xí)有關(guān)uClinux下的網(wǎng)絡(luò)編程。本節(jié)主要講述當(dāng)前在網(wǎng)絡(luò)編程中被廣泛使用的socket。socket一般被翻譯為“套接字”,簡而言之就是網(wǎng)絡(luò)進(jìn)程中的ID。其實網(wǎng)絡(luò)通信,本質(zhì)就是進(jìn)程間的通信,在網(wǎng)絡(luò)中,每個節(jié)點都有唯一一個網(wǎng)絡(luò)地址,即通常說的IP地址,兩個進(jìn)程在通信的時候,必須首先要確定通信雙方的網(wǎng)絡(luò)地址。但是網(wǎng)絡(luò)地址只能確定進(jìn)程所在的PC機(jī),然而同一臺PC可能有好幾個網(wǎng)絡(luò)進(jìn)程,只有網(wǎng)絡(luò)地址是不能夠確定到底是哪個進(jìn)程,所以套接字還需要提供其他信息,那就是端口號,同
38、一臺PC機(jī),一個端口號只能分配給一個進(jìn)程。所以,網(wǎng)絡(luò)地址和端口號結(jié)合在一起,才可以共同確定整個Internet中的一個網(wǎng)絡(luò)進(jìn)程。套接字最常用的有兩種:流式套接字(Stream Socket)和數(shù)據(jù)報套接字(Datagram Socket)。在Linux中,分別稱為”SOCK_STREAM”和”SOCK_DGRAM”。這兩種套接字的區(qū)別在于它們使用不同的協(xié)議。流式套接字使用TCP協(xié)議,數(shù)據(jù)報套接字使用的是UDP協(xié)議。TCP(Transmission Control Protocol)傳輸控制協(xié)議,是TCP/IP體系中的運輸層協(xié)議,是面向連接的,因而可提供可靠的,按序傳送數(shù)據(jù)流,它的可靠是因為它使
39、用三段握手協(xié)議來傳輸數(shù)據(jù),并且采用“重發(fā)機(jī)制”確保數(shù)據(jù)的正確發(fā)送,接收端收到數(shù)據(jù)后要發(fā)出一個肯定確認(rèn),而發(fā)送端必須接收到接收端的確認(rèn)信息后,否則發(fā)送端會重發(fā)數(shù)據(jù)。同時TCP是無錯誤傳遞的,有自己的檢錯和糾錯機(jī)制,使用TCP協(xié)議的套接字是屬于流式套接字。大家熟知的telnet就是使用的流式套接字。UDP(User Datagram Protocol)用戶數(shù)據(jù)報協(xié)議提供無連接的不可靠的服務(wù),在傳送數(shù)據(jù)之前不需要建立連接。遠(yuǎn)地主機(jī)在接收接收到UDP數(shù)據(jù)報后,不需要給出任何應(yīng)答,這樣的話,如果發(fā)送一個數(shù)據(jù)報,可能到達(dá)也可能丟失。如果發(fā)送多個包,到達(dá)接收端的次序可能是顛倒的。數(shù)據(jù)報套接字有時候也稱為“無
40、連接套接字”,大家熟悉的TFTP和NFS使用的就是該協(xié)議。大多數(shù)情況下,如果只是將數(shù)據(jù)包發(fā)送給給定地址的機(jī)器,是不能夠確定到底把數(shù)據(jù)包發(fā)送給機(jī)器哪一個進(jìn)程的,端口號的指定才能夠更明確的指明。適用于通信的用戶應(yīng)用程序可以使用從1到65535的任何一個端口號,并將它分配給端口。這些號通常分成以下幾個范圍段:端口0,不使用。如果傳遞的端口號是0,就會為進(jìn)程分配一個1024到5000之間的一個沒有使用的端口。端口1255,保留給特定的服務(wù),如FTP,遠(yuǎn)程網(wǎng),F(xiàn)INGER等。端口2561023,保留給別的一般服務(wù)如Routing function(路由函數(shù))。端口10244999,可以被任意的客戶機(jī)端口
41、所使用,客戶機(jī)套接字通常會使用這個范圍段的端口。端口500065535,為用戶定義的服務(wù)器端口所使用。如果一個客戶機(jī)需要事先知道服務(wù)器的端口,那么服務(wù)器套接字就應(yīng)該使用這個范圍的端口值。下面結(jié)合一個具體的服務(wù)器端的例子,使讀者熟悉socket編程的方法。/* * Institute of Automation, Chinese Academy of Sciences * File Name: comsamp.c * Description:communication with socket * Author:Xueyuan Nie * Date: */#include #include #in
42、clude #include #include #include #include #include #include #include #include #include /*=* * Defines * *=*/#ifndef TRUE#define FALSE 0#define TRUE 1#endif#ifndef EXIT_FAILURE#define EXIT_FAILURE 1#endif#ifndef EXIT_SUCCESS#define EXIT_SUCCESS 0#endif#ifndef EXT_NO_ERROR#define EXT_NO_ERROR 0#endif#
43、ifndef EXT_ERROR#define EXT_ERROR 1#endif#ifndef INVALID_SOCKET#define INVALID_SOCKET -1#endif#ifndef SOCK_ERR#define SOCK_ERR -1#endif/*=* * Global data local to this module * *=*/typedef int SOCKET;typedef struct ConnectData_tag int port;int waitForStart; SOCKET sFd; /* socket to listen/accept on
44、*/ SOCKET msgFd; /* socket to send/receive messages */ ConnectData;ConnectData *CD;int i=0;int connectionMade = 0; /*=* * Local functions * *=*/void prompt_info(int signumber) char src=this is a test for socketn;int nBytesToSet=strlen(src); send(CD-msgFd, src, nBytesToSet, 0);void init_sigaction(voi
45、d) struct sigaction act; act.sa_handler=prompt_info; act.sa_flags=0; sigemptyset(&act.sa_mask); sigaction(SIGPROF,&act,NULL);void init_time(double t_usec) struct itimerval value; int int_usec; int_usec=(int)(t_usec*); value.it_value.tv_sec=0; value.it_value.tv_usec=int_usec; value.it_interval=value.
46、it_value; setitimer(ITIMER_PROF,&value,NULL);int ModeInit(void) int error = EXT_NO_ERROR; error = ExtInit(CD); if (error != EXT_NO_ERROR) goto EXIT_POINT; printf(Succeeded in creating listening Socket by NXYn);EXIT_POINT: return(error); /* end ModeInit */* Function: ExtInit * Abstract: * Called once at program startup to do any initialization. * A socket is created to lis
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《學(xué)前教育概述》課件
- 單位管理制度集合大合集【人力資源管理篇】十篇
- 單位管理制度分享匯編【員工管理篇】十篇
- 單位管理制度分享大全【人員管理篇】
- 單位管理制度范例選集【員工管理】
- 單位管理制度范例合集【人力資源管理篇】十篇
- 單位管理制度呈現(xiàn)合集【員工管理篇】
- 單位管理制度呈現(xiàn)大合集【人事管理】十篇
- 《微點精析》考向19 文化常識 高考語文一輪復(fù)習(xí)考點微專題訓(xùn)練(原卷+解析)
- 第4單元 民族團(tuán)結(jié)與祖國統(tǒng)一(B卷·能力提升練)(解析版)
- 關(guān)于調(diào)整縣人民醫(yī)院預(yù)算管理委員會成員的通知
- 《工程計量》課件
- 2024年度企業(yè)網(wǎng)絡(luò)搭建及應(yīng)用技能大賽方案
- 2024分娩鎮(zhèn)痛ppt課件完整版
- 教務(wù)處述職報告
- 進(jìn)口公司創(chuàng)業(yè)計劃書
- 2023-2024學(xué)年福建省泉州市晉江市八年級(上)學(xué)期期末數(shù)學(xué)試題(含解析)
- 完整版中職哲學(xué)與人生教案
- 麥凱66表格(完全版)
- 大學(xué)英語新編語言學(xué)教程Chapter 5 Semantics
- AB-PLC-軟件與Windows操作系統(tǒng)兼容列表
評論
0/150
提交評論