亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Apache APR可移植運行庫簡介(4)

2019-11-17 04:37:27
字體:
來源:轉載
供稿:網友
 
1.5.3錯誤處理
大型的系統程序的錯誤處理是十分重要的,APR作為一個通用庫接口集合具體的說明了使用APR時如何進行錯誤處理。
1.5.3.1 錯誤碼定義
錯誤處理的第一步就是定義返回碼,包括“錯誤碼和狀態碼分類”。APR的函數大部分都返回int類型作為返回碼的,不過為了更明確易懂,APR在apr_errno.h中使用typedef int apr_status_t將其進行了重新定義。它在一起定義的還有apr所用的所有錯誤碼和狀態碼。假如一個APR函數絕對的不可能出錯,那么此時就答應不返回ap_status_t錯誤碼,只需要返回void類型即可。不過APR中大部分的函數都是返回apr_status_t值。
APR中的返回碼的定義并不是隨意的,沒有規則的。相反,APR給出了定義返回碼的嚴格的規定。APR中根據返回信息的相似性將它們分為七大類,分別定義如下所示:
#define APR_OS_ERRSPACE_SIZE    50000
#define APR_SUCCESS                            0
#define APR_OS_START_ERROR              20000
#define APR_OS_START_STATUS             (APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE)
#define APR_OS_START_USERERR    (APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE)
#define APR_OS_START_CANONERR (APR_OS_START_USERERR /
                                         + (APR_OS_ERRSPACE_SIZE * 10))
#define APR_OS_START_EAIERR              (APR_OS_START_CANONERR + APR_OS_ERRSPACE_SIZE)
#define APR_OS_START_SYSERR             (APR_OS_START_EAIERR + APR_OS_ERRSPACE_SIZE)
正常情況下,函數返回APR_SUCCESS作為成功標志。否則根據情況返回上述類別中的任一種。每一大類的返回信息又可以具體細分為實際的值。在Apache中,每一類返回信息所答應的數目由APR_OS_ERRSPACE_SIZE決定,目前為50000,APR_OS_CANONERR為500000。另一方面,APR_OS_START_ERROR、APR_OS_START_STATUS、APR_OS_START_USEERR、APR_OS_START_CANONERR、APR_OS_START_EAIERR和APR_OS_START_SYSERR,它們每個都擁有自己獨自的偏移量,具體偏移量的值以及含義如下表描述:
錯誤名稱
含義
0
每個平臺都有0,但是都沒有實際的定義,0又的確是一個errno value的offset,但是它是“匿名的”,它不像EEXIST那樣有著可以“自描述”的名字。
APR_OS_START_ERROR
該定義是平臺相關的,不同平臺的值可能不同,它定義了APR中所答應的錯誤碼的起始偏移量,即20000,這意味著所有的錯誤碼值不能低于20000。至于錯誤碼,它可以是導致APR函數失敗的任何原因。在這個范圍內定義的所有錯誤碼形式都必須是APR_E*格式,比如APR_ENOSTAT、APR_ENOSOCKET、APR_ENOPOOL。該類別中答應定義最多50000種錯誤碼。
APR_OS_START_STATUS
該定義也是平臺相關的,它定義了APR中所答應的返回狀態值的起始偏移量,即APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE,即70000開始。不過需要注重的是,狀態值并不能表示失敗還是成功。假如要表示返回成功,必須使用APR_SUCCESS返回。在這個范圍的狀態碼形式都必須是APR_*格式,比如APR_DETACH、APR_INCHILD。
APR_OS_START_USERERR
APR_OS_START_USEERR
該定義也是平臺相關的。當用戶使用APR庫的時候,假如它希望定義APR返回碼之外的其余的自定義返回碼,那么這些返回碼必須從APR_OS_START_USEERR開始,即APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE,即從120000開始。
APR_OS_START_CANONERR
APR_OS_START_CANONERR is where APR versions of errno values are defined on systems which don't have the corresponding errno.對于這類返回碼的定義通常如下:
#ifdef EEXIST
#define APR_EEXIST EEXIST
#else
#define APR_EEXIST         (APR_OS_START_CANONERR + 2)
#endif
APR_OS_START_EAIERR
在使用socket編程的時候假如調用getaddrinfo()函數,該函數會返回一系列的以EAI_*開始的錯誤碼,比如EAI_AGAIN,EAI_FAIL等等。這些不規則的錯誤碼最終都要轉換為APR中對應的返回碼。這些轉換碼從APR_OS_START_EAIERR開始,最多答應50000個(當然事實上肯定沒有這么多)。
APR_OS_START_SYSERR
由于APR必須保持跨平臺的特性,因此不同的操作系統平臺肯定有自己所獨有的一些返回碼,這些返回碼不具有移植性,是與平臺相關的。盡管如此,他們也必須轉換為APR內部返回碼。APR_OS_START_SYSERR指定了定義這些不具有移植性返回碼的起始偏移,為720000,容量為50000。
各返回信息起始便移量及其區別可以用下圖描述:
從上表可以看出,所有的APR定義的返回碼都是從APR_OS_START_ERROR開始,那么0到APR_OS_START_ERROR之間將近20000個空位豈不是浪費了?事實上這部分空間并沒有浪費。我們后面所描述的”native error”會占用這部分的空隙。
Apache中的返回碼如下表所示:
錯誤名稱
含義
APR_ENOSTAT
APR無法對一個文件執行stat操作
20001
APR_ENOPOOL
APR沒有提供內存池來執行內存分配操作
20002
APR_EBADDATE
APR給出了一個無效的日期
20003
APR_EINVALSOCK
APR給出了一個無效的socket
20004
APR_ENOPROC
APR沒有給定一個進程的結構
20005
APR_ENOTIME
APR沒有給定一個時間結構
20006
APR_ENODIR
APR沒有給定一個目錄結構
20007
APR_ENOLOCK
APR沒有給定一個互斥鎖結構
20008
APR_ENOPOLL
APR沒有給定一個Poll結構
20009
APR_ENOSOCKET
APR沒有給定一個socket
20010
APR_ENOTHREAD
APR沒有給定一個線程結構
20011
APR_ENOTHDKEY
APR沒有給定一個線程Key結構
20012
APR_ENOSHMAVAIL
APR中沒有更多的可用共享內存
20013
APR_EDSOOPEN
APR中無法打開一個DSO對象
20014
APR_EGENERAL
APR中的通常的錯誤
20015
APR_EBADip
描述的IP地址錯誤
20016
APR_EBADMASK
描述的IP地址掩碼錯誤
20017
APR_ESYMNOTFOUND
無法查找到請求symbo
20018
APR_INCHILD
程序正在執行子進程
70001
APR_INPARENT
程序正在執行父進程
70002
APR_DETACH
線程從主線程中被分離出來
70003
APR_NOTDETACH
線程尚未從主線程中分離出來
70004
APR_CHILD_DONE
子進程已經執行完畢
70005
APR_CHILD_NOTDONE
子進程尚未執行完畢
70006
APR_TIMEUP
執行操作超時
70007
APR_INCOMPLETE
The Operation was incomplete although some processing was performed and the results are partially valid
70008
APR_BADCH
Getopt函數查找到一個不在選項字符串中的選項
70012
APR_BADARG
Getopt發現一個選項缺少參數,而在選項字符串中該選項必須指定
70013
APR_EOF
APR已經到達文件的末尾
70014
APR_NOTFOUND
APR在poll結構中無法發現socket
70015
APR_ANONYMOUS
APR正在使用匿名的共享內存
70019
APR_FILEBASED
APR正在使用文件名作為共享內存的key
70020
APR_KEYBASED
APR正在使用共享key作為共享內存的key
70021
APR_EINIT
 
