通信工程專業(yè)實(shí)習(xí)報(bào)告-2_第1頁
通信工程專業(yè)實(shí)習(xí)報(bào)告-2_第2頁
通信工程專業(yè)實(shí)習(xí)報(bào)告-2_第3頁
通信工程專業(yè)實(shí)習(xí)報(bào)告-2_第4頁
通信工程專業(yè)實(shí)習(xí)報(bào)告-2_第5頁
已閱讀5頁,還剩14頁未讀 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

VIP免費(fèi)下載

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

文檔簡(jiǎn)介

PAGE21目錄1前言………………………71.1實(shí)習(xí)單位簡(jiǎn)介………………………71.2實(shí)習(xí)目的……………72實(shí)習(xí)內(nèi)容…………………83實(shí)習(xí)總結(jié)…………………273.1實(shí)習(xí)中遇到的問題…………………273.2實(shí)習(xí)收獲……………273.3實(shí)習(xí)建議……………283.4實(shí)習(xí)總結(jié)……………281前言1.1實(shí)習(xí)單位簡(jiǎn)介1.2實(shí)習(xí)目的(1)通過實(shí)習(xí)使學(xué)生對(duì)所要設(shè)計(jì)的課題有一個(gè)初步的了解,獲得基本的感性認(rèn)識(shí),加深對(duì)課題的認(rèn)識(shí),學(xué)會(huì)理論聯(lián)系實(shí)際,擴(kuò)大知識(shí)面,引發(fā)設(shè)計(jì)思路,對(duì)設(shè)計(jì)任務(wù)有更明確更深刻的理解;(2)通過撰寫實(shí)習(xí)報(bào)告和課題討論,使學(xué)生學(xué)會(huì)綜合應(yīng)用所學(xué)知識(shí),提高應(yīng)用專業(yè)知識(shí)的能力,并為后續(xù)的畢業(yè)論文和畢業(yè)設(shè)計(jì)做好鋪墊和準(zhǔn)備;(3)通過實(shí)習(xí)能夠開闊學(xué)生的視野,培養(yǎng)學(xué)生分析問題、解決問題的能力,進(jìn)一步了解專業(yè)發(fā)展現(xiàn)狀和前景,為以后的工作方向有更好的定位。2實(shí)習(xí)內(nèi)容2.1文件操作2.1.1UNIX哲學(xué)之一:一切皆為文件Linux文件種類:1.普通文件2.目錄文件3.鏈接文件4.設(shè)備文件2.1.2關(guān)于文件描述符文件描述符是一個(gè)非負(fù)整數(shù),是一個(gè)索引值0STDIN_FILENO1STDOUT_FILENO2STDERR_FILENO包含在<unistd.h>文件描述符的范圍是0~OPEN_MAXLinux下OPEN_MAX為10485762.1.3不帶緩沖的文件I/O操作這次項(xiàng)目中將要用到的文件操作openclosereadwritelseek注:這些函數(shù)是ANSIC的組成部分,但是是POSIX的組成部分2.1.4關(guān)于出錯(cuò)處理由于對(duì)文件的操作由于某種原因,比如文件打開失敗、文件讀、寫失敗,這些出錯(cuò)會(huì)導(dǎo)致程序執(zhí)行失敗解決辦法:加上出錯(cuò)處理,可以在出錯(cuò)時(shí)很明了的發(fā)現(xiàn)錯(cuò)誤出在哪里常用函數(shù):#include<errno.h>#include<stdio.h>voidperror(constchar*s);2.1.5不帶緩沖的文件操作函數(shù)open#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>Intopen(constchar*pathname,intflags);Intopen(constchar*pathname,intflags,mode_tmode);返回值:成功返回新分配的文件描述符,出錯(cuò)返回-1并謳置errno2.1.6參數(shù)的含義pathname是要打開或創(chuàng)建的文件的名字。oflag參數(shù)可用于說明此函數(shù)的多個(gè)選擇項(xiàng)。mode對(duì)于open函數(shù)而言,僅當(dāng)創(chuàng)建新文件時(shí)才使用第三個(gè)參數(shù)。以下三個(gè)常數(shù)中必須指定一個(gè),且僅允講指定一個(gè)(這些常數(shù)定義在<fcntl.h>頭文件中):O_RDONLY只讀打開。O_WRONLY只寫打開。O_RDWR讀、寫打開。2.1.7可選以下可選項(xiàng)可以同時(shí)指定0個(gè)或多個(gè),和必選項(xiàng)按位或來作為flags參數(shù)。O_APPEND每次寫時(shí)都加到文件的尾端。O_CREAT若此文件丌存在則創(chuàng)建它。使用此選擇項(xiàng)時(shí),需同時(shí)說明第三個(gè)參數(shù)mode,用其說明該新文件的存取講可權(quán)位。O_EXCL如果同時(shí)指定了O_CREAT,而文件已經(jīng)存在,則出錯(cuò)。這可測(cè)試一個(gè)文件是否存在,如果不存在則創(chuàng)建此文件成為一個(gè)原子操作。O_TRUNC如果此文件存在,而且為只讀或只寫成功打開,則將其長(zhǎng)度截短為0。2.1.8第三個(gè)參數(shù)第三個(gè)參數(shù)mode指定文件權(quán)限,可以用八進(jìn)制數(shù)表示,比如0644表示-rw-r--r--2.1.9close可用close函數(shù)關(guān)閉一個(gè)打開文件:#include<unistd.h>Intclose(intfiledes);返回:若成功為0,若出錯(cuò)為-1當(dāng)一個(gè)進(jìn)程終止時(shí),它所有的打開文件都由內(nèi)核自動(dòng)關(guān)閉。2.1.10read用read函數(shù)從打開文件中讀數(shù)據(jù)#include<unistd.h>ssize_tread(intfeledes,void*buff,size_tnbytes);返回:讀到的字節(jié)數(shù),若已到文件尾為0,若出錯(cuò)為-1。如read成功,則返回讀到的字節(jié)數(shù)。如已到達(dá)文件的尾端,則返回0。2.1.11write用write函數(shù)向打開文件寫數(shù)據(jù)。#include<unistd.h>ssize_twrite(intfiledes,constvoid*buff,size_tnbytes);返回:若成功為已寫的字節(jié)數(shù),若出錯(cuò)為-1。其返回值通常不參數(shù)nbytes的值不同,否則表示出錯(cuò)。write出錯(cuò)的一個(gè)常見原因是:磁盤已寫滿,或者超過了對(duì)一個(gè)給定進(jìn)程的文件長(zhǎng)度限制。2.1.12lseek#include<sys/types.h>#include<unistd.h>off_tlseek(intfilesdes,off_toffset,intwhence);返回:若成功為新的文件位移,若出錯(cuò)為-1。對(duì)參數(shù)offset的解釋不參數(shù)whence的值有關(guān)。若whence是SEEK_SET,則將該文件的位移量設(shè)置為距文件開始處offset個(gè)字節(jié)。若whence是SEEK_CUR,則將該文件的位移量設(shè)置為其當(dāng)前值加offset,offset可為正或負(fù)。若whence是SEEK_END,則將該文件的位移量設(shè)置為文件長(zhǎng)度加offset,offset可為正或負(fù)。2.1.13標(biāo)準(zhǔn)I/O操作標(biāo)準(zhǔn)i/o庫及其頭文件stdio.h為底層I/O系統(tǒng)調(diào)用提供了一個(gè)通用的接口,這個(gè)庫已經(jīng)成為ANSI標(biāo)準(zhǔn)C的一部分在啟動(dòng)程序時(shí),有三個(gè)文件流是自動(dòng)打開的,他們是stdin,stdout,stderr這三個(gè)文件分別代表著標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤輸出,與底層文件描述符0、1、2對(duì)應(yīng)標(biāo)準(zhǔn)I/O庫提供了大量的復(fù)雜函數(shù)2.1.14fopen函數(shù)函數(shù)原型#include<stdio.h>FILE*fopen(constchar*filename,constchar*mode)返回值:成功返回一個(gè)非空的FILE*指針,失敗時(shí)返回NULL參數(shù):mode可以是以下字符串中的一個(gè)(注意是字符串不是字符)2.1.15fopen“r”:只讀,文件必須已存在“w”:只寫,如果文件不存在則創(chuàng)建,如果文件已存在則把文件長(zhǎng)度截?cái)啵═runcate)為0字節(jié)再重新寫,也就是替換掉原來的的文件內(nèi)容“a”:只能在文件末尾追加數(shù)據(jù),如果文件不存在則創(chuàng)建“r+”:允許讀和寫,文件必須已存在“w+”:允許讀和寫,如果文件不存在則創(chuàng)建,如果文件已存在則把文件長(zhǎng)度截?cái)酁?字節(jié)再重新寫“a+”:允許讀和追加數(shù)據(jù),如果文件不存在則創(chuàng)建2.1.16fcloseIntfclose(FILE*fp);返回值:成功返回0,出錯(cuò)返回EOF并設(shè)置errno2.1.17fread/fwrite原型:#include<stdio.h>size_tfread/fwrite(void*ptr,size_tsize,size_tnmemb,FILE*stream)參數(shù):size:讀取/寫入的記錄大小nmemb:讀取/寫入的記錄數(shù)返回值:成功返回實(shí)際讀入或?qū)懭氲挠涗洈?shù)目失敗返回EOF2.1.18fseek原型:#include<stdio.h>fseeek(FILE*stream,longintoffset,intwhence)其參數(shù)與前面lseek完全一樣2.1.19fgets原型:#include<stdio.h>char*fgets(char*str,intn,FILEstream)說明:fgets函數(shù)從輸入文件流stream里讀取一個(gè)字符串。并把它讀到的字符寫到str指向的字符串里,直到:1、遇到換行符,應(yīng)經(jīng)傳輸了n-1個(gè)字符,或者達(dá)到文件尾。注意:它會(huì)把遇到的換行符也傳遞到接收字符串里,再在結(jié)尾加上一個(gè)表示結(jié)尾的空字節(jié)\0標(biāo)準(zhǔn)I/O的三種緩沖全緩沖如果緩沖區(qū)寫滿了就寫回內(nèi)核。常規(guī)文件通常是全緩沖的。行緩沖如果用戶程序?qū)懙臄?shù)據(jù)中有換行符就把這一行寫回內(nèi)核,或者如果緩沖區(qū)寫滿了就寫回內(nèi)核。標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出對(duì)應(yīng)終端設(shè)備時(shí)通常是行緩沖的。不帶緩沖用戶程序每次調(diào)庫函數(shù)做寫操作都要通過系統(tǒng)調(diào)用寫回內(nèi)核。標(biāo)準(zhǔn)錯(cuò)誤輸出通常是無緩沖的,這樣用戶程序產(chǎn)生的錯(cuò)誤信息可以盡快輸出到設(shè)備。2.2Linux入門知識(shí)2.2.1Linux誕生Linux最初版本是1991年,芬蘭赫爾辛基大學(xué)LinusTorvalds開發(fā)的;隨后在網(wǎng)絡(luò)上發(fā)布Linux0.0.2;到1993年底94年底,Linux1.0誕生;1993年Linux加入GNU并遵循公共版權(quán)許可證(GPL),從而為以后的快速發(fā)展創(chuàng)造了條件;1994Linux的第一個(gè)商業(yè)發(fā)行版Slackware問世;目前Linux的定位——服務(wù)器市場(chǎng)、桌面市場(chǎng)、嵌入式平臺(tái)2.2.2GNU簡(jiǎn)介GNU(GNUIsNotUNIX)是自由軟件基金會(huì)的一個(gè)項(xiàng)目,該項(xiàng)目的目標(biāo)是開發(fā)一個(gè)自由的UNIX版本,這一UNIX版本稱為HURD。GNU項(xiàng)目已經(jīng)開發(fā)了許多高質(zhì)量的編程工具,包括emacs編輯器、著名的GNUC和C++編譯器(gcc和g++),這些編譯器可以在任何計(jì)算機(jī)系統(tǒng)上運(yùn)行。所有的GNU軟件和派生工作均適用GNU通用公共許可證,即GPL(GeneralPublicLicense)。GPL允許軟件作者擁有軟件版權(quán),但授予其他任何人以合法復(fù)制、發(fā)行和修改軟件的權(quán)利。2.2.3什么是自由軟件自由軟件(freesoftware)中的free并不是指免費(fèi),而是指自由。它賦予使用者四種自由。自由之一:有使用軟件的自由。自由之二:有研究該軟件如何運(yùn)作的自由,并且得以改寫該軟件來符合使用者自身的需求。取得該軟件的源碼是達(dá)成此目的前提。自由之三:有重新散布該軟件的自由,所以每個(gè)人都可以有散布自由軟件的自由。自由之四:有改善再利用該軟件的自由,并且可以發(fā)表改寫版供公眾使用,如此一來,整個(gè)社群都可以受惠2.2.4目前l(fā)inux的常見發(fā)行版本2.2.5Linux操作系統(tǒng)的架構(gòu)2.2.6Linux下的常用命令命令的工作原理:用戶在提示符下輸入的名令經(jīng)Shell(名令解釋程序)解釋后傳給內(nèi)核輸入命令應(yīng)注意:1、格式:命令【選項(xiàng)】【參數(shù)】2、區(qū)分大小寫2.2.7Linux的文件命名規(guī)則由Linux文件系統(tǒng)的規(guī)定,文件名和目錄名可以包含以下字符:大寫英文字母A-Z、小寫英文字母a-z、數(shù)字0-9、“@”、“_”等。在文件名和目錄中,不得包括的字符有:*?></;&![]|\‘“(){}。不得以”+“和”-“開頭。Linux中的文件名是大小寫敏感的,也就是說,rainbow和Rainbow代表兩個(gè)丌同的文件。一個(gè)以“.”打頭的文件表明這個(gè)文件是隱藏文件(可以用ls-a查看)。Linux系統(tǒng)中文件名的最大長(zhǎng)度為255個(gè)字符。2.2.8文件權(quán)限文件的權(quán)限,分為三段,分別代表“所有者(u)”、“同組人(g)”、“其它人(o)”的讀(r)、寫(w)、執(zhí)行(x)的權(quán)限。對(duì)普通文件而言,“r”代表可以閱讀文件內(nèi)容,“w”代表可以修改或刪除文件內(nèi)容,"x"代表可以將文件作為命令來執(zhí)行(同時(shí)需要r權(quán)限)。修改文件權(quán)限:命令——chmod(最常用)

