• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 第六章 系統數據文件和信息

    發表于:2007-05-26來源:作者:點擊數: 標簽:
    ? 6?1〓引言? 有很多操作需要使用一些與系統有關的數據文件,例如,口令字文件/etc/passwc l和組文件 /etc/group就是經常由多種程序使用的兩個文件。用戶每次登錄入 Unix系統 時,以 及每次執 行ls-l命令時都要使用口令字文件。? 由于歷史原因,這些數據
     

    ?  
    6?1〓引言?  
    有很多操作需要使用一些與系統有關的數據文件,例如,口令字文件/etc/passwc  
    l和組文件  
    /etc/group就是經常由多種程序使用的兩個文件。用戶每次登錄入Unix系統時,以  
    及每次執  
    行ls-l命令時都要使用口令字文件。?  
    由于歷史原因,這些數據文件都是ASCII文本文件,并且使用標準I/O庫讀這些文件  
    。但是,  
    對于較大的系統,順序掃描口令字文件變得很花費時間,我們想以非ASCII文本格  
    式存放這  
    些文件,但仍向應用程序提供一個可以處理任何一種文件格式的界面。對于這些數  
    據文件的  
    可移植界面是本章的主題。本章也包括了系統標識函數、時間和日期函數。?  
    6?2〓口令字文件?  
    Unix口令字文件(POSIX?1則將其稱為用戶數據庫)包含了圖6?1中所示的各字段,  
    這些字段  
    包含在<pwd?h>中定義的passwd結構中。?  
    注意,POSIX?1只指定passwd結構中7個字段中的5個。另外2個元素由SVR4和4?3  
    +BSD支持  
    。???P146?  
    圖6?1〓/etc/passwd文件中的字段?  
    由于歷史原因,口令字文件是/etc/passwd,而且是一個文本文件。每一行包含圖  
    6?1中所  
    示的7個字段,字段之間用冒號相分隔。例如,該文件中可能有下列三行:?  
    root:jheVopR58x9Fx:0:1:The superuser:/:/bin/sh?  
    nobody:*:65534:65534::/:?  
    stevens:3hKVD8R58r9Fx:224:20:Richard Stevens:/home/stevens:/bin/ksh?  
    關于這些記錄項請注意下列各點:?  
    ·通常有一個記錄項,其用戶名為root。此記錄項的用戶ID是O(超級用戶)。?  
    ·密碼口令字字段包含了經單向密碼單法處理過的用戶口令字副本。因為此算法是  
    單問的,  
    所以我們不能從密碼口令字猜測到原來的口令字。當前使用的算法(見Morris和Th  
    ompson〔  
    1979〕)總是產生13個可打印字符(在64字符集〔a-zA-Z0-9?1〕中)。因為對  
    用戶名no  
    b  
    ody的記錄的密碼口令字段只包含一個字符(*),所以密碼口令字決不會與此值相匹  
    配。此用  
    戶名可用于網絡服務器,這些服務器允許我們登錄到一個系統,但其用戶ID和組I  
    D(65534)  
    ,并不提供優先權。以此用戶ID和組ID我們可存取的文件只是大家都可讀、寫的文  
    件。(這  
    假定用戶ID65534和組ID65534并不擁有任何文件。)在本節稍后部分我們將討論對  
    口令字文  
    件最近所作的更改(陰影口令字)。?  
    ·在口令字文件記錄中的某些字段可能是空。如果密碼口令字段為空,這通常就意  
    味著該用  
    戶沒有口令字。(不希望這樣做。)nobody記錄有兩個空白字段:注釋字段和初始s  
    hell字段  
    ??瞻鬃⑨屪侄尾划a生任何影響??瞻譻hell字段則表示取系統默認值,這通常是  
    /bin/sh。  
    ?  
    ·支持finger(1)命令的某些Unix系統支持在注釋字段中的附加信息。其中,各部  
    分之間都  
    用逗號分隔:用戶姓名,辦公室地點,辦公室電話號碼,家庭電話號碼。另外,如  
    果在注釋  
    字段中的用戶姓名是一個&,則它被代換為登錄名。例如,可以有下列記錄:??  
       
    stevens:3hKVD8R58r9Fx:224:20:Richard &,B232,555-1111,555-2222:/home/ste  
    vens:/bin  
    /ksh?  
    即使你所使用的系統并不支持finger命令,這些信息仍可存放在注釋字段中,因為  
    該字段只  
    是一個注釋,并不由系統公用程序解釋。?  
    POXIX?1只定義了兩個存取口令字文件中信息的函數。在給出用戶登錄名或數值用  
    戶ID后,  
    這兩個函數就能查看相關記錄。?  
    #include <sys/types?h>?  
    include <pwd?h>?  
    struct passwd *getpwuid(uid 跡茫模*常病絫 ?uid?);?  
    struct passwd *getpwnaw(const char *?name?);?  
    Both return:pointer if OK,NULL on error?  
    兩個函數反回:看成功為指針,出錯為NULL?  
    getpwuid由ls(1)程序使用,以便將包含在一個i-node中的數值用戶ID映照為用戶  
    登錄名。g  
    etpwnaw在我們鍵入登錄名時由login(1)程序使用。?  
    這兩個函數都返回一個指向passwd結構的指針,該結構已由這兩個函數在執行時填  
    入了所需  
    的信息。此結構通常是在相關函數內的靜態變量,只要調用相關函數,其內容就會  
    被重寫。  
    ?  
    如果我們要查看的只是一個登錄名或一個用戶ID,那么這兩個POSIX?1函數是能滿  
    足要求的  
    ,但是也有些程序要查看整個口令字文件。下列三個函數則可用于此種目的。?  
    #include <sys/types?h>?  
    #include <pwd?h>?  
    struct passwd *getpwent(void);?  
    Returns:pointer if OK,NULL on error or end of file?  
    返回:看成功為指針,出錯或文件尾為NULL??  
    void setpwent(void);?  
    void endpwent(void);?  
    POXIX?1沒有定義這三個函數,但它們受到SVR4和4?3+BSD的支持。?  
    調用getpwent時,它返回口令字文件中的下一個記錄。如同上面所述的兩個POSIX  
    ?1函數一  
    樣,它返回一個由它填寫好的passwd結構的指針。每次調用此函數時都重寫該結構  
    。在第一  
    次調用該函數時,它打開它所使用的各個文件。在使用本函數時,對口令字文件中  
    各個記錄  
    安排的順序并無要求。?  
    函數setpwent反繞它所使用的文件,endpwent則關閉這些文件。在使用getpwent查  
    看完了口  
    令字文件后,一定要調用endpwent關閉這些文件。getpwent知道什么時間它應當打  
    開它所使  
    用的文件(第一次被調用時),但是它并不能知道何時關閉這些文件。?  
    實例?  
    程序6?1示出了函數getpwnam的一個實現。?  
    程序6?1〓getpwent函數?  
    P148?  
    在程序開始處調用setpwent是保護性的措施,以便在調用者在此之前已經調用過g  
    etpwent的  
    情況下,反繞有關文件使它們定位到文件開始處。getpwnaw和getpwuid完成后不應  
    使有關文  
    件仍處于打開狀態,所以應調用endpwent關閉它們。?  
    6?3〓陰影口令字(Shadow Passwords)?  
    在上面一節我們曾提及,對Unix口令字通常使用的密碼算法是單向算法。給出一個  
    密碼口令  
    字,我們找不到一種算法可以將其反變換到普通文本口令字。(普通文本口令字是  
    在Passwor  
    d:提示后鍵入的口令字。)但是我們可以對口令字進行猜測,將猜測的口令字經單  
    向算法變  
    換成密碼形成,然后將其與用戶的密碼口令字相比較。如果用戶口令字是隨機選擇  
    的,那么  
    這種方法并不是很有用的。但是用戶往往以非隨機方式選擇口令字(對偶的姓名、  
    街名、寵  
    物名等)。一個經常重復的試驗是先得到一份口令字文件,然后用試探方法猜測口  
    令字。(Ga  
    rfinkel和Spaftord〔1991〕的第二章對Unix口令字及口令字密碼處理方案的  
    歷史情況  
    及細節進行了說明。)?  
    為使企圖這樣做的人難以獲得原始資料(密碼口令字),某些系統將密碼口令字存放  
    在另一個  
    通常稱為陰影口令字文件中。該文件至少要包含用戶名和密碼口令字。與該口令字  
    相關的其  
    它信息也可存放在該文件中。例如,具有陰影口令字的系統經常要求用戶在一定時  
    間間隔后  
    選擇一個新口令字。這被稱之為口令字時效,要選擇新口令字的時間間隔長度經常  
    也存放在  
    陰影口令字文件中。?  
    在SVR4中,陰影口令文件是/etc/shadow。在4?3+BSD中,密碼口令字存放在/etc  
    /master?  
    passwd中。?  
    陰影口令字文件不應是一般用戶可以讀取的。僅有少數幾個程序需要存取密碼口令  
    字文件,  
    例如login(1)和passwd(1),這些程序常常是設置-用戶-ID為root。有了陰影口令  
    字后,普  
    通口令字文件/etc/passwd可由各用戶自由讀取。?  
    6?4〓組文件?  
    Unix組文件(POSIX?1稱其為組數據庫)包含了圖6?2中所示字段。這些字段包含在  
    <grp?h>  
    中所定義的group結構中。??  
    P149???  
    圖6?2〓/etc/group文件中的字段?  
    POSIX?1只定義了其中3個字段。另一個字段gr 跡茫模*常病絧asswd則由SVR4和  
    4?3+BSD  
    支持。?  
    字段gr-mem是一個指針數組,其中的指針各指向一個屬于該組的用戶名。該數組以  
    空指針(n  
    ull)結尾。?  
    我們可以用下列兩個由posix?1定義的函數來查看組名或數值組I。?  
    #include <sys/types?h>?  
    #include <grp?h>?  
    struct group *getgrgid(gid 跡茫模*常病絫 ?gid?);?  
    struct group *getgrnam(const char *?name?);?  
    Both return:pointer if OK,NULL on error兩個函數返回:若成功為指針,出錯  
    為NULL?  
    如同對口令字文件進行操作的函數一樣,這兩個函數通常也返回指向一個靜態變量  
    的指針,  
    在每次調用時都重寫該靜態變量。?  
    如果需要搜索整個組文件,則須使用另外幾個函數。下列三個函數類似于針對口令  
    字文件的  
    三個函數。?  
    #include <sys/types?h>?  
    #include <grp?h>?  
    struct group *getgrent(void);?  
    Returns:Pointer if OK,NULL on error or end of file?  
    返回:若成功為指針,出錯或文件尾為NULL?  
    void setgrent(void);?  
    void endgrent(void);?  
    這三個函數由SVR4和4?3+BSD提供POSIX?1并末定義這些函數。?  
    setgrent打開組文件(如若它尚末被打開)并反繞它。getgrent從組文件中讀下一個  
    記錄,如  
    若該文件尚末打開則先打開它。endgrent關閉組文件。?  
    6?5〓添加組ID?  
    在Unix中,組的使用已經作了些更改。在Version7中,每個用戶任何時候都只屬于  
    一個組。  
    當用戶登錄時,系統就按口令字文件中與其相關記錄中的數字組ID,賦給他實際組  
    ID。我們  
    可以在任何時候執行newgrp(1)以更改組ID。如果newgrp命令執行成功(關于許可權  
    規則,請  
    參閱手冊頁。),則我們的實際組ID就更改為新的組ID,它將被用于后續的文件存  
    取許可權  
    檢查。執行不帶任何參數的newgrp,則可返回到原來的組。?  
    這種組的成員關系一直維持到1983年左右。此時,4?2BSD引入了添加組ID的概念  
    。我們不  
    僅屬于我們的口令字記錄中組ID所對應的組,也可屬于多至16個另外的一些組。文  
    件存取權  
    檢查相應修改為:不僅將進程的有效組ID與文件的組ID相比較,而且也將所有添加  
    組ID與文  
    件的組ID進行比較。?  
    添加組ID是POSIX?1的可選特性。常數NGROUPS 跡茫模*常病組AX(圖2?7)規定了  
    添加組ID  
    的數量,其常用值是16。如果不支持添加組ID,則此常數值為O。?  
    SVR4和4?3+BSD都支持添加組ID。?  
    FIPS 151-1要求支持添加組ID,并要求NGROUP 跡茫模*常病組AX至少是8。?  
    使用添加組ID的優點是我們不必再顯式地經常更改組。一個用戶常常會參加多個項  
    目組,因  
    此也就要同時屬于多個組。?  
    為了存取和設置添加組ID提供了下列三個函數:?  
    POSIX?1只說明了getgroups。因為setgroups和initgroups是特權操作,所以Pos  
    ix?1沒有  
    說明它們。但是,SVR4和4?3+BSD支持所有這三個函數。?  
    getgroups將進程所屬用戶的各添加組ID填寫到數組bgrouplist中,填寫入該數組  
    的添加組I  
    D數最多為gidsetsize個。實際填寫到數組中的添加組ID數由函數返回。如果系統  
    常數NGROU  
    P 跡茫模*常病組AX為0,則返回0,這并不表示出錯。?  
    #include <sys/types?h>?  
    #include <unistd?h>?  
    int getgroups(int ?gidsetsize?,gid 跡茫模*常病絫 ?grouplist?[]);  
    ?  
    Returns:number of supplementary group IDs if OK,-1 on error?  
    int setgroups(int? ngroups,?const gid 跡茫模*常病絫 ?grouplist?[]  
    );?  
    int initgroups(const char *?username,?gid 跡茫模*常病絫? basegid);?  
    ?  
    兩個函數返回:若成功為0,出錯為-1?  
    Both return:0 if OK,-1 on error?  
    作為一種特殊情況,如若giclsetsize為0,則函數只返回添加組ID數,而對數組g  
    rouplist  
    則不作修改。(這使調用者可以確定grouplist數組的長度,以便進行分配。)?  
    setgroups可由超級用戶調用以便為調用進程設置添加組ID表。grouplist,是組I  
    D數組,而  
    ngroups說明了數組中的元素數。?  
    通常,只有initgroups函數調用setgroups,initgroups讀整個組文件(用函數getg  
    rent,setg  
    rent和endgrent),然后對username確定其組的成員關系。然后,它調用setgroup  
    s,以便為  
    該用戶初始化添加組ID表。因為initgroups調用setgroups,所以只有超級用戶才能  
    調用init  
    groups。除了在組文件中找到username是成員的組,initgroups也在添加組ID表中  
    包括了ba  
    segid。basegid是username在口令字文件中的組ID。?  
    initgroups只有少數幾個程序調用,例如login(1)程序在用戶登錄時調用該函數。  
    ?  
    6?6〓其它數據文件?  
    至此我們討論了兩個系統數據文件-口令字文件和組文件。在日常事務操作中,Un  
    ix系統還  
    使用很多其它文件。例如,BSD網絡軟件有一個記錄各網絡服務器所提供的服務的  
    數據文件(  
    /etc/services),有一個記錄協議信息是數據文件(/etc/protocols),還有一個則  
    是記錄網  
    絡信息的數據文件(/etc.networks)。幸運的是,對于這些數據文件的界面都與上  
    述對口令  
    字文件和組文件的相似。?  
    一般原理是,每個數據文件至少有三個函數:?  
    1? get函數;讀下一個記錄,如果需要還打開該文件。此種函數通常返回指向一  
    個結構的  
    指針。當已達到文件尾端時返回空指針。大多數get函數返回指向一個靜態存儲類  
    結構的指  
    針,如果要保存其內容,則需復制它。?  
    2? set函數:打開相應數據文件(如果尚末打開),然后反繞該文件。如果希望在  
    相應文件  
    起始處開始處理,則調用此函數。?  
    3? end函數:關閉相應數據文件。正如前述,在結束了對相應數據文件的讀、寫  
    操作后,  
    總應調用此函數以關閉所有相關文件。?  
    另外,如果數據文件支持某種形式的關鍵字搜尋,則也提供搜尋具有指定關鍵字的  
    記錄的例  
    程。例如,對于口令字文件提供了兩個按關鍵字進行搜尋的程序:getpwnam尋找具  
    有指定用  
    戶名的記錄;getpwuid尋找具有指定用戶ID的記錄。?  
    圖6?3中列出了一些這樣的例程,這些都是SVR4和4?3+BSD支持的。在圖中列出了  
    針對口令  
    字文件和組文件的函數,這些已在上面說明過。圖中也列出了一些與網絡有關的函  
    數。對圖  
    中列出的所有數據文件都有get、set和end函數。?  
    在SVR4中,圖6?3中最后四個數據文件都是符號連接,連接到目錄/e6tc/inet下的  
    同名文件  
    上。?  
    SVR4和4?3+BSD都有類似于圖中所列的附加函數,但是這些附加函數都處理系統管  
    理文件,  
    專用于各個實現。?  
    P153???  
    圖6?3〓存取系統數據文件的一些例程?  
       
    6?7〓登錄會計?  
    大多數Unix系統都提供下列兩個數據文件:utmp文件,它記錄當前登錄進系統的各  
    個用戶;  
    wtmp文件,它跟蹤各個登錄和注銷事件。?  
    在Version7中,一個包含下列結構的二進制記錄寫入這兩個文件中:?  
    struct utmp {?  
    char ut 跡茫模*常病絣ine[8]; /* tty 行:"ttyh0","ttyd0","ttyp0",… *  
    /?  
    char ut 跡茫模*常病絥ame[8]; /*登錄名 */?  
    long ut 跡茫模*常病絫ime;  /*公元秒數 */?  
    };?  
    在登錄時,login程序填寫這樣的一個結構,然后將其寫入到utmp文件中,同時也  
    將其添寫  
    到wtmp文件中。在注銷時,init進程在utmp文件中的相應記錄擦除(每個字節都填  
    以0),并  
    將一個新記錄添寫到wtmp文件中。讀wtmp文件中的該注銷記錄,其ut 跡茫模*常?nbsp; 
    〗name字  
    段清除為0。在  
    系統再啟動時,以及更改系統時間和日期的前后,都在wtmp文件中添寫特殊的記錄  
    項。who(  
    1)程序讀utmp文件,并以可讀格式打印其內容。后來的Unix版本提供last(1)命令  
    ,它讀wtm  
    p文件并打印所選擇的記錄。?  
    大多數Unix版本仍提供utmp和wtmp文件,但在這些文件中的信息量卻增加了。ver  
    sion 7中2  
    0字節的結構在SVR2中已擴充為36字節,而在SVR4中,utmp結構已擴充為350字節。  
    ?  
    SVR4中,這些記錄的詳細格式請參見手冊頁utmp(4)和utmpx(4)。在SVR4中,這兩  
    個文件都  
    在目錄/var/adm中。SVR4提供了很多函數(見getut(3)和getutx(3))讀、寫這兩個  
    文件。?  
    4?3+BSD中,登錄記錄的格式請參見手冊頁utmp(5)。這兩個文件的路徑名是/var  
    /run/utmp  
    和/var/log/wtmp。?  
    6?8〓系統標識?  
    POSIX?1定義了uname函數,它返回與宿主機和操作系統有關的信息。?  
    #include <sys/utsname?h>?  
    int uname(struct utsname *?name?;?  
    Returns:nonnegative value if OK,-1 on error 返回:若成功為非負值,出錯為  
    -1?  
    通過該函數的參數向其傳遞一個utsname結構的地址,然后該函數填寫此結構。PO  
    SIX?1只  
    定義了該結構中最少需要的字段(它們都是字符數組),而每個數組的長度則由實現  
    確定。某  
    些實現在該結構中提供了另外一些字段。在歷史上,系統V為每個數組分配9個字節  
    ,其中有  
    1個字節用于字符串結束符(null字符)。?  
    struct utsname {?  
    char sysname[9];  /*name of the operating system */操作系統名?  
    char nodename[9];  /* name of this node */ 此節點名?  
    char release[9];  /*current release of operating system */操作系統當前  
    發行版?  
    char version[9];  /*current version of this release */此發行版的當前版  
    ?  
    char machine[9];  /*name of hardware type */硬件類型名?  
    };?  
    在utsname結構中的信息通??捎胾name(1)命令打印。?  
    POSIX?1警告:nodename元素可能并不適用于在一通信網絡上引用宿主機。此函數  
    來自于系  
    統V,在較早時期,nodename元素適用于在UUCP網絡上引用主機。?  
    也應理解在此結構中并沒有給出有關POSIX?1版本的信息。這應當使用2?5?2節  
    中所說明  
    的 跡茫模*常病絇OSIX 跡茫模*常病絍ERSION以獲得該信息。最后,此函數給出  
    了一種存  
    取該結構中信息的方法,至于  
    如何初始化這些信息,POSIX?1沒有作任何說明。大多數系統V版本在構造系統核  
    時通過編  
    譯將這些信息存放在系統核中。?  
    貝克萊類的版本提供gethostname函數,它只返回宿主機名。這通常就是在TCP/IP  
    網上該宿  
    主機的名字。??  
    #include <unistd?h>?  
    int gethostname(char *?name,?int ?namelen);??  
    Returns:0 if OK,-1 on error返回:若成功為0,出錯為-1?  
    通過name返回的字符串以null符結尾(除非沒有提供足夠的空間)。<sys/param?h  
    中的常數  
    MAXHOSTNAMELEN規定了此名字的最大長度(通常是64字節)。如果該宿主機聯到TCP  
    /IP網,則  
    此宿主機名通常是該宿主機的完整的域名。?  
    hostname(1)命令可用來存取和設置宿主機名。(超級用戶用一個類似的函數setho  
    stname來  
    設置宿主機名。)宿主機名通常在系統自舉時設置,它由/etc/rc取自一個啟動文件  
    。?  
    雖然此函數是貝克萊所特有的,但是,SVR4作為BSD兼容性軟件包的一部分提供ge  
    tbostname  
    和setbostname函數,以及hostname命令。SVR4也將MAXHOSTNAMELEN擴充為256字節  
    。?  
    6?9〓時間和日期例程?  
    由Unix系統核提供的基本時間服務是國際標準時公元1970?1?1 00:00:00以來  
    經過的秒  
    數。在1?10節中曾提及這種秒數是以數據類型time-t表示的。我們稱它們為日歷  
    時間。日  
    歷時間包括時間和日期。Unix在這方面與其它操作系統的區別是(a)以國際標準時  
    而非本地  
    時間計時,(b)可自動進行轉換,例如變換到夏日制,(c)將時間和日期作為一個量  
    值保存。  
    time函數返回當前時間和日期。?  
    #include <time?h>?  
    time 跡茫模*常病絫 time(time 跡茫模*常病絫 *?calptr);??  
    Returns:value of time if OK,-1 on error 返回:若成功為時間值,出錯為-1?  
       
    時間值作為函數值返回。如果參數是非null,則時間值也存放在由calptr指向的單  
    元內。?  
    在很多貝克萊類的系統中,time(3)只是一個函數,它調用gettime of day(2)系統  
    調用。?  
    在SVR4中調用stime(2)函數,在貝克萊類的系統中調用settime of day(2)對系統  
    核中的當  
    前時間設置初始值。?  
    與time和stime函數相比,BSD的gettime of day和settime of day提供了更高的分  
    辨率(微  
    秒級)。這對某些應用是很重要的。?  
    一旦取得這種以秒計的很大的時間值后,通常要調用另一個時間函數將其變換為人  
    們可讀的  
    時間和日期。圖6?4說明了各種時間函數之間的關系。(圖中以虛線表示的四個函  
    數localti  
    me、mktime、ctime和strftime都受到環境變量TZ的影響。我們將在本節的最后部  
    分對其進  
    行說明。)?  
    P156???  
    圖6?4〓各個時間函數之間的關系?  
    兩個函數localtime和gmtime將日歷時間變換成以年、月、日、時、分、秒、周日  
    表示的時  
    間,將這些存放在一個tm結構中。?  
    struct tm {  /* a broken-down time */ 以年、月、日、時、分、秒表示的時間  
    ?  
    int tm 跡茫模*常病絪ec;  /* seconds after the minute:[0,61] */秒[0  
    ,61]  
    ?int tm 跡茫模*常病絤in;  /* minutes after the hour:[0,59] */分[0  
    ,59]  
    ?int tm 跡茫模*常病絟our; /* hours after midnight:[0,23] */時[0,  
    23]?  
    int tm 跡茫模*常病絤day; /* day of the month:[1,31] */日[1,31]  
    ?  
    int tm 跡茫模*常病絤on; /* month of the year:[0,11] */月[0,11]  
    ?  
    int tm 跡茫模*常病統ear; /* years since 1900 */ 1900后的年?  
    int tm 跡茫模*常病絯day; /* days since Sunday:[0,6] */①星期幾[0,  
    6]?  
    int tm 跡茫模*常病統day; /* days since January 1:[0,365] */②自1月1日  
    經過的天  
    數[0,365]?  
    int tm 跡茫模*常病絠sdst; /* daylight saving time flag:<0,0,>0 */③夏日  
    制時間標  
    志:<0,0,>0?  
    };?  
    秒可以超過59的理由是可以表示潤秒。注意,除了月日字段,其它字段的值都以0  
    開始。如  
    果夏日制生效,則夏日制標志值為正,如果已非夏日制時間則為零,如果此信息不  
    可用,則  
    為負。?  
    #include <time?h>?  
    struct tm *gmtime(const time 跡茫模*常病健t—?calptr);??  
    struct tm *localtime(const time 跡茫模*常病絫 ?*calptr);??  
    Both return:pointer to broken-down time?  
    兩個函數返回:指向tm結構的指針?  
    localtime和gmtime之間的區別是:localtime將日歷時間變換成本地時間(考慮到本  
    地時區和  
    夏日制標志),而gmtime則將日歷時間變換成國際標準時的年、月、日、時、分、  
    秒、周日  
    。?  
    函數mktime以本地時間的年、月、日等作為參數,將其變換成time-t值。?  
    #include <time?h>?  
    time 跡茫模*常病絫 mktime(struct tm *?tmptr);? 返回:若成功為日歷時間  
    ,出錯為  
    -1?  
    asctime和ctime函數產生下列形式的26字節字符串,這與date(1)命令的系統默認  
    輸出形式  
    類似:??  
    Tue Jan 14 17:49:03 1992\n\0?  
    #include <time?h>?  
    char *asctime(const struct tm *?tmptr);??  
    char *ctime(const time 跡茫模*常病絫 *?calptr);??  
    兩個函數返回:指向null結尾的字符串?  
    asctime的參數是指向年、月、日等字符串的指針,而ctime的參數則是指向日歷時  
    間的指針  
    。?  
    最后一個時間函數是strftime,它是非常復雜的printf類的時間值函數。?  
    #include <time?h>?  
    size 跡茫模*常病絫 strftime(char *?buf,?size 跡茫模*常病絫 maxsize,  
    const cha  
    r *?format,??  
    const struct tm *?tmptr);? 返回:若有空間為存入數組的字符數,否則為0?  
       
    最后一個參數是要格式化的時間值,說明為指向一個年、月、日、時、分、秒、周  
    日時間值  
    的指針。格式化結果存放在一個長度為maxsize個字符的buf數組中,如果buf長度  
    是以存放  
    格式化結果及一個null絡止符,則該函數返回在buf中存放的字符數(不包括null終  
    止符)。  
    否則該函數返回0。?  
    format參數控制時間值的格式。如同printf函數一樣,變換說明的形式是百分號之  
    后跟一個  
    特定字符。在format中的其它字符則按原擇輸出。兩個連續的百分號在輸出中產生  
    一個百分  
    號。與printf函數的不同之處是,每個變換說明產生一個定長輸出字符串,在for  
    mat字符串  
    中沒有字段磯刃奘畏?M??5中列出了21種ANSIC規定的變換說明。?  
    P158???  
    圖6?5〓strftime?  
    圖中第三列的數據來自于在SVR4上,對應于下列時間和日期,執行strftime函數所  
    得的結果  
    。?  
    Tue〓Jan〓14〓19:40〓MST〓1992?  
    圖6?5中的大多數格式說明的意義是很明顯的。需要略作解釋的是%U和%W。%U是相  
    應日期在  
    該年中所屬因數,包含該年中第一個星期日的周是第一周。%W也是相應日期在該年  
    中所屬的  
    周數,不同的是包含第一個星期一的周為第一周。?  
    SVR4和4?3+BSD都對strftime的格式字符串提供另一些擴充支持。?  
    我們曾在前面提及,圖6?4中以虛線表示的四個函數受到環境變量TZ的影響。這四  
    個函數是  
    :localtime,mktime,ctime和strftime。如果定義了TZ,則這些函數將使用其值以  
    代替系統  
    默認時區。如果TZ定義為空串(亦即TZ=),則使用國際標準時。TZ的值常常類似于  
    TZ=EST5ED  
    T,但是POSIX?1允許更詳細的說明。有關TZ的詳細情況請參閱POSIX?1標準[IE  
    EE 1990]  
    的8?1?1節,SVR4 environ(5)手冊頁[A T&T 1990e],或4?3+BSD ctime(3)手  
    冊頁。?  
    本節所述的所有時間和日期函數都是由ANSIC標準定義的。在此基礎上,POSIX?1  
    只增加了  
    環境變量TZ。?  
    圖6?4中七個函數中的五個可以回溯到Version7(或更早),它們是:time、local  
    time、gmt  
    ime、asctime和ctime。在Unix時間功能方面近期所作的增加大多是處理非US時區  
    以及夏日  
    制的更改規則。?  
    6?10〓摘要?  
    在所有Unix系統上都使用口令字文件和組文件。我們說明了各種讀這些文件的函數  
    。我們也  
    介紹了陰影口令字,它可以增加系統的安全性。添加組ID正在得到更多應用,它提  
    供了一個  
    用戶同時可以參辦多個組的方法。我們也介紹了大多數系統所提供的存取其它與系  
    統有關的  
    數據文件的類似的函數。最后,我們說明了ANSIC和POSIX?1提供的與時間和日期  
    有關的一些函數?!迹蹋汀?/TD>

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>