70022
APR_ENOTIMPL
在該平臺上,該APR函數尚未實現
70023
APR_EMISMATCH
輸入的兩個密碼不匹配
70024
APR_EABSOLUTE
給定的路徑值是絕對路徑
70019
APR_ERELATIVE
給定的路徑是相對路徑
70020
APR_EINCOMPLETE
給定的路徑既不是相對路徑也不是絕對路徑
70021
APR_EABOVEROOT
給定的路徑在跟路徑上
70022
APR_EBUSY
給定的互斥鎖正忙,已經被鎖定
70025
APR_EPROC_UNKNOWN
該進程無法被APR所識別
70024
有一點必須明確的是返回碼并不一定總是錯誤碼。假如你的函數返回多個值,它們中的每一個都意味著執行成功,但是它們的值卻不一樣,或者你的函數僅僅返回成功或者失敗兩種情況,那么APR中通常仍然會返回一個apr_status_t值。
在第一種情況下,即假如執行成功具有多種狀態,那么可以為每一個狀態定義一個APR返回狀態碼,典型的例子就是apr_proc_wait函數,它用于等待子進程結束,它會返回三種情況:APR_CHILDDONE表示子進程已經執行完畢;APR_CHILDNOTDONE表示子進程尚未執行完畢;錯誤碼則意味著等待子進程失敗。對于前兩種返回不能稱之為失敗,它們都是成功返回,只是返回狀態不一樣而已,為此APR中定義兩個狀態碼表示返回狀態,記住不是錯誤碼。
對于第二種情況,即執行成功后僅有一種狀態,那么假如執行成功,APR中通常返回APR_SUCCESS,而不是什么都不返回;假如執行失敗,則定義新的APR狀態碼來描述這種失敗。比如apr_compare_users函數,它返回APR_SUCCESS表示失敗,同時定義APR_EMISMATCH和其余錯誤碼表示失敗。
根據上面的原則,你就會發現APR中的函數很少有返回類型為void或者void*的。更多的都是返回apr_status_t。
APR中所有的錯誤碼的定義在apr_errno.h中都可以找到。當APR函數中發生錯誤的時候,這些函數必須返回一個錯誤碼。假如這些錯誤是在系統調用錯誤,那么APR將使用系統調用返回的錯誤碼errno作為返回碼原樣返回,比如:
if(open(fname,oflags,0777)<0)
    return errno;
