版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第16章嵌入式LinuxC語(yǔ)言標(biāo)準(zhǔn)庫(kù)雖然C語(yǔ)言的功能非常強(qiáng)大,但它事實(shí)上是一種非常精練的語(yǔ)言,C的簡(jiǎn)單性和兼容性使得它的應(yīng)用非常廣泛,大到巨型機(jī)的操作系統(tǒng),小至電子表,都可以很好的運(yùn)行。在不同的環(huán)境中,C的運(yùn)行方式可能有所差異。在獨(dú)立運(yùn)行(如在電子表等設(shè)備中)的條件下只能實(shí)現(xiàn)語(yǔ)言本身所提供的功能,一些如輸入輸出、內(nèi)存管理、字符操作等常見(jiàn)功能并沒(méi)有包含在這種運(yùn)行方式中。而在非獨(dú)立運(yùn)行的條件下,可以通過(guò)調(diào)用庫(kù)提供的函數(shù),實(shí)現(xiàn)C所沒(méi)有提供的功能。在眾多的庫(kù)當(dāng)中,使用頻率最高的當(dāng)屬C標(biāo)準(zhǔn)庫(kù),以至于很多的程序員認(rèn)為標(biāo)準(zhǔn)庫(kù)是語(yǔ)言的一部分,一些幾乎在每個(gè)程序中都會(huì)出現(xiàn)的函數(shù),如printf、scanf等,其實(shí)都是由標(biāo)準(zhǔn)庫(kù)提供的函數(shù),而不是語(yǔ)言本身的特性。16.1Glibc簡(jiǎn)介Glibc(GNUCLibrary)是GNU發(fā)布的C標(biāo)準(zhǔn)庫(kù),也即C的運(yùn)行庫(kù),是Linux系統(tǒng)中最底層的應(yīng)用程序開(kāi)發(fā)接口(API),幾乎其他的庫(kù)都會(huì)依賴與Glibc。在Glibc中不僅封裝了操作系統(tǒng)提供的各種系統(tǒng)服務(wù),而且也提供了許多其他一些必要功能的實(shí)現(xiàn)。16.2字符測(cè)試和數(shù)據(jù)轉(zhuǎn)換函數(shù)16.2.1字符測(cè)試函數(shù)<ctype.h>中的函數(shù)支持單個(gè)字符的典型操作,例如確定一個(gè)字符a是否為小寫,在很多C語(yǔ)言的教科書(shū)中都采用了如下的表達(dá)式:(‘a(chǎn)’<c=&&c<=’z’)這樣寫的程序可讀性很差,而且這種方式只在ASCII字符集中有效,在別的字符集中結(jié)果是未知的。16.2.2數(shù)據(jù)轉(zhuǎn)換函數(shù)這類函數(shù)的主要功能是完成將字符或字符串轉(zhuǎn)換為不同類型的數(shù),主要定義在頭文件<stdlib.h>中。16.3基本I/O函數(shù)Linux針對(duì)輸入輸出(I/O)的函數(shù)很直觀,可以總結(jié)為四個(gè)方面:打開(kāi)、讀取、寫入和關(guān)閉,對(duì)應(yīng)的有四個(gè)系統(tǒng)調(diào)用,它們是:open()、read()、write()、close()。16.3.1open()函數(shù)新的文件描述符是從open()函數(shù)得到的。首先回顧該函數(shù)的原型:intopen(constchar*pathname,intflags,mode_tmode);它的三個(gè)參數(shù)的含義如下:參數(shù)pathname: 為C字符串,表示打開(kāi)的文件名;參數(shù)intflags: 為一個(gè)或多個(gè)標(biāo)志,部分可用的標(biāo)志請(qǐng)讀者參見(jiàn)表16-5;參數(shù)mode_tmode:產(chǎn)生文件的權(quán)限模式,可以使用八進(jìn)制數(shù)來(lái)表示新文件的權(quán)限,也可采用<sys/stat.h>中定義的符號(hào)常量,如表16-6所示。當(dāng)打開(kāi)已有文件時(shí),將忽略這個(gè)參數(shù)。16.3.2close()函數(shù)當(dāng)使用完文件可以使用close()關(guān)閉該文件,close()會(huì)讓緩沖區(qū)中的數(shù)據(jù)寫回磁盤,并釋放該文件所占用的資源。該函數(shù)的原型如下:intclose(intfd);參數(shù)fd為文件描述符,由open()等函數(shù)所返回的有效的文件描述符。若文件順利關(guān)閉則返回0,發(fā)生錯(cuò)誤則返回-1,并置errno。通常文件在關(guān)閉時(shí)出錯(cuò)是不常見(jiàn)的,但也不是不可能的情況,特別是關(guān)閉通過(guò)網(wǎng)絡(luò)訪問(wèn)的文件來(lái)說(shuō)就會(huì)出現(xiàn)這種情況。16.3.3read()函數(shù)和write()函數(shù)輸入輸出的操作最終是通過(guò)read()和write()這兩個(gè)函數(shù)來(lái)完成的,它們的形式和使用方法十分相近,因而放在一起介紹。它們的函數(shù)原型為:ssize_tread(intfd,void*buf,size_tcount);ssize_rwrite(intfd,constvoid*buf,size_tcount);這兩個(gè)函數(shù)的參數(shù)都有:參數(shù)fd,表示已打開(kāi)文件的文件描述符;參數(shù)buf,為指向緩沖區(qū)的指針;參數(shù)count,為要讀取或?qū)懭氲淖止?jié)數(shù)。16.3.4其他函數(shù)其他常用的基本I/O函數(shù)還有表16-7所列的這些。16.4標(biāo)準(zhǔn)I/O函數(shù)基于文件流的標(biāo)準(zhǔn)I/O函數(shù)與前面所提的基本I/O函數(shù)最大的區(qū)別就是對(duì)緩沖區(qū)的利用。低級(jí)I/O函數(shù)在很多應(yīng)用中是不帶緩沖區(qū)的,程序員可以直接操作硬件,這樣為開(kāi)發(fā)驅(qū)動(dòng)等底層的系統(tǒng)應(yīng)用提供了方便。而在高層次的應(yīng)用中,不帶緩沖區(qū)的I/O操作效率往往較低,而由用戶自行維護(hù)緩沖區(qū)不僅繁瑣,而且容易出錯(cuò)。因此ANSI制定了一系列基于流緩沖的標(biāo)準(zhǔn)I/O函數(shù),如fopen()、printf()、scanf()等。16.4.1fopen()函數(shù)打開(kāi)文件有三個(gè)標(biāo)準(zhǔn)函數(shù),分別為:fopen(),fdopen()和freopen()。它們的函數(shù)原型如下所示:#include<stdio.h>FILE*fopen(constchar*path,constchar*mode);FILE*fdopen(intfd,constchar*mode);FILE*freopen(constchar*path,constchar*mode,FILE*stream);它們以不同的模式打開(kāi)文件,并返回一個(gè)指向文件流的FILE指針,此后對(duì)文件讀寫都是通過(guò)這個(gè)FILE指針來(lái)進(jìn)行。16.4.2fclose()函數(shù)關(guān)閉文件指針的函數(shù)為fclose,它的函數(shù)原型是:intfclose(FILE*stream);這時(shí)緩沖區(qū)的數(shù)據(jù)將寫入文件中,并釋放系統(tǒng)所提供的文件資源。如果只是希望將緩沖區(qū)中的數(shù)據(jù)寫入文件,但因?yàn)榭赡芎竺孢€要用到文件指針,不希望這個(gè)時(shí)候關(guān)閉它,可以使用另外一個(gè)函數(shù):fflush(),函數(shù)原型如下:intfflush(FILE*stream);16.4.3fread()和fwrite()函數(shù)當(dāng)利用fopen()函數(shù)打開(kāi)文件后,就可對(duì)文件流進(jìn)行讀寫操作了。根據(jù)每次讀寫的數(shù)據(jù)量的不同,可分為塊讀寫、字符讀寫和字符串讀寫三類函數(shù),其中后兩類函數(shù)主要是針對(duì)文本文件的。下面主要介紹針對(duì)塊讀寫的fread()和fwrite()函數(shù)。fread()函數(shù)和fwrite()函數(shù)的原型是:size_tfread(void*ptr,size_tsize,size_tnmemb,FILE*stream);size_tfwrite(void*ptr,size_tsize,size_tnmemb,FILE*stream);16.4.4printf()和scanf()函數(shù)相信所有知道C語(yǔ)言的讀者都十分熟悉這兩個(gè)函數(shù),在著名的HelloWorld程序中就有printf()函數(shù)。這類函數(shù)稱為格式化輸入輸出函數(shù),可以指定輸入輸出的具體格式,而不像前面所介紹的fread()和fwrite()函數(shù)只能讀寫原始的數(shù)據(jù)。標(biāo)準(zhǔn)庫(kù)針對(duì)不同的實(shí)際應(yīng)用提供了一些print()函數(shù)和scanf()函數(shù)的變體,如下所列的這些:intprintf(constchar*format,…)intfprintf(FILE*fp,constchar*format,…)intsprintf(char*buf,constchar*format,…)intscanf(constchar*format,…)intfscanf(FILE*fp,constchar*format,…)intsscanf(char*buf,constchar*format,…)16.4.5其他函數(shù)在實(shí)際應(yīng)用中,標(biāo)準(zhǔn)I/O函數(shù)是比較常用的,筆者在表16-11中簡(jiǎn)要列出了一些函數(shù)的原型和功能,讀者在需要用到時(shí),可通過(guò)man手冊(cè)查詢這些函數(shù)的詳細(xì)用法。16.5內(nèi)存配置及字符串處理函數(shù)內(nèi)存的使用是程序設(shè)計(jì)中需要仔細(xì)考慮的重要因素。特別是在嵌入式系統(tǒng)中,內(nèi)存資源是十分寶貴的,內(nèi)存管理的好壞直接影響到最終程序的執(zhí)行效率及穩(wěn)定性。動(dòng)態(tài)內(nèi)存的使用可以總結(jié)為三個(gè)步驟:(1)申請(qǐng):告訴系統(tǒng)需要多大的內(nèi)存空間,系統(tǒng)準(zhǔn)備好一整塊內(nèi)存空間后,將這段內(nèi)存的首地址返回給調(diào)用者;(2)使用:對(duì)內(nèi)存空間中的數(shù)據(jù)進(jìn)行復(fù)制、比較、檢索、清除等工作;(3)釋放:告訴系統(tǒng)不再需要這段內(nèi)存空間,系統(tǒng)將其回收。本節(jié)將按照這三個(gè)步驟介紹標(biāo)準(zhǔn)庫(kù)中提供的內(nèi)存配置函數(shù)。其中字符串處理函數(shù)的實(shí)質(zhì)也是對(duì)內(nèi)存進(jìn)行操作,因此在下面一并作介紹。16.5.1內(nèi)存分配函數(shù)程序可以使用malloc()函數(shù)和calloc()函數(shù)來(lái)動(dòng)態(tài)分配內(nèi)存,函數(shù)原型是:#include<stdlib.h>void*malloc(size_tsize);void*calloc(size_tnmemb,size_tsize);16.5.2memXXX函數(shù)常見(jiàn)的內(nèi)存操作主要有復(fù)制、查找、清除和設(shè)置,標(biāo)準(zhǔn)庫(kù)提供了幾個(gè)函數(shù)為操作任意的內(nèi)存塊提供了底層服務(wù)。1.內(nèi)存設(shè)置函數(shù):memset()memset()函數(shù)將參數(shù)val的值復(fù)制到buf的前count個(gè)字節(jié)中去。在前面的例程中,我們就用到這個(gè)函數(shù)清除內(nèi)存塊,下面的代碼總結(jié)了這樣的清除過(guò)程:void*p=malloc(sizeof(char)*count);if(p!=NULL)memset(p,0,count*sizeof(char));2.內(nèi)存復(fù)制函數(shù):memcpy()、memmove()、memccpy()memcpy()函數(shù)從src處復(fù)制count字節(jié)的數(shù)據(jù)到dest,但是他不處理內(nèi)存區(qū)域的重疊問(wèn)題。memmove()函數(shù)與memcpy函數(shù)類似,也是從src處復(fù)制count字節(jié)的數(shù)據(jù)到dest。但是它處理重疊內(nèi)存區(qū)域問(wèn)題。memcpy()函數(shù)從src處復(fù)制count字節(jié)的數(shù)據(jù)到dest,但當(dāng)遇到以下情況中的一種是即停止復(fù)制:數(shù)據(jù)中包含val,則將val復(fù)制到dest后,就停止復(fù)制;數(shù)據(jù)中不包含val,則復(fù)制完count字節(jié)的數(shù)據(jù)之后,就停止復(fù)制。3.內(nèi)存塊比較函數(shù)memcmp()memcmp()函數(shù)比較任意類型的兩個(gè)數(shù)據(jù)緩沖區(qū)中的count個(gè)字節(jié)的內(nèi)容,如果buf1小于、等于或大于buf2,將分別返回負(fù)數(shù)、零或正數(shù),如下面的例程所示4.搜索字節(jié)值函數(shù):memchr()memchr()函數(shù)從緩沖區(qū)頭開(kāi)始搜尋buf所指的內(nèi)存空間的前count個(gè)字節(jié),知道發(fā)現(xiàn)第一個(gè)值為val的字節(jié),返回指向該值在緩沖區(qū)中的位置的指針,如果沒(méi)有找到則返回0。16.5.3strXXX函數(shù)16.5.4釋放內(nèi)存的函數(shù)動(dòng)態(tài)分配的內(nèi)存在使用完畢后一定要及時(shí)的釋放,完成這個(gè)操作的函數(shù)是free()。這個(gè)函數(shù)唯一的參數(shù)是一個(gè)指針:#include<stdlib.h>voidfree(void*ptr);16.5.5動(dòng)態(tài)內(nèi)存分配的實(shí)例下面是一個(gè)實(shí)現(xiàn)單向鏈表插入、查找和遍歷方法的例子,其中實(shí)現(xiàn)插入操作的函數(shù)是Insert()、實(shí)現(xiàn)獲取操作的函數(shù)是get(),通過(guò)順序遍歷鏈表查找或獲取某個(gè)節(jié)點(diǎn)。16.6日期時(shí)間函數(shù)在Shell中,我們可以通過(guò)date命令獲得系統(tǒng)的日期和時(shí)間,而在程序中,我們往往需要有更為精確的時(shí)間表示,如計(jì)算程序的執(zhí)行時(shí)間就需要得到秒級(jí)甚至毫妙級(jí)的計(jì)時(shí)信息。本節(jié)將討論Linux系統(tǒng)中表示時(shí)間的方法,以及如何在程序中獲得時(shí)間和計(jì)算時(shí)間。16.6.1時(shí)間的定義同現(xiàn)實(shí)世界一樣,在Linux系統(tǒng)中也存在若干關(guān)于時(shí)間和日期的定義,不同的時(shí)間函數(shù)基于不同的時(shí)間定義,要用好這些函數(shù)有必要先了解相關(guān)的背景知識(shí)。這里我為讀者列舉了一些常見(jiàn)的定義,它們是:UTC(CoordinatedUniversalTime):協(xié)調(diào)世界時(shí),又稱為世界標(biāo)準(zhǔn)時(shí)間,也就是大家所熟知的格林威治標(biāo)準(zhǔn)時(shí)間(GreenwichMeanTime,GMT)。CalendarTime:日歷時(shí)間,是用“從一個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)到此時(shí)的時(shí)間經(jīng)過(guò)的秒數(shù)”來(lái)表示的時(shí)間。epoch:時(shí)間點(diǎn),即UTC的1970年1月1日00:00:00。linux中系統(tǒng)時(shí)間中采用的是從epoch開(kāi)始計(jì)算的時(shí)間,其系統(tǒng)調(diào)用time()函數(shù)得到的就是從epoch到當(dāng)前時(shí)刻的秒計(jì)數(shù);clocktick:時(shí)鐘計(jì)時(shí)單元(有的資料中稱做時(shí)鐘滴答次數(shù)),一個(gè)時(shí)鐘計(jì)時(shí)單元的時(shí)間長(zhǎng)短是由CPU控制的。16.6.2日歷時(shí)間標(biāo)準(zhǔn)庫(kù)的<time.h>頭文件中定義了時(shí)間和日期的結(jié)構(gòu)和方法,其中最重要的數(shù)據(jù)類型是time_t類型,用time_t表示的時(shí)間(日歷時(shí)間)是從epoch時(shí)間點(diǎn)到此時(shí)的秒數(shù)。在<time.h>中,我們可以看到time_t是一個(gè)長(zhǎng)整型數(shù):typedeflongtime_t;/*時(shí)間值*/16.6.3時(shí)鐘計(jì)時(shí)單元如果要計(jì)算某個(gè)算法的執(zhí)行時(shí)間,使用日歷時(shí)間顯然是不夠精確的,因?yàn)樗荒芫_到秒級(jí)。獲得更高精度的時(shí)間則要使用clock()函數(shù),該函數(shù)原型如下:#include<time.h>clock_tclock(void);16.6.4格式化日期和時(shí)間structtm中的成員包含了所有的時(shí)間信息,程序員完全可以親自編寫代碼,按自己需要的格式輸出日期和時(shí)間。但標(biāo)準(zhǔn)庫(kù)提供了功能強(qiáng)大的格式化函數(shù),可以滿足大多數(shù)情況下的顯示需求,減輕了程序員的工作量。可以通過(guò)asctime()函數(shù)和ctime()函數(shù)將時(shí)間以固定的格式顯示出來(lái),下面是兩個(gè)函數(shù)的原型:#include<time.h>char*asctime(conststructtm*timeptr);char*ctime(consttime_t*timer);16.6.5自定義時(shí)間格式函數(shù)strftime()可以將時(shí)間格式化為我們想要的格式。它的原型如下:size_tstrftime(char*strDest,size_tmaxsize,constchar*format,conststructtm*timeptr);該函數(shù)類似與sprintf()函數(shù),它的參數(shù)介紹如下:參數(shù)strDest:保存已格式化的字符串的緩沖區(qū);參數(shù)maxsize:緩沖區(qū)的大??;參數(shù)format:格式化字符串;參數(shù)timeptr:指向structtm的指針,表示將要被格式化的時(shí)間。16.7其他函數(shù)16.7.1錯(cuò)誤處理函數(shù)良好的程序不僅應(yīng)該確保程序的正確執(zhí)行,而且當(dāng)程序出現(xiàn)錯(cuò)誤時(shí)能有效的提供出錯(cuò)信息,便于用戶查詢。C語(yǔ)言本身缺乏異常和錯(cuò)誤處理機(jī)制,標(biāo)準(zhǔn)C庫(kù)為一個(gè)運(yùn)行中的進(jìn)程提供了一個(gè)預(yù)定義的變量,稱為errno。在前面的幾節(jié)中我們可以發(fā)現(xiàn)標(biāo)準(zhǔn)庫(kù)函數(shù)在報(bào)告錯(cuò)誤時(shí)基本都采用了兩種方法:函數(shù)返回錯(cuò)誤代碼或成功代碼,如果是錯(cuò)誤代碼,則代碼本身可用于指出何處出錯(cuò);函數(shù)返回特定值(或值范圍)以指明錯(cuò)誤,且設(shè)置全局變量errno以指明問(wèn)題可能的原因。1.perror()函數(shù)perror()函數(shù)用來(lái)將上一個(gè)函數(shù)發(fā)生錯(cuò)誤的原因輸出到標(biāo)準(zhǔn)錯(cuò)誤(STDERR)。該函數(shù)的聲明如下:#include<stdio.h>voidperror(constchar*s);2.strerror()函數(shù)strerror()只返回錯(cuò)誤代碼所對(duì)應(yīng)的描述字符串指針,不直接輸出。它的函數(shù)聲明如下:#include<stdio.h>char*strerror(interrnum);16.7.2系統(tǒng)日志函數(shù)Linux下提供日志服務(wù)的程序叫syslogd,它的任務(wù)就是記錄各種由其他程序發(fā)給它的消息。在文
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 智能城市環(huán)境保護(hù)管理方案
- 中小學(xué)心理健康月活動(dòng)方案
- 公共交通安全項(xiàng)目實(shí)施方案
- 房地產(chǎn)開(kāi)發(fā)公司客戶糾紛處理流程
- 愛(ài)心傳承責(zé)任繼承協(xié)議
- 《企業(yè)員工薪酬福利管理協(xié)議》
- 市政道路交安設(shè)施優(yōu)化方案
- 外賣平臺(tái)突發(fā)送餐延誤應(yīng)急預(yù)案
- 非營(yíng)利組織免疫接種倡導(dǎo)制度
- 農(nóng)產(chǎn)品溯源SAAS管理方案
- 銀監(jiān)會(huì)英語(yǔ)考試六篇英語(yǔ)閱讀理解和一篇完形填空
- 初中數(shù)學(xué)人教七年級(jí)上冊(cè)(2023年更新) 一元一次方程合并同類項(xiàng)解一元一次方程教案
- 血液透析中心各項(xiàng)制度
- 聽(tīng)覺(jué)理解能力評(píng)估記錄表
- 食品企業(yè)生產(chǎn)部門年終總結(jié)報(bào)告精編ppt
- DBJ50∕T-338-2019 輕質(zhì)隔墻條板應(yīng)用技術(shù)標(biāo)準(zhǔn)
- 通用版:溫濕度記錄表
- 《計(jì)算機(jī)視覺(jué)》教學(xué)大綱
- 小清新個(gè)人簡(jiǎn)歷求職動(dòng)態(tài)PPT模板
- 胸痹心痛PPT課件
- 天然藥物化學(xué)重點(diǎn)筆記總結(jié)
評(píng)論
0/150
提交評(píng)論