例:[root@localhost~]#chmod664a.txt2.2.9Linux下開發(fā)工具——viVi是“Visualinterface”的簡(jiǎn)稱Unix、Linux下的程序開發(fā)工具Unix、Linux下修改配置文件Vi可以執(zhí)行輸入、刪除、查找、替換、塊操作等眾多文本操作Vi不是一個(gè)排版程序、它只是一個(gè)文本編輯程序Vi是全屏幕文本編輯程序,它沒有菜單,只有命令現(xiàn)常用的為vi的升級(jí)版vim2.2.10Vi的安裝使用Vim的安裝:sudoapt-getinstallvimVim的使用:vi<文件名>——?jiǎng)?chuàng)建(如果沒有創(chuàng)建)并進(jìn)入文件例vihello.cvi編輯器有三種工作模式:命令行模式:剛進(jìn)入文件即為此模式,此模式下可以移動(dòng)鼠標(biāo)、通過鍵盤輸入一些命令完成查找、復(fù)制等功能,或進(jìn)入底行模式、插入模式插入模式:在命令行模式下輸入i或a進(jìn)入(最常用為i),只有在命令行模式下才能字符輸入,按【Esc】返回到命令行模式底行模式:在該模式下,用戶可以將文件保存或退出。這一模式下的命令都以“:”開始2.2.11Linux編譯器gcc及其使用編譯如C、C++、ObjectC、Java、Fortran、Pasca等多種語言一個(gè)交叉平臺(tái)編譯器,適合在嵌入式領(lǐng)域的開發(fā)編譯全稱為GNUCompilerCollection,GNU項(xiàng)目中符合ANSIC標(biāo)準(zhǔn)的編譯系統(tǒng)gcc可以使程序員靈活地控制編譯過程。編譯過程一般可以分為四個(gè)階段,每個(gè)階段分別調(diào)用不同的工具迚行處理使用格式:gcc【選項(xiàng)】源文件名連接:gcctest.o-otest一般情況下直接由源程序生成可執(zhí)行文件:1、gcctest.c即可生成以a.out命名的可執(zhí)行文件2、gcctest.c–otest(或其他名字)即生成具有自己命名的可執(zhí)行文件執(zhí)行:./可執(zhí)行文件名2.2.12MakefileMakefile需要按照某種語法進(jìn)行編寫,其中說明了如何編譯各個(gè)源文件并連接生成可執(zhí)行文件,并定義了源文件之間的依賴關(guān)系。當(dāng)修改了其中某個(gè)源文件時(shí),如果其他源文件依賴于該文件,則也要重新編譯所有依賴該文件的源文件。Makefile文件的建立:通常采用vimakefile,編輯完成后保存即生成makefile文件一個(gè)Makefile文件主要含有一系列的規(guī)則,每條規(guī)則包含以下內(nèi)容:–一個(gè)目標(biāo)(target),即make最終需要?jiǎng)?chuàng)建的文件,如可執(zhí)行文件和目標(biāo)文件;目標(biāo)也可以是要執(zhí)行的動(dòng)作,如“clean”。–一個(gè)或多個(gè)依賴文件(dependency)列表,通常是編譯目標(biāo)文件所需要的其他文件。–一系列命今(command),是make執(zhí)行的動(dòng)作,通常是把指定的相關(guān)文件編譯成目標(biāo)文件的編譯命令,每個(gè)命令占一行,且每個(gè)命令行的起始字符必須為TAB字符。Makefile的執(zhí)行保存并退出makefile文件后,輸入make命令如果要使用其他文件作為makefile,則可利用類似下面的make命令選項(xiàng)指定makefile文件:$make-fMakefile.debug2.2.13Make的工作過程首先make按順序讀取makefile中的規(guī)則然后檢查該規(guī)則中的依賴文件與目標(biāo)文件的時(shí)間戳哪個(gè)更新如果目標(biāo)文件的時(shí)問戳比依賴文件還早,就按規(guī)則中定義的命令更新目標(biāo)文件。如果該規(guī)則中的依賴文件又是其他規(guī)則中的目標(biāo)文件,那么依照規(guī)則鏈不斷執(zhí)行這個(gè)過程,直到Makefile文件的結(jié)束,至少可以找到一個(gè)不是規(guī)則生成的最終依賴文件,獲得此文件的時(shí)間戳然后從下到上依照規(guī)則鏈執(zhí)行目標(biāo)文件的時(shí)間戳比此文件時(shí)間戳舊的規(guī)則,直到最頂層的規(guī)則2.2.14Makefile的優(yōu)點(diǎn)通過以上的分析過程,可以看到make的優(yōu)點(diǎn),因?yàn)?o目標(biāo)文件依賴.c源文件,源碼文件里一個(gè)簡(jiǎn)單改變都會(huì)造成那個(gè)文件被重新編譯,并根據(jù)規(guī)則鏈依次由下到上執(zhí)行編譯過程,直到最終的可執(zhí)行文件被重新連接。例如,當(dāng)改變一個(gè)頭文件的時(shí)候,由于所有的依賴關(guān)系都在Makefile里,因此不再需要記住依賴此頭文件的所有源碼文件,make可以自動(dòng)的重新編譯所有那些因依賴這個(gè)頭文件而改變了的源碼文件,如果需要,再進(jìn)行重新連接2.3單向鏈表的實(shí)現(xiàn)2.3.1malloc和freemalloc是在堆上分配空間,并返回指向該段存儲(chǔ)空間的地址#include<stdlib.h>void*malloc(size_tsize);voidfree(void*pointer);使用:int*p;p=malloc(100);if(p==NULL){…}2.3.2鏈表在物理內(nèi)存上的存儲(chǔ)head指針是鏈表的頭指針,指向第一個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)的next指針域指向下一個(gè)節(jié)點(diǎn),最后一個(gè)節(jié)點(diǎn)的next指針域?yàn)镹ULL,在圖中用0表示。機(jī)構(gòu)圖:2.3.3鏈表的特點(diǎn)每個(gè)鏈表有一個(gè)頭指針,通過頭指針可以找到第一個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都可以通過指針域找到它的后繼,最后一個(gè)節(jié)點(diǎn)的指針域?yàn)镹ULL,表示沒有后繼。數(shù)組在內(nèi)存中是連續(xù)存放的,而鏈表在內(nèi)存中的布局是丌規(guī)則的,我們知道訪問某個(gè)數(shù)組元素b[n]時(shí)可以通過基地址+n×每個(gè)元素的字節(jié)數(shù)得到它地址,或者說數(shù)組支持隨機(jī)訪問,而鏈表是不支持隨機(jī)訪問的,只能通過前一個(gè)元素的指針域得知后一個(gè)元素的地址,因此只能從頭指針開始順序訪問各節(jié)點(diǎn)。2.3.4鏈表節(jié)點(diǎn)的基本格式#defineMAX16#defineMAXLINE1024typedefstructclient*mylink;structclient{charuser[MAX];charcode[MAX];intfd;mylinknext;};2.3.5鏈表的插入2.4多進(jìn)程編程2.4.1進(jìn)程與程序程序(program)是存放在磁盤文件中的可執(zhí)行文件。進(jìn)程:程序的執(zhí)行實(shí)例被稱為進(jìn)程(process)。進(jìn)程ID:每個(gè)linux進(jìn)程都一定有一個(gè)唯一的數(shù)字標(biāo)識(shí)符,稱為進(jìn)程ID(processID)。進(jìn)程ID總是一非負(fù)整數(shù)。2.4.2進(jìn)程的三種狀態(tài)運(yùn)行狀態(tài)(Running):占用處理機(jī)資源;處亍此狀態(tài)的迚程的數(shù)目小于等于CPU的數(shù)目。在沒有其他進(jìn)程可以執(zhí)行時(shí)(如所有進(jìn)程都在阻塞狀態(tài)),通常會(huì)自動(dòng)執(zhí)行系統(tǒng)的idle進(jìn)程(相當(dāng)于空操作)。就緒狀態(tài)(Ready):進(jìn)程已獲得除處理機(jī)外的所需資源,等待分配處理機(jī)資源;只要分配CPU就可執(zhí)行??梢园炊鄠€(gè)優(yōu)先級(jí)來劃分隊(duì)列,如:時(shí)間片用完->低優(yōu),I/O完成->中優(yōu),頁面調(diào)入完成->高優(yōu)阻塞狀態(tài)(Blocked):由于進(jìn)程等待某種條件(如I/O操作或進(jìn)程同步),在條件滿足之前無法繼續(xù)執(zhí)行。該事件發(fā)生前即使把處理機(jī)分配給該進(jìn)程,也無法運(yùn)行。如:等待I/O操作的完成。2.4.3項(xiàng)目中使用多進(jìn)程的原因本項(xiàng)目多進(jìn)程只應(yīng)用在了客戶端原因是在客戶端信息的發(fā)送和接收都是互相獨(dú)立的,即并發(fā)執(zhí)行,采用兩個(gè)進(jìn)程一個(gè)進(jìn)程負(fù)責(zé)發(fā)送消息,一個(gè)進(jìn)程負(fù)責(zé)接收消息,可以順利的實(shí)現(xiàn)信息的發(fā)收本項(xiàng)目中服務(wù)器也可以才用多進(jìn)程,即用多個(gè)進(jìn)程分別處理所連接的各個(gè)用戶的信息,但由于使用了select,所以省去了多進(jìn)程2.4.4進(jìn)程控制#include<sys/types.h>#include<unistd.h>pid_tfork(void);fork調(diào)用失敗則返回-12.4.5fork用法一個(gè)父進(jìn)程希望復(fù)制自己,使父、子進(jìn)程同時(shí)執(zhí)行不同的代碼段。——網(wǎng)絡(luò)服務(wù)器的經(jīng)典代碼一個(gè)進(jìn)程要執(zhí)行一個(gè)不同的程序?!@對(duì)shell是常見的情況。在這種情況下,子進(jìn)程在從fork返回后立即調(diào)用exec函數(shù)。2.4.6fork發(fā)生了什么Fork產(chǎn)生的子進(jìn)程是對(duì)父進(jìn)程完整的復(fù)制但fork之后返回兩個(gè)值,即一次調(diào)用,兩個(gè)返回其中的一個(gè)返回值是子程序的id號(hào),一個(gè)返回為0 》當(dāng)返回值大于0,即為子進(jìn)程ID時(shí),父進(jìn)程執(zhí)行》當(dāng)返回值等于0,子進(jìn)程執(zhí)行通過上述原理實(shí)現(xiàn)父進(jìn)程、子進(jìn)程執(zhí)行不同的代碼段2.4.7fork.c2.4.8代碼分析父進(jìn)程初始化。父進(jìn)程調(diào)用fork,這是一個(gè)系統(tǒng)調(diào)用,因此進(jìn)入內(nèi)核。內(nèi)核根據(jù)父進(jìn)程復(fù)制出一個(gè)子進(jìn)程,父進(jìn)程和子進(jìn)程的PCB信息相同,用戶態(tài)代碼和數(shù)據(jù)也相同。因此,子進(jìn)程現(xiàn)在的狀態(tài)看起來和父迚程一樣,做完了初始化,剛調(diào)用了fork迚入內(nèi)核,還沒有從內(nèi)核返回。現(xiàn)在有兩個(gè)一模一樣的進(jìn)程看起來都調(diào)用了fork進(jìn)入內(nèi)核等待從內(nèi)核返回(實(shí)際上fork只調(diào)用了一次),此外系統(tǒng)中還有很多別的進(jìn)程也等待從內(nèi)核返回。是父進(jìn)程先返回還是子進(jìn)程先返回,還是這兩個(gè)進(jìn)程都等待,先去調(diào)度執(zhí)行別的進(jìn)程,這都不一定,取決于內(nèi)核的調(diào)度算法。如果某個(gè)時(shí)刻父進(jìn)程被調(diào)度執(zhí)行了,從內(nèi)核返回后就從fork函數(shù)返回,保存在變量pid中的返回值是子進(jìn)程的id,是一個(gè)大于0的整數(shù),因此執(zhí)下面的else分支,然后執(zhí)行for循環(huán),打印“Thisistheparent\n”三次之后終止。如果某個(gè)時(shí)刻子進(jìn)程被調(diào)度執(zhí)行了,從內(nèi)核返回后就從fork函數(shù)返回,保存在變量pid中的返回值是0,因此執(zhí)行下面的if(pid==0)分支,然后執(zhí)行for循環(huán),打印“Thisisthechild\n”六次之后終止。fork調(diào)用把父進(jìn)程的數(shù)據(jù)復(fù)制一份給子進(jìn)程,但此后二者互不影響,在這個(gè)例子中,fork調(diào)用之后父進(jìn)程和子進(jìn)程的變量message和n被賦予不同的值,互不影響。父進(jìn)程每打印一條消息就睡眠1秒,這時(shí)內(nèi)核調(diào)度別的進(jìn)程執(zhí)行,在1秒這樣長(zhǎng)的間隙里(對(duì)于計(jì)算機(jī)來說1秒很長(zhǎng)了)子進(jìn)程很有可能被調(diào)度到。同樣地,子進(jìn)程每打印一條消息就睡眠1秒,在這1秒期間父進(jìn)程也很有可能被調(diào)度到。所以程序運(yùn)行的結(jié)果基本上是父子進(jìn)程交替打印,但這也不是一定的,取決于系統(tǒng)中其它進(jìn)程的運(yùn)行情況和內(nèi)核的調(diào)度算法,如果系統(tǒng)中其它進(jìn)程非常繁忙則有可能觀察到不同的結(jié)果。另外,也可以把sleep(1);去掉看程序的運(yùn)行結(jié)果如何2.4.9終止進(jìn)程正常終止:–從main返回–調(diào)用exit–調(diào)用_exit異常終止–調(diào)用abort–由一個(gè)信號(hào)終止2.4.10正常終止exit和_exit函數(shù)用于正常終止一個(gè)程序#include<stdlib.h>voidexit(intstatus);exit則先執(zhí)行一些清除處理.然后進(jìn)入內(nèi)核清除操作包括調(diào)用執(zhí)行各終止處理程序,關(guān)閉所有標(biāo)準(zhǔn)I/O流#include<unistd.h>void_exit(intstatus);_exit立即進(jìn)入內(nèi)核2.4.11異常終止信號(hào)終止信號(hào)是在軟件層次上的對(duì)中斷機(jī)制的一種模擬原理上,一個(gè)進(jìn)程收到一個(gè)信號(hào)與處理器收到一個(gè)中斷請(qǐng)求是一樣的信號(hào)是異步的常用的用來終止進(jìn)程的函數(shù):#include<signal.h>#include<sys/types.h>intkill(pid_tpid,intsig)例kill(myid,SIGINT);2.5聊天室項(xiàng)目簡(jiǎn)介2.5.1項(xiàng)目說明基本架構(gòu):C/S架構(gòu)何為C/S架構(gòu)?即服務(wù)器(server)/客戶端(client)結(jié)構(gòu)2.5.2項(xiàng)目總體講解基本功能:ClientA登陸聊天服務(wù)器前,需要注冊(cè)自己的ID和密碼注冊(cè)成功后,ClientA就可以通過自己的ID和密碼登陸聊天服務(wù)器多個(gè)ClientX可以同時(shí)登陸聊天服務(wù)器之后,與其他用戶進(jìn)行通訊聊天ClientA成功登陸后可以查看當(dāng)前聊天室內(nèi)其他在線用戶ClientxClientA可以選擇發(fā)消息給某個(gè)特定的ClientX,即”悄悄話”功能ClientA可以選擇發(fā)消息全部的在線用戶,即”群發(fā)消息”功能ClientA在退出時(shí)需要保存聊天記錄Server端維護(hù)一個(gè)所有登陸用戶的聊天會(huì)的記錄文件,以便備查C語言開發(fā)的思路:C語言是一種面向過程的語言,即傳統(tǒng)的結(jié)構(gòu)化程序設(shè)計(jì)(StructuredProgrammingSP)方法在數(shù)據(jù)處理過程中,采用的是自頂向下、分而治之的方法,將整個(gè)程序按功能劃分為幾個(gè)可獨(dú)立編程的子過程模塊,每一子模塊完成指定的子任務(wù),最后,主過程通過調(diào)用各子過程完來成全部處理工作2.5.3根據(jù)架構(gòu)劃分2.5.4用戶錄入從標(biāo)準(zhǔn)輸入接收用戶的錄入,提示用戶輸入相應(yīng)信息可以使用函數(shù)fgets2.5.5信息打包確立自己的通信協(xié)議,即每次傳遞的信息包含哪些這里的協(xié)議可以是一個(gè)結(jié)構(gòu)體,打包即將用戶錄入添加到結(jié)構(gòu)體中2.5.6信息發(fā)送、接收讀、寫套接字注:在讀寫時(shí)注意類型轉(zhuǎn)換2.5.7信息顯示取出包內(nèi)信息,并輸出2.5.8保存消息將消息寫入到定好的文件中2.5.9傳遞消息采用TCP/ip協(xié)議,采用網(wǎng)絡(luò)編程實(shí)現(xiàn)客戶端與服務(wù)器的通信2.5.10服務(wù)器解析消息服務(wù)器收到數(shù)據(jù)后,將數(shù)據(jù)解析,根據(jù)不同的模式執(zhí)行不同的操作處理包括:鏈表操作、信息轉(zhuǎn)發(fā)、信息回應(yīng)等2.5.11實(shí)習(xí)目標(biāo)了解linux下C開發(fā)平臺(tái)學(xué)會(huì)使用gnu開發(fā)工具了解C語言開發(fā)流程,提高c語言編程能力對(duì)所做項(xiàng)目有一定了解,熟悉本項(xiàng)目的開發(fā)思路及所用知識(shí),培養(yǎng)軟件開發(fā)興趣2.6網(wǎng)絡(luò)編程2.6.1字節(jié)序由于丌同的計(jì)算機(jī)系統(tǒng)采用不同的字節(jié)序存儲(chǔ)數(shù)據(jù),同樣一個(gè)4字節(jié)的32位整數(shù),在內(nèi)存中存儲(chǔ)的方式就不同.字節(jié)序分為小端字節(jié)序(LittleEndian)和大端字節(jié)序(BigEndian),Intel處理器大多數(shù)使用小端字節(jié)序,Motorola處理器大多數(shù)使用大端(BigEndian)字節(jié)序;2.6.2網(wǎng)絡(luò)字節(jié)序TCP/IP協(xié)議規(guī)定,網(wǎng)絡(luò)數(shù)據(jù)流應(yīng)采用大端字節(jié)序,即低地址高字節(jié).為使網(wǎng)絡(luò)程序具有可移植性,使同樣的C代碼在大端和小端計(jì)算機(jī)上編譯后都能正常運(yùn)行,可以調(diào)用以下庫函數(shù)做網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序的轉(zhuǎn)換2.6.3網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序轉(zhuǎn)換#include<arpa/inet.h>uint32_thtonl(uint32_thostlong);uint16_thtons(uint16_thostshort);uint32_tntohl(uint32_tnetlong);uint16_tntohs(uint16_tnetshort);這些函數(shù)名很好記,h表示host,n表示network,l表示32位長(zhǎng)整數(shù),s表示16位短整數(shù)。例如htonl表示將32位的長(zhǎng)整數(shù)從主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序,例如將IP地址轉(zhuǎn)換后準(zhǔn)備發(fā)送。如果主機(jī)是小端字節(jié)序,這些函數(shù)將參數(shù)做相應(yīng)的大小端轉(zhuǎn)換然后返回,如果主機(jī)是大端字節(jié)序,這些函數(shù)不做轉(zhuǎn)換,將參數(shù)原封不動(dòng)地返回。2.6.4基于數(shù)據(jù)流的socket編程流程2.6.5socketIntsocket(intfamily,inttype,intprotocol);socket()打開一個(gè)網(wǎng)絡(luò)通訊端口,如果成功的話,就像open()一樣返回一個(gè)文件描述符,應(yīng)用程序可以像讀寫文件一樣用read/write在網(wǎng)絡(luò)上收發(fā)數(shù)據(jù),如果socket()調(diào)用出錯(cuò)則返回-1。對(duì)于IPv4,family參數(shù)指定為AF_INET即為遵循UNIX網(wǎng)絡(luò)套接字。對(duì)于TCP協(xié)議,type參數(shù)指定為SOCK_STREAM,表示面向流的傳輸協(xié)議。(如果是UDP協(xié)議,則type參數(shù)指定為SOCK_DGRAM,表示面向數(shù)據(jù)報(bào)的傳輸協(xié)議。)protocol參數(shù)的介紹從略,指定為0即可。2.6.6bindIntbind(intsockfd,conststructsockaddr*myaddr,socklen_taddrlen);bind()成功返回0,失敗返回-1。服務(wù)器程序所監(jiān)聽的網(wǎng)絡(luò)地址和端口號(hào)通常是固定不變的,客戶端程序得知服務(wù)器程序的地址和端口號(hào)后就可以向服務(wù)器發(fā)起連接,因此服務(wù)器需要調(diào)用bind綁定一個(gè)固定的網(wǎng)絡(luò)地址和端口號(hào)。bind()的作用是將參數(shù)sockfd和myaddr綁定在一起,使sockfd這個(gè)用于網(wǎng)絡(luò)通訊的文件描述符監(jiān)聽myaddr所描述的地址和端口號(hào)。2.6.7sockaddr初始化bzero(&servaddr,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_addr.s_addr=htonl(INADDR_ANY);servaddr.sin_port=htons(SERV_PORT);首先將整個(gè)結(jié)構(gòu)體清零,然后設(shè)置地址類型為AF_INET,網(wǎng)絡(luò)地址為INADDR_ANY,這個(gè)宏表示本地的任意IP地址,因?yàn)榉?wù)器可能有多個(gè)網(wǎng)卡,每個(gè)網(wǎng)卡也可能綁定多個(gè)IP地址,這樣設(shè)置可以在所有的IP地址上監(jiān)聽,直到不某個(gè)客戶端建立了連接時(shí)才確定下來到底用哪個(gè)IP地址,端口號(hào)為SERV_PORT,我們定義為97322.6.8listenintlisten(intsockfd,intbacklog);listen()成功返回0,失敗返回-1。典型的服務(wù)器程序可以同時(shí)服務(wù)于多個(gè)客戶端,當(dāng)有客戶端發(fā)起連接時(shí),服務(wù)器調(diào)用的accept()返回并接受這個(gè)連接,如果有大量的客戶端發(fā)起連接而服務(wù)器來不及處理,尚未accept的客戶端就處于連接等待狀態(tài),listen()聲明sockfd處于監(jiān)聽狀態(tài),并且最多允許有backlog個(gè)客戶端處于連接待狀態(tài),如果接收到更多的連接請(qǐng)求就忽略。2.6.9select定義函數(shù)intselect(intn,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtimeval*timeout);函數(shù)說明select()用來等待文件描述符狀態(tài)的改變。參數(shù)n代表最大的文件描述符加1,參數(shù)readfds、writefds和exceptfds稱為描述符組,是用來回傳該描述符的讀,寫或例外的狀況。2.6.10Select的操作select底下的宏提供了處理這三種描述詞組的方式:FD_CLR(intfd,fd_set*set);用來清除描述詞組set中相關(guān)fd的位FD_ISSET(intfd,fd_set*set);用來測(cè)試描述詞組set中相關(guān)fd的位是否為真FD_SET(intfd,fd_set*set);用來設(shè)置描述詞組set中相關(guān)fd的位FD_ZERO(fd_set*set);用來清除描述詞組set的全部位參數(shù)timeout為結(jié)構(gòu)timeval,用來設(shè)置select()的等待時(shí)間,其結(jié)構(gòu)定義如下structtimeval{time_ttv_sec;time_ttv_usec;};如果參數(shù)timeout設(shè)為NULL則表示select()沒有timeout。2.6.11返回值執(zhí)行成功則返回文件描述符狀態(tài)已改變的個(gè)數(shù)2.6.12acceptIntaccept(intsockfd,structsockaddr*cliaddr,socklen_t*addrlen);三方握手完成后,服務(wù)器調(diào)用accept()接受連接,如果服務(wù)器調(diào)用accept()時(shí)還沒有客戶端的連接請(qǐng)求,就阻塞等待直到有客戶端連接上來。cliaddr是一個(gè)傳出參數(shù),accept()返回時(shí)傳出客戶端的地址和端口號(hào)。addrlen參數(shù)是一個(gè)傳入傳出參數(shù)(value-resultargument),傳入的是調(diào)用者提供的緩沖區(qū)cliaddr的長(zhǎng)度以避免緩沖區(qū)溢出問題,傳出的是客戶端地址結(jié)構(gòu)體的實(shí)際長(zhǎng)度(有可能沒有占滿調(diào)用者提供的緩沖區(qū))。如果給cliaddr參數(shù)傳NULL,表示不關(guān)心客戶端的地址。2.6.13客戶端程序Intconnect(intsockfd,conststructsockaddr*servaddr,socklen_taddrlen);connect()成功返回0,出錯(cuò)返回-1??蛻舳诵枰{(diào)用connect()連接服務(wù)器,connect和bind的參數(shù)形式一致,區(qū)別在于bind的參數(shù)是自己的地址,而connect的參數(shù)是對(duì)方的地址。3實(shí)習(xí)總結(jié)3.1實(shí)習(xí)中遇到的問題Q1:什么是多文件處理,如何操作?這個(gè)問題是我此次實(shí)習(xí)時(shí)一上來就遇到的問題,因?yàn)槔蠋熤v過,我也遇到過,當(dāng)我們寫程序時(shí),若只在一個(gè)文件中寫,寫的代碼可能會(huì)有幾百上千行,維護(hù)起來特別麻煩。所以要用到多文件管理,可是,如何調(diào)用文件,如何定義,在主函數(shù)中如何聲明,這是我所不知道的,我也是問了老師兩遍,才弄清楚。多文件,要在主函數(shù)中聲明你要用的函數(shù),并在分文件中定義。其實(shí)就這么簡(jiǎn)單,必要的頭文件如“stdafx.h”一定要包含進(jìn)去就可以了。Q2:怎么讀入文件,怎么輸出到文件?這個(gè)是我自己看書解決的,我的思路很明確,把文件當(dāng)做數(shù)據(jù)庫,我輸入的數(shù)據(jù)寫到里面,回來我再調(diào)用,每個(gè)函數(shù)都會(huì)把文件中的內(nèi)容讀入到結(jié)構(gòu)體數(shù)組中,然后我在查找,修改,刪除,排序等,最后完成操作后,若有變動(dòng),則再次寫入到文件中,這樣下次再使用時(shí),就是用戶改過的內(nèi)容。這里比較重要的是要知道文件中有多少條記錄,用到了feof函數(shù)以及fopen,fread,fwrite,fclose函數(shù)。feof是查找文件否到了末尾,其余的就不用說了。Q3:“容錯(cuò)”處理?這個(gè)是比較讓人頭疼的事,你得想到各種情況,比如,你讓用戶輸入數(shù)字來選擇相應(yīng)功能,但是用戶輸入了字母,這個(gè)時(shí)候就要提示用戶輸入錯(cuò)誤,并再次出現(xiàn)菜單,這就需要循環(huán)語句,但是我遇到了死循環(huán),就是因?yàn)槊看斡脩糨斎胍粋€(gè)選項(xiàng)后,會(huì)有敲下回車,這個(gè)回車會(huì)在文件緩沖區(qū)中,下一次scanf()語句執(zhí)行時(shí),會(huì)直接得到這個(gè)回車,造成死循環(huán)。因此要寫一條語句“吃掉”這個(gè)回車。3.2實(shí)習(xí)收獲

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論