對于系統調用,除了直接返回系統錯誤碼之外,另外一種策略就是使用新的APR錯誤碼替代原始的系統錯誤碼,比如:
if (CreateFile(fname, oflags, sharemod, NULL,
      createflags, attributes, 0) == INVALID_HANDLE_VALUE
return (GetLAstError() + APR_OS_START_SYSERR);
上面的兩個例子在不同的平臺上實現了相同的功能。顯而易見,即使在兩個平臺上存在的潛在問題都是一樣的,那么也會導致返回截然不同的錯誤碼。不過對于這兩種情況APR都是支持的。事實上APR的觀點是,當一個錯誤發生的時候,程序通常是記錄該錯誤并且繼續往下執行,默認情況下它并不會去嘗試解決發生的錯誤。不過這并不意味著APR根本不捕捉錯誤并且提供解決方案。事實上,在后面的部分我們會看到APR中如何處理錯誤。
1.5.3.2 返回碼信息映射
大部分情況下,狀態碼主要用于系統內部使用,因此它的含義隱晦,對于用戶影響不是非凡的大,但是錯誤碼則不一樣。用戶更多的是希望系統返回足夠多的信息以便直到發生錯誤的原因,從而進行跟蹤和調試。因此這種情況下,假如假如僅僅返回一個整數給用戶,用戶可能會莫名其妙,一頭霧水。最好的方法就是能夠將該返回碼所代表的實際的含義以字符串的形式返回出去。事實上大部分操作系統平臺都提供了這種對應函數,比如stderror。APR中使用apr_strerror函數將上述的返回碼轉換為實際的字符串信息:
APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
                                 apr_size_t bufsize)
statcode是需要轉換的返回碼,轉換后的字符串保存在緩沖區buf中,函數所答應的字符串的長度由bufsize控制。
對于不同的返回碼,APR采取不同的轉換策略:
■ 系統錯誤碼(statcode< APR_OS_START_ERROR)
這類錯誤碼APR中稱之為”native error”,即這些錯誤碼并不是APR定義的,而是系統返回的。比如open函數的返回碼就應該算”native error”。對于這類錯誤碼,APR的處理就是直接使用stderror_r函數返回系統提示的消息,假如找不到該系統錯誤碼,返回”APR does not understand this error code”信息。之所以不使用stderror是因為stderror不是線程安全的。假如平臺能夠實現線程安全的stderror函數,比如Solaris, OS/390,那么你也可以使用stderror,否則不要這么做。
這類”native error”通常小于20000,因此它們會使用APR_OS_START_ERROR之前的空隙。
■ APR定義返回碼(APR_OS_START_ERROR <= statcode <= APR_OS_START_USERERR)
這類返回碼通常是APR定義并使用的,因此APR本身必須能夠維持這些返回碼和返回信息之間的對應關系。APR中采取的是最原始的”switch/case”方法來對傳入的返回碼逐一進行判定:
static char *apr_error_string(apr_status_t statcode)
{
    switch (statcode) {
    case APR_ENOPOOL:
        return "A new pool could not be created.";
    case APR_EBADDATE:
        return "An invalid date has been provided";
    case APR_EINVALSOCK:
        return "An invalid socket was returned";
    case APR_ENOPROC:
        return "No process was provided and one was required.";
    ......
}
因此假如需要了解APR_ENOPOOL返回碼的確切含義,只需要使用語句printf(“%s”,apr_error_string(APR_ENOPOOL))即可。
■ APR自定義返回碼(APR_OS_START_USERERR <= statcode <= APR_OS_START_EAIERR)
■ EAI錯誤碼(APR_OS_START_EAIERR <= statcode <= APR_OS_START_SYSERR)
該范圍內的錯誤碼主要對應getaddrinfo函數返回的EAI_*系列錯誤碼。因此在對statcode進行調整后直接調用gai_strerror()返回對應的信息即。假如操作系統不支持gai_strerror函數,那么直接返回"APR does not understand this error code"。
■ 平臺相關錯誤碼(APR_OS_START_SYSERR <= statcode)
這類錯誤碼總是與平臺相關的,APR返回碼與實際的錯誤碼之間保持下面的關系:
APR_Error = APR_OS_START_SYSERR + 系統錯誤碼
由于這類錯誤碼與平臺相關,因此處理也是與平臺相關的。
1)、對于WINDOW平臺而言,所有的Window平臺所特有的錯誤碼及實際含義都保存在數組gaErrorList中:
static const struct {
    apr_status_t code;
    const char *msg;
} gaErrorList[] = {
    WSAEINTR,           "Interrupted system call",
    WSAEBADF,           "Bad file number",
    WSAEACCES,          "Permission denied",
    ……
}
因此處理過程就很簡單,一旦獲取了錯誤碼比如WSAEACCES后通過查找gaErrorList數組就可以獲取其實際含義。返回后的字符串使用FormatMessage格式化輸出。
2)、對于Unix平臺而言主要是由于linux在調用諸如gethostbyname或者gethostbyaddr等函數時候會返回一些特有的錯誤碼,比如HOST_NOT_FOUND、NO_ADDRESS、NO_DATA、NO_RECOVERY、TRY_AGAIN等。Linux專門提供了hstrerror函數獲取這些錯誤碼的實際含義。因此對這類錯誤碼的處理假如系統實現了hstrerror,則調用hstrerror處理,否則使用最原始的switch/case進行處理:
switch(err) {
    case HOST_NOT_FOUND:
        msg = "Unknown host";
        break;
    case NO_ADDRESS:
        msg = "No address for host";
        break;
    case NO_DATA:
        msg = "No address for host";
        break;
    default:
        msg = "Unrecognized resolver error";
    }
3)、另一種需要考慮的就是OS/2。由于OS/2不是我們的重點,此處不再描述。需要了解的可以參考源代碼。
1.5.3.3 錯誤捕捉策略
對于APR自定義錯誤碼,APR可以直接通過返回值獲取,而對于系統調用錯誤碼,Apache則必須使用系統函數來獲取。對于所有的操作系統平臺,Apache提供了四個函數捕捉系統相關錯誤碼:
apr_get_os_error()
apr_set_os_error(e)
apr_get_netos_error()
apr_set_netos_error(e)
前兩個分別用于或者和設置系統錯誤碼,而后者則主要用于獲取和設置網絡錯誤碼,之所以進行這種區分,是因為大部分操作系統平臺上獲取系統錯誤碼和獲取網絡錯誤碼的方法不同。在Window平臺上獲取錯誤碼主要是調用函數GetLastError和SetLastError,對于網絡錯誤的獲取則是WSAGetLastError和WSASetLastError。Unix下則與之不同。下表列出了各個平臺對應的處理:
 
apr_get_os_error
apr_set_os_error(e)
apr_get_netos_error
apr_set_netos_error(e)
Window
GetLastError
SetLastError(e)
WSAGetLastError
WSASetLastError
Unix
(errno)
(errno = (e))
(errno)
(errno = (e))
Netware
(errno)
(errno = (e))
WSAGetLastError
WSASetLastError
Apache中大部分的操作都是將返回碼與指定的返回碼進行比較,然后根據比較結果做出進一步的操作。不過Apache中對于錯誤碼的比較并不是使用最簡單的格式,比如“if(s==APR_EBUSY)”,取而代之的是,Apache中使用一些簡單的宏來執行比較任務,通常格式為:
APR_STATUS_IS_XXX
XXX通常是錯誤碼APR_XXX的XXX部分,比如APR_STATUS_IS_EOF、APR_STATUS_IS_BADCH等等。而這些宏的實現非常簡單,一看就明白:
#define APR_STATUS_IS_BADCH(s)          ((s) == APR_BADCH)
APR_errno.h中的大部分內容就是這種宏定義,每一個錯誤碼都會對應這樣一個宏定義。
另外系統中還定義了兩個宏分別用于實現APR返回碼與操作系統本地碼的轉換:
#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR)
#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR)
前者用于將操作系統平臺相關的返回碼轉換為APR定義的返回碼,而后者則相反,用于將APR定義的返回碼轉換為操作系統平臺相關碼。
由于APR是可移植的,這樣就可能碰到這樣一個問題:不同平臺錯誤碼的不一致。如何處理呢?APR給我們提供了2種策略:
a)對于所有的操作系統平臺都返回相同的錯誤碼
這種策略的缺點是從平臺相關錯誤碼轉換為通用錯誤碼比較耗費時間,而且大多數情況下,開發人員需要的僅僅是輸出一個錯誤字符串而已。假如我們將所有的錯誤碼轉換為一個通用的公共的錯誤碼子集,那么為了輸出一個錯誤字符串信息,我們必須完成四個步驟:
    make syscall that fails
        convert to common error code                 step 1
        return common error code
            check for success
            call error output function               step 2
                convert back to system error         step 3
                output error string                  step 4
相比而言,這是一個比較耗時的步驟。通過使用使用平臺相關錯誤碼的話,那么整個步驟可以壓縮為只有兩步:
    make syscall that fails
        return error code
            check for success
            call error output function               step 1
                output error string                  step 2
這種策略的第二個可能造成的問題就是錯誤碼的損耗,這種問題源自各個平臺錯誤碼數目的不均衡性。比如Windows和OS/2操作系統定義了成百上千錯誤碼,而POSIX才定義了50錯誤碼,假如都轉換為規范統一的錯誤碼,勢必會有Window平臺錯誤碼含義的丟失(錯誤碼多的比如Window平臺),或者可能得不到擁有真正含義的錯誤碼(錯誤碼少的,比如POSIX)。
b) 返回平臺相關錯誤碼,假如需要將它轉換為APR通用錯誤碼
第二種策略中,程序的執行路線往往要根據函數返回錯誤碼來定,這么做的缺點就是把這些工作推給了程序員。執行流程如:
make syscall that fails

        convert to common error code
        return common error code
            decide execution based on common error code
假如考慮到將平臺相關的錯誤碼轉換為通用的錯誤碼,那么上面的代碼段可以修改為如下:
make syscall that fails
        return error code
            convert to common error code (using ap_canonical_error)
            decide execution based on common error code
1.5.4宏處理
Apache目前能夠支持五個大種類的運行平臺,包括Window、OS/2、BeOS、Unix、NetWare,而Window又可以細分為Window98、Window2000等等。Unix則又可以進一步細分,包括Linux,ScoUNIX,DARWIN等等。為了能夠讓Apache運行在如此之多的操作系統平臺上,Apache在源代碼中增加了許多的編譯開關。
舉個例子,比如utime.h頭文件的包含問題。因為文件在Linux(gcc)下面和Windows(cl)下所處的C Library目錄不同。包含的處理辦法就不一樣。可能需要這樣寫才能完全正確的包含。
#if HAVE_UTIME_H                   //---- 假如有utime.h 文件
#    ifdef WIN32                   //-----假如是win32環境   
#        include <sys/utime.h>    //-----包含sys/utime.h
#    endif
#    ifdef LINUX                   //---- 假如是Linux環境
#        include <utime.h>        //---- 包含utime.h   
#    endif
#else                              //--- 假如沒有utime.h定義出需要的結構   
struct utimbuf
{
long actime;
long modtime;
};
#endif
Apache處理與之類似。根據編譯環境的不同來編譯不同的代碼。 這樣的#define的區隔,主要就是為了區隔不同平臺的不同細微區別。有的區別也許是某些常量沒有定義,有些區別是某些函數不存在。
Apache中使用的很多的編譯開關是各個操作系統或者各個編譯器已經確定的,通過這些預定義就可以很輕易的區分使用的操作系統平臺,比如__osf__和__alpha是DEC的OSF/1 1.3操作系統中的定義,因此假如某個函數只能運行于OSF/1 1.3中,則可以使用下面的編譯處理代碼:
#ifdefine __osf____aplpa
        //調用函數
#endif
下面的表格中給出了目前大部分的操作系統以及編譯器的編譯開關:

機器硬件     生產商            操作系統                     編譯器         能夠識別的編譯其開關變量
AMIGA        Commodore          AMIGA-OS (AMIGADOS)           GNU           amiga or AMIGA, __GNUC__, maybe MC68000 or AMIGA3000
any          any                UNIX                          GNU           unix, __GNUC__, ...
any          any                UNIX                          CC            unix, ...
Amiga 3000   Commodore          Amiga UNIX 2.1 SVR4.0         GNU           unix,__unix__,AMIX,__AMIX__,__svr4__,m68k, __m68k__, __motorola__, __GNUC__
SUN-3        Sun                SUN-OS3 (UNIX BSD 4.2)        GNU           sun, unix, mc68020, __GNUC__
SUN-3        Sun                SUN-OS4 (UNIX SUNOS 4.1)      GNU           sun, unix, mc68020, __GNUC__
SUN-386      Sun                SUN-OS4 (UNIX SUNOS 4.0)      GNU           sun, unix, sun386, i386, __GNUC__
SUN-386      Sun                SUN-OS4 (UNIX SUNOS 4.0)      CC            sun, unix, sun386, i386
SUN-4        Sun                SUN-OS4 (UNIX SUNOS 4.1)      GNU           sun, unix, sparc, __GNUC__
SUN-4        Sun                SUN-OS4 (UNIX SUNOS 4.1)      CC            sun, unix, sparc
SUN-4        Sun                SUN-OS5 (UNIX Solaris)        GCC           sun, unix, sparc, __GNUC__
Ultrasparc   Sun                Solaris 7 (UNIX SUNOS 5.7)    CC            sun, unix, __sparc, __sparcv9
UltraSparc   Sun                Solaris 7 (UNIX SUNOS 5.7)    GCC           sun, unix, __sparc, __arch64__, __GNUC__
IBM-PC/386   any                SUN-OS5 (UNIX Solaris)        GCC           sun, unix, __svr4__, i386, __GNUC__
HP9000-300   Hewlett-Packard    NetBSD 0.9 (UNIX BSD 4.3)     GNU           unix, __NetBSD__, mc68000, __GNUC__
HP9000-300   Hewlett-Packard    HP-UX 8.0 (UNIX SYS V)        GNU           [__]hpux, [__]unix, [__]hp9000s300, mc68000, __GNUC__
HP9000-800   Hewlett-Packard    HP-UX 8.0 (UNIX SYS V)        GNU           [__]hpux, [__]unix, [__]hp9000s800
IRIS         Silicon Graphics   IRIX (UNIX SYS V 3.2)         GNU           unix, SVR3, mips, sgi, __GNUC__
IRIS         Silicon Graphics   IRIX (UNIX SYS V)             cc -ansi      [__]unix, [__]SVR3, [__]mips, [__]sgi
IRIS         Silicon Graphics   IRIX 5 (UNIX SYS V 4)         GNU           [__]unix, [__]SYSTYPE_SVR4, [__]mips, [__]host_mips, [__]MIPSEB, [__]sgi, _
DSO__, [__]_MODERN_C, __GNUC__
DECstation 5000                 RISC/OS (Ultrix V4.2A)        GNU           unix, [__]mips, [__]ultrix
DG-UX 88k    Data General       DG/UX                         GNU           unix, m88000, DGUX
DEC Alpha    DEC                OSF/1 1.3                     cc            [unix,] __unix__, __osf__, __alpha
DEC Alpha    DEC                OSF/1 1.3                     GNU           unix, __unix__, __osf__, __alpha, __alpha__, _LONGLONG
Apple MacII  Apple              A/UX (UNIX SYS V 2)           GNU           [__]unix, [__]AUX, [__]macII, [__]m68k, mc68020, mc68881, __GNUC__
NeXT         NeXT               NeXTstep 3.1 (UNIX)           cc            NeXT, m68k; NEXTAPP for NeXTstep application
PowerPC      Apple              Mach 3.0 + MkLinux            GNU           unix, __powerpc__, __PPC__, _ARCH_PPC, _CALL_SYSV, __ELF__, __linux__
PowerPC      Apple              Mach + Rhapsody               cc            __MACH__, __APPLE__, __ppc[__], __GNUC__, __APPLE_CC__
PowerPC      Apple              Mach + MacOS X                cc            __MACH__, __APPLE__, __ppc__, __GNUC__, __APPLE_CC__
Sequent      Sequent            PTX 3.2.0 V2.1.0 i386 (SYS V) GNU           unix, i386, _SEQUENT_, __GNUC__
Sequent      Sequent            PTX V4.1.3                    GNU           unix, i386, _SEQUENT_, __svr4__, __GNUC__
Convex C2    Convex             ConvexOS 10.1                 GNU           __convex__, __GNUC__
IBM RS/6000  IBM                AIX 3.2                       GNU           _AIX, _AIX32, _IBMR2, __CHAR_UNSIGNED__, __GNUC__
IBM-PC/386   any                LINUX (free UNIX)             GNU           unix, linux, i386, __GNUC__
IBM-PC/386   any                LINUX (free UNIX)             Intel 5.0     __unix__, __linux__, __INTEL_COMPILER, __ICC, __USLC__
IBM-PC/386   any                386BSD 0.1 (UNIX BSD 4.2)     GNU           unix, __386BSD__, i386, __GNUC__
IBM-PC/386   any                NetBSD 0.9 (UNIX BSD 4.3)     GNU           unix, __NetBSD__, i386, __GNUC__
IBM-PC/386   any                FreeBSD 4.0 (UNIX BSD 4.4)    GNU           unix, __FreeBSD__, i386, __GNUC__
IBM-PC/386   any                EMX 0.9c (UNIXlike on OS/2)   GNU           [unix,] i386, __GNUC__, __EMX__
IBM-PC/386   any                Cygwin32 on WinNT/Win95       GNU           _WIN32, __WINNT__, __CYGWIN32__, __POSIX__, _X86_, i386, __GNUC__
IBM-PC/386   any                Mingw32 on WinNT/Win95        GNU           _WIN32, __WINNT__, __MINGW32__, _X86_, i386, __GNUC__
IBM-PC/386   any                WinNT/Win95                   MSVC4.0,5.0   _WIN32, _M_IX86, _MSC_VER
IBM-PC/386   any                WinNT/Win95                   Borland 5.0   __WIN32__, _M_IX86, __TURBOC__, __BORLANDC__
IBM-PC/386   any                WinNT/Win95 and Cygwin32      GNU           _WIN32, __WINNT__, __CYGWIN32__, __POSIX__, __i386__, _X86_, __GNUC__
IBM-PC/586   any                BeOS 5                        GNU           __BEOS__, __INTEL__, __i386__, _X86_, __GNUC__
IBM-PC/586   any                HP NUE/ski, Linux             GNU           unix, linux, __ia64[__], __GNUC__, __LP64__
RM400        Siemens-Nixdorf    SINIX-N 5.42                  c89           unix, mips, MIPSEB, host_mips, sinix, SNI, _XPG_IV
Acorn        Risc PC            RISC OS 3.x                   GNU           [__]arm, [__]riscos, __GNUC__
Acorn        Risc PC            RISC OS 3.x                   Norcroft      [__]arm, [__]riscos
APPLE IIGS   Apple              ??                            ??
 
 
 
 
 

當然,列出上面的大部分的編譯開關,并不是說Apache都支持它們,事實上Apache僅僅支持一部分,假如僅僅對某個操作系統或者某個機器有愛好,則可以挑選對應的宏定義中的代碼。
上述的編譯器開發都是某個平臺相關的,事實上只要運行于該平臺,該開關自然就成立,不需要APR本身重新定義。另外有一些特性開關則是必須由APR自行定義。這些特性通常是操作系統之間很小的區別,比如同樣是Unix系統,可能有的支持共享內存,有的不支持,為此在使用共享內存之前必須能夠判定當前的平臺是否支持。這些特性宏的定義可以從apr.h.in模板中定義:
#define APR_HAVE_ARPA_INET_H     @arpa_ineth@
#define APR_HAVE_CONIO_H         @conioh@
#define APR_HAVE_CRYPT_H         @crypth@
#define APR_HAVE_CTYPE_H         @ctypeh@
#define APR_HAVE_DIRENT_H        @direnth@
#define APR_HAVE_ERRNO_H         @errnoh@
#define APR_HAVE_FCNTL_H         @fcntlh@
#define APR_HAVE_IO_H            @ioh@
#define APR_HAVE_LIMITS_H        @limitsh@
#define APR_HAVE_NETDB_H         @netdbh@
#define APR_HAVE_NETINET_IN_H    @netinet_inh@
#define APR_HAVE_NETINET_SCTP_H @netinet_sctph@
#define APR_HAVE_NETINET_SCTP_UIO_H @netinet_sctp_uioh@
#define APR_HAVE_NETINET_TCP_H   @netinet_tcph@
#define APR_HAVE_PTHREAD_H       @pthreadh@
#define APR_HAVE_SEMAPHORE_H     @semaphoreh@
#define APR_HAVE_SIGNAL_H        @signalh@
#define APR_HAVE_STDARG_H        @stdargh@
#define APR_HAVE_STDINT_H        @stdint@
#define APR_HAVE_STDIO_H         @stdioh@
#define APR_HAVE_STDLIB_H        @stdlibh@
#define APR_HAVE_STRING_H        @stringh@
#define APR_HAVE_STRINGS_H       @stringsh@
#define APR_HAVE_SYS_IOCTL_H     @sys_ioctlh@
#define APR_HAVE_SYS_SENDFILE_H @sys_sendfileh@
#define APR_HAVE_SYS_SIGNAL_H    @sys_signalh@
#define APR_HAVE_SYS_SOCKET_H    @sys_socketh@
#define APR_HAVE_SYS_SOCKIO_H    @sys_sockioh@
#define APR_HAVE_SYS_SYSLIMITS_H @sys_syslimitsh@
#define APR_HAVE_SYS_TIME_H      @sys_timeh@
#define APR_HAVE_SYS_TYPES_H     @sys_typesh@
#define APR_HAVE_SYS_UIO_H       @sys_uioh@
#define APR_HAVE_SYS_UN_H        @sys_unh@
#define APR_HAVE_SYS_WAIT_H      @sys_waith@
#define APR_HAVE_TIME_H          @timeh@
#define APR_HAVE_UNISTD_H        @unistdh@
#define APR_HAVE_SHMEM_MMAP_TMP     @havemmaptmp@
#define APR_HAVE_SHMEM_MMAP_SHM     @havemmapshm@
#define APR_HAVE_SHMEM_MMAP_ZERO    @havemmapzero@
#define APR_HAVE_SHMEM_SHMGET_ANON @haveshmgetanon@
#define APR_HAVE_SHMEM_SHMGET       @haveshmget@
#define APR_HAVE_SHMEM_MMAP_ANON    @havemmapanon@
#define APR_HAVE_SHMEM_BEOS         @havebeosarea@
 
#define APR_USE_SHMEM_MMAP_TMP     @usemmaptmp@
#define APR_USE_SHMEM_MMAP_SHM     @usemmapshm@
#define APR_USE_SHMEM_MMAP_ZERO    @usemmapzero@
#define APR_USE_SHMEM_SHMGET_ANON @useshmgetanon@
#define APR_USE_SHMEM_SHMGET       @useshmget@
#define APR_USE_SHMEM_MMAP_ANON    @usemmapanon@
#define APR_USE_SHMEM_BEOS         @usebeosarea@
#define APR_USE_FLOCK_SERIALIZE           @flockser@
#define APR_USE_SYSVSEM_SERIALIZE         @sysvser@
#define APR_USE_POSIXSEM_SERIALIZE        @posixser@
#define APR_USE_FCNTL_SERIALIZE           @fcntlser@
#defineAPR_USE_PROC_PTHREAD_SERIALIZE @procpthreadser@
#define APR_USE_PTHREAD_SERIALIZE    @pthreadser@
 
#define APR_HAS_FLOCK_SERIALIZE           @hasflockser@
#define APR_HAS_SYSVSEM_SERIALIZE         @hassysvser@
#define APR_HAS_POSIXSEM_SERIALIZE        @hasposixser@
#define APR_HAS_FCNTL_SERIALIZE           @hasfcntlser@
#define APR_HAS_PROC_PTHREAD_SERIALIZE @hasprocpthreadser@
#define APR_HAS_RWLOCK_SERIALIZE      @hasrwlockser@
#define APR_PROCESS_LOCK_IS_GLOBAL @proclockglobal@
#define APR_HAVE_CORKABLE_TCP   @have_corkable_tcp@
#define APR_HAVE_GETRLIMIT      @have_getrlimit@
#define APR_HAVE_IN_ADDR        @have_in_addr@
#define APR_HAVE_INET_ADDR      @have_inet_addr@
#define APR_HAVE_INET_NETWORK   @have_inet_network@
#define APR_HAVE_IPV6           @have_ipv6@
#define APR_HAVE_MEMMOVE        @have_memmove@
#define APR_HAVE_SETRLIMIT      @have_setrlimit@
#define APR_HAVE_SIGACTION      @have_sigaction@
#define APR_HAVE_SIGSUSPEND     @have_sigsuspend@
#define APR_HAVE_SIGWAIT        @have_sigwait@
#define APR_HAVE_STRCASECMP     @have_strcasecmp@
#define APR_HAVE_STRDUP         @have_strdup@
#define APR_HAVE_STRICMP        @have_stricmp@
#define APR_HAVE_STRNCASECMP    @have_strncasecmp@
#define APR_HAVE_STRNICMP       @have_strnicmp@
#define APR_HAVE_STRSTR         @have_strstr@
#define APR_HAVE_MEMCHR         @have_memchr@
#define APR_HAVE_STRUCT_RLIMIT @struct_rlimit@
#define APR_HAVE_UNION_SEMUN    @have_union_semun@
#define APR_HAVE_SCTP           @have_sctp@
 
/* APR Feature Macros */
#define APR_HAS_SHARED_MEMORY     @sharedmem@
#define APR_HAS_THREADS           @threads@
#define APR_HAS_SENDFILE          @sendfile@
#define APR_HAS_MMAP              @mmap@
#define APR_HAS_FORK              @fork@
#define APR_HAS_RANDOM            @rand@
#define APR_HAS_OTHER_CHILD       @oc@
#define APR_HAS_DSO               @aprdso@
#define APR_HAS_SO_ACCEPTFILTER   @acceptfilter@
#define APR_HAS_UNICODE_FS        0
#define APR_HAS_PROC_INVOKED      0
#define APR_HAS_USER              1
#define APR_HAS_LARGE_FILES       0
#define APR_HAS_XTHREAD_FILES     0
#define APR_HAS_OS_UUID           0
在使用configure進行配置的時候,apr.h.in模板作為輸入最終生成apr.h文件。不過apr.h.in中的@xx@將被0或者1所取代:假如該平臺支持某個特定,相應的宏將定義為1,否則定義為0。


關于作者
張中慶,目前主要的研究方向是嵌入式瀏覽器,移動中間件以及大規模服務器設計。目前正在進行Apache的源代碼分析,計劃出版《Apache源代碼全景分析》上下冊。Apache系列文章為本書的草案部分,對Apache感愛好的朋友可以通過flydish1234 at sina.com.cn與之聯系!

假如你覺得本文不錯,請點擊文后的“推薦本文”鏈接??!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91视频国产高清| 国模精品视频一区二区三区| 国产福利视频一区二区| 国产精品99久久久久久久久久久久| 国产视频久久久久| 久久久国产91| 欧美激情亚洲自拍| 久久久久久中文字幕| www高清在线视频日韩欧美| www.日韩.com| 成人性生交大片免费看小说| 性色av一区二区三区在线观看| 成人做爰www免费看视频网站| 欧美大片va欧美在线播放| 欧美极品xxxx| 国产精品91免费在线| 欧美性感美女h网站在线观看免费| 日韩视频一区在线| 欧美中文字幕在线观看| 亚洲欧美日韩精品久久奇米色影视| 久久好看免费视频| 羞羞色国产精品| 午夜精品蜜臀一区二区三区免费| 色久欧美在线视频观看| 欧美精品中文字幕一区| 国产午夜精品免费一区二区三区| 亚洲国产精品久久久久久| 亚洲成人激情在线观看| 欧美大尺度激情区在线播放| 欧美日韩福利视频| 亚洲国产精品大全| 久久久亚洲网站| 一区二区三区 在线观看视| 久久综合色影院| 久久视频在线视频| 欧洲美女免费图片一区| 欧美日韩国产中字| www.日韩不卡电影av| 日韩av免费网站| yw.139尤物在线精品视频| 精品少妇v888av| 久久久免费观看| 日日骚av一区| 欧美亚洲国产视频| 国产精品免费福利| 国产午夜精品麻豆| 久久人人爽人人爽人人片亚洲| 北条麻妃一区二区在线观看| 国产精品一区二区久久久| 欧美尤物巨大精品爽| 久久久久久久久久国产精品| 欧美孕妇性xx| 91国产高清在线| 国产在线拍偷自揄拍精品| 国产视频自拍一区| 2020国产精品视频| 狠狠躁天天躁日日躁欧美| 亚洲国产97在线精品一区| 国产一区二区丝袜| 97久久精品人人澡人人爽缅北| 97色在线观看免费视频| 亚洲美女视频网站| 亚洲第一视频在线观看| 黑人巨大精品欧美一区二区三区| 韩国19禁主播vip福利视频| 成人中文字幕+乱码+中文字幕| 日韩在线视频国产| 4388成人网| 日韩欧美亚洲国产一区| 欧美性理论片在线观看片免费| 国产精品久久久久久超碰| 久久久999精品免费| 国产在线精品成人一区二区三区| 欧美在线免费视频| 亚洲精品videossex少妇| 亚洲开心激情网| 成人欧美一区二区三区在线| 黑人巨大精品欧美一区二区一视频| 日韩国产精品视频| 日韩欧美中文字幕在线观看| 亚洲一区二区中文字幕| 日韩中文字在线| 亚洲天堂网在线观看| 久久精品中文字幕一区| 亚洲国产精品视频在线观看| 91九色单男在线观看| 久久免费少妇高潮久久精品99| 亚洲色图欧美制服丝袜另类第一页| 亚洲欧美自拍一区| 国产综合久久久久久| 国产成人在线视频| 国产成人综合亚洲| 久久国产精品久久国产精品| 成人妇女免费播放久久久| 亚洲a级在线播放观看| 福利视频导航一区| 狠狠色噜噜狠狠狠狠97| 精品成人国产在线观看男人呻吟| 国产成人精品999| 国产午夜精品一区二区三区| 亚洲va码欧洲m码| 国产精品第二页| 国产一区二区三区日韩欧美| 亚洲成人久久一区| 九九九热精品免费视频观看网站| 欧美成人手机在线| 国产精品麻豆va在线播放| 中文字幕不卡av| 上原亚衣av一区二区三区| 综合网日日天干夜夜久久| 亚洲图片欧洲图片av| 2018日韩中文字幕| 久久久久国产一区二区三区| 亚洲精品一区二区三区婷婷月| 国产精品成熟老女人| 91豆花精品一区| 国产美女扒开尿口久久久| 日韩视频免费在线观看| 欧美一级在线播放| 亚洲天堂久久av| 欧美国产激情18| 欧美人成在线视频| 国产精品aaaa| 国产精品中文字幕在线| 美日韩丰满少妇在线观看| 97涩涩爰在线观看亚洲| 一本大道久久加勒比香蕉| 久久亚洲精品中文字幕冲田杏梨| 成人乱色短篇合集| 国产精品露脸av在线| 欧美在线国产精品| 欧美疯狂xxxx大交乱88av| 国产精品久久久久久久久久三级| 欧美老肥婆性猛交视频| 亚洲激情中文字幕| 欧美理论电影在线播放| 日本欧美中文字幕| 91探花福利精品国产自产在线| 亚洲影视九九影院在线观看| 欧美老少做受xxxx高潮| 国产精品美女久久久久久免费| 国产午夜精品免费一区二区三区| 国产日韩在线视频| 欧美最猛性xxxxx免费| 亚洲精品日韩激情在线电影| 国产精品久久久久久久久男| 国产精品亚洲аv天堂网| 午夜精品福利在线观看| 日韩欧美a级成人黄色| 国产精品美女免费| 亚洲欧美在线免费| 91久久久久久久久久久久久| 国产精品一区二区三区成人| 日韩高清av在线| 日韩精品极品视频| 精品久久久久久| 久久久久久中文字幕| 精品久久香蕉国产线看观看gif| 91av在线免费观看| 欧美视频一区二区三区…| 久久97精品久久久久久久不卡| 成人动漫网站在线观看| 一本色道久久综合亚洲精品小说| 亚洲偷欧美偷国内偷|