亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
樓主: 雨絲風片
打印 上一主題 下一主題

[FreeBSD] 【FreeBSD system programming 】中文翻譯計劃及所有異義提交處 [復制鏈接]

論壇徽章:
2
亥豬
日期:2014-03-19 16:36:35午馬
日期:2014-11-23 23:48:46
91 [報告]
發(fā)表于 2006-02-16 19:41 |只看該作者
原帖由 雨絲風片 于 2006-2-16 19:18 發(fā)表


給你整過去了!進度條也已更新,


不要忘了有時間幫我找找翻譯的或者邏輯的錯誤

論壇徽章:
0
92 [報告]
發(fā)表于 2006-02-16 19:49 |只看該作者
原帖由 gvim 于 2006-2-16 19:41 發(fā)表


不要忘了有時間幫我找找翻譯的或者邏輯的錯誤


群眾的眼睛是雪亮的!

論壇徽章:
0
93 [報告]
發(fā)表于 2006-02-16 21:18 |只看該作者
我在翻譯緒論,目前完成度80%
明天不出意外可以提交

論壇徽章:
0
94 [報告]
發(fā)表于 2006-02-16 21:41 |只看該作者
原帖由 meilincore 于 2006-2-16 21:18 發(fā)表
我在翻譯緒論,目前完成度80%
明天不出意外可以提交



論壇徽章:
0
95 [報告]
發(fā)表于 2006-02-17 08:36 |只看該作者

第六章 高級I/O

第六章 高級I/O

翻譯:雨絲風片@chinaunix.net


6.1 高級I/O和進程資源

正如我們在前面章節(jié)中看到的,程序可以同時打開多個文件描述符。這些文件描述符并不一定就是文件,還可以是fifo、pipe或者socket。于是,如何復用這些打開的描述符就很重要了。例如,考慮一個簡單的郵件閱讀程序,比如pine。它顯然應當允許用戶在讀寫email的同時也能去檢查是否有新郵件。這就意味著在任一給定時刻都至少能夠接收兩個來源的輸入:一個來源是用戶,另一個是用來檢查新郵件的描述符。處理描述符的復用是個復雜的問題。一種方法是把所有打開的描述符都標記為非阻塞的(O_NONBLOCK),然后在它們之中循環(huán),直到找到一個可以進行I/O操作的描述符為止。這種方法的問題是程序會一直在循環(huán),如果長時間內(nèi)沒有I/O可用,進程就會一直占據(jù)CPU。當有多個進程在一組很少的描述符上循環(huán)時,你的CPU的負載就會惡化。

另一種方法就是設置信號處理器去捕獲I/O變?yōu)榭捎玫氖录,然后就讓進程進入休眠狀態(tài)。如果你只打開了少量的描述符,而且并不經(jīng)常請求I/O的話,這種方法從理論上看倒是不錯。由于進程已經(jīng)休眠,就不會再占用CPU,僅當I/O可用時它才恢復執(zhí)行。然而,這種方法的問題在于信號處理的開銷有點大。比如一個web服務器,每分鐘收到100個請求,那就幾乎一直都在捕獲信號。每秒鐘捕獲上百個信號的開銷是相當大的,不單是進程,對于內(nèi)核發(fā)送信號的開銷而言也是一樣的。

到目前為止,我們看到的兩種選擇都有限制,效率也不高,它們需要解決的共同問題就是進程需要知道I/O究竟什么時候能用?然而,這個信息實際上只有內(nèi)核才能事先知道,因為是內(nèi)核在最終處理系統(tǒng)中的所有打開的描述符。例如,當一個進程通過fifo向另一個進程發(fā)送數(shù)據(jù)的時候,發(fā)送進程會調(diào)用write,這是一個系統(tǒng)調(diào)用,因此會進入內(nèi)核。在發(fā)送方的write系統(tǒng)調(diào)用執(zhí)行完畢之前接收方對此是一無所知的。于是就引出了一個更好的復用文件描述符的方法:由內(nèi)核來替進程管理描述符。換句話說,就是把一個打開描述符的鏈表發(fā)送給內(nèi)核,然后等待,直到內(nèi)核發(fā)現(xiàn)某個或多個描述符已經(jīng)準備好了或者已經(jīng)超時了為止。

這就是select()、poll()和kqueue()接口采用的方法。通過這些接口,內(nèi)核就會管理文件描述符,當I/O可用時就去喚醒進程。這些接口巧妙地處理了上述問題。進程不必再在打開的文件描述符中循環(huán),也不必再去設置信號了。但進程在使用這些函數(shù)的時候還是會產(chǎn)生一點小問題。這是因為I/O操作是在從這些接口返回之后才去執(zhí)行的。所以它至少需要兩個系統(tǒng)調(diào)用才能完成其操作。例如,你的程序有兩個用于讀的描述符。你對它們使用select,然后等待它們直至有數(shù)據(jù)可讀。這就需要進程首先調(diào)用select,在select返回之后,就對該描述符調(diào)用read。更妙的是,你還可以對所有打開的描述符執(zhí)行一個整體的read。一旦其中有某個描述符準備好讀之后,read就會返回,并把數(shù)據(jù)放在緩沖區(qū)中,同時還會給出一個標識,用來指示這個數(shù)據(jù)是從哪個描述符讀進來的。

6.2 select

我首先要講的接口是select()。格式如下:

  1. int  select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,  struct timeval *timeout);
復制代碼


傳給select的第一個參數(shù)已經(jīng)造成了多年的混亂。nfds參數(shù)的正確用法是把它設成文件描述符的最大值加1。換句話說,如果你有一組文件描述符{0,1,8},nfds參數(shù)就應當被設置成9,因為你的描述符的最大值為8。有些人錯誤地以為這個參數(shù)的意思是文件描述符的總數(shù)加1,對于我們的例子而言就是4。記住,一個文件描述符只是一個整數(shù)而已,所以你的程序就需要指出你所想要在其上select的最大的描述符值。

select接下來會按順序針對所有尚未完成的讀、寫以及異常條件檢查其余的三個參數(shù),readfds、writefds和exceptfds。(詳細信息請參見man(2) select)。注意,如果readfds、writefds和execptfds中沒有設置描述符,那么傳給select的對應參數(shù)應當被設置成NULL。

readfds、writefds和execptfds參數(shù)通過以下4個宏進行設置。

FD_ZERO(&fdset);

FD_ZERO宏用來對指定的描述符集合中的bit進行清零。有一點需要特別注意:只要使用select,就應當調(diào)用這個宏;否則select的行為將是不可預知的。

FD_SET(fd, &fdset);

FD_SET宏用于向一組激活的描述符中添加一個描述符。

FD_CLR(fd, &fdset);

FD_CLR宏用于從一組激活的描述符中刪除一個描述符。

FD_ISSET(fd, &fdset);

FD_ISSET宏是在select返回之后使用的,用于測試某個描述符是否已準備好進行I/O操作。

select的最后的參數(shù)是一個超時值。如果超時值被設置為NULL,則對select的調(diào)用將以不確定的方式被阻塞,直至某個操作已準備好為止。如果你需要一個確定的超時時間,那么超時值就得是一個非空的timeval結(jié)構(gòu)體。timeval結(jié)構(gòu)體如下:

  1.   struct timeval {
  2.       long    tv_sec;         /* seconds */
  3.       long    tv_usec;        /* microseconds */
  4.   };
復制代碼


如果select調(diào)用成功,將返回準備好的描述符的數(shù)目。如果select因為超時而返回,則返回值為0。如果有錯誤發(fā)生,則返回-1,同時會相應地設置errno。

6.3 poll

我們在這里對I/O的討論主要是針對BSD的。System V支持一種特殊類型的I/O,即所謂的STREAMS。和socket一樣,STREAMS也具有優(yōu)先級屬性,這種屬性有時也被成為數(shù)據(jù)帶。數(shù)據(jù)帶可用來給STREAMS中的特定數(shù)據(jù)設置較高的優(yōu)先級。BSD最初并不支持這一特性,不過有些人添加了System V仿真功能,可以對某些類型提供支持。由于我們并不關(guān)注System V,因此我們只會引用數(shù)據(jù)帶或數(shù)據(jù)優(yōu)先級帶的概念。詳細信息請參見System V STREAMS。

poll函數(shù)和select很相似:

  1.   int  poll(struct pollfd *fds, unsigned int nfds, int timeout);
復制代碼


和原產(chǎn)于BSD的select不同,poll是由System V Unix創(chuàng)建的,在早期的BSD版本中并不支持它。目前主流BSD系統(tǒng)中都已經(jīng)支持poll了。

和select相似,poll也是在一組給定的文件描述符上進行復用。在指定這些描述符的時候,你必須使用一個結(jié)構(gòu)體數(shù)組,其中每個結(jié)構(gòu)體代表一個文件描述符。和select相比,poll的好處就是你可以判斷一些很罕見的條件,而select則無法做到。這些條件是POLLERR、POLLHUP和POLLNVAL,我們稍后討論。盡管對于選擇select還是poll的問題已經(jīng)有了相當多的討論,但這在很大程度上還是取決于你的個人愛好。poll所使用的結(jié)構(gòu)體是pollfd結(jié)構(gòu)體,如下:

  1.   struct pollfd {
  2.       int     fd;             /* which file descriptor to poll */
  3.       short   events;         /* events we are interested in */
  4.       short   revents;        /* events found on return */
  5.   };
復制代碼


fd

fd成員用于指定你想要poll的文件描述符。如果你想刪除一個描述符,那就把那個描述符的fd成員設置成-1。通過這種方法,你可以避免對整個數(shù)組進行混洗,同時還可以清除revents成員中列出的所有事件。

events, revents

events成員是一個bit掩碼,用于指定針對指定描述符所關(guān)心的事件。revents成員也是一個bit掩碼,但它的值是由poll設置的,用于記錄在指定描述符上發(fā)生的事件。這些事件的定義如下:

  1.   #define POLLIN          0x0001
復制代碼


POLLIN事件表明你的程序?qū)⑦x擇該描述符上的可讀數(shù)據(jù)事件。注意,此處的數(shù)據(jù)不包括高優(yōu)先級數(shù)據(jù),比如socket上的帶外數(shù)據(jù)。

  1.   #define POLLPRI         0x0002
復制代碼


POLLPRI事件表明你的程序準備選擇該描述符上的任何高優(yōu)先級事件。

  1.   #define POLLOUT         0x0004
  2.   #define POLLWRNORM      POLLOUT
復制代碼


POLLOUT和POLLWRNOMR事件表明你的程序想知道什么時候可以對一個描述符執(zhí)行寫操作了。在FreeBSD和OpenBSD上這兩個事件是相同的;你可以在你的系統(tǒng)頭文件(/usr/include/poll.h)中查證這一點。從技術(shù)角度來說,它們之間的區(qū)別在于POLLWRNOMR僅當數(shù)據(jù)優(yōu)先帶等于0的時候才去檢測是否可以進行寫操作。

  1.   #define POLLRDNORM      0x0040
復制代碼


POLLRDNORM事件表明你的程序準備選擇該描述符上的常規(guī)數(shù)據(jù)。注意,在某些系統(tǒng)上,這個事件指定的操作和POLLIN完全一樣。但在NetBSD和FreeBSD上,這個事件和POLLIN并不相同。同樣,請去查看你的系統(tǒng)頭文件(/usr/include/poll.h)。嚴格地說,POLLRDNORM僅當數(shù)據(jù)優(yōu)先帶等于0的時候采取檢測是否可以進行讀操作。

  1.   #define POLLRDBAND      0x0080
復制代碼


POLLRDBAND事件表明你的程序想知道什么時候能夠以一個非0的數(shù)據(jù)帶值從該描述符讀數(shù)據(jù)。

  1.   #define POLLWRBAND      0x0100
復制代碼


POLLWRBAND事件表明你的程序想知道什么時候能夠以一個非0的數(shù)據(jù)帶值向該描述符寫數(shù)據(jù)。

專用于FreeBSD的選項

下面的選項是專用于FreeBSD的,知道的和使用的人都不是太多。但它們還是值得提一下,因為它們可以提供更多的靈活性。這些都是新的選項,poll并不保證能夠檢測這些條件,而且它們只能用于UFS文件系統(tǒng)。如果你的程序需要檢測這些類型的事件,那最好使用kqueue接口,我們將在稍后介紹。

  1.   #define POLLEXTEND      0x0200
復制代碼


如果文件已經(jīng)被執(zhí)行,則設置POLLEXTEND事件。

  1.   #define POLLATTRIB      0x0400
復制代碼


如果有任一文件屬性發(fā)生改變,則設置POLLATTIB事件。

  1.   #define POLLNLINK       0x0800
復制代碼


如果文件被重命名、刪除或解除鏈接,則設置POLLNLINK事件。

  1.   #define POLLWRITE       0x1000
復制代碼


如果文件內(nèi)容被修改,則設置POLLWRITE事件。

下面的事件并不是pollfd events成員的有效標志,poll也將忽略它們。它們是在pollfd revents中返回的,用于表明發(fā)生了某個事件。

  1.   #define POLLERR         0x0008
復制代碼


POLLERR事件表明有錯誤發(fā)生。

  1.   #define POLLHUP         0x0010
復制代碼


POLLHUP表明在對應的STREAMS上發(fā)生了掛起事件。POLLHUP和POLLOUT是互斥事件,因為一個發(fā)生了掛起的STREAMS就不再是可寫的了。

  1.   #define POLLNVAL        0x0020
復制代碼


POLLNVAL表明對poll的請求是無效的。

poll的最后一個參數(shù)是超時值?梢酝ㄟ^這個參數(shù)告訴poll一個以微秒為單位的超時值。如果把超時值設置為-1,poll就會阻塞,直至所請求的事件發(fā)生為止。如果超時值設置為0,則poll將立即返回。

如果對poll的調(diào)用成功,則返回一個正整數(shù)。這個正整數(shù)的值表示有多少個描述符發(fā)生了事件。如果超時,poll將返回0。如果有錯誤發(fā)生,poll則會返回-1。

6.4 kqueue

到目前為止,poll和select已經(jīng)是相當不錯的復用文件描述符的方法了。但為了使用這兩個函數(shù),你需要創(chuàng)建一個描述符的鏈表,然后把它們發(fā)送給內(nèi)核,在返回的時候又要再次查看這個鏈表。這看上去有點效率低下。一個更好一些的模型是把描述符鏈表交給內(nèi)核,然后就等待。一旦有某個或多個事件發(fā)生,內(nèi)核就把一個只包含有發(fā)生了事件的描述符的鏈表通知給進程,由此避免了每次函數(shù)返回的時候都要去遍歷整個鏈表。盡管對于只打開了幾個描述符的進程而言這點改進算不得什么,但對于那些打開了幾千個文件描述符的程序來說,這種性能改進就相當顯著了。這就是kqueue誕生背后的主要目的。同時,設計者還希望進程能夠檢測更多類型的事件,比如文件修改、文件刪除、信號交付或者子進程退出,并提供一個包含了其它任務的靈活的函數(shù)調(diào)用。處理信號、復用文件描述符、以及等待子進程等操作都可以封裝到這個單一的kqueue接口中,因為它們都是在等待某個事件的發(fā)生。

另一個設計考慮就是如何讓一個進程毫無干擾地使用多個kqueue實例。如你所見,進程可以設置一個信號處理器,但是,當代碼中的其它部分也想捕獲那個指定信號的時候該怎么辦?或者考慮更壞的情況,比如一個庫函數(shù)對你的程序想要捕獲的信號設置了信號處理器的時候?要想通過調(diào)試來找出你的程序為什么沒有執(zhí)行你所設置的信號處理器可能要花費幾個小時的時間。不過一般說來,這些情況并不會經(jīng)常發(fā)生。好的程序員應該避免在庫函數(shù)中設置信號處理器。對于大型的、復雜的程序來說,這些情況就很難避免了,所以為了更完美一點,我們應當能夠檢測這些事件,而kqueue就可以。

kqueue API由兩個函數(shù)調(diào)用和一個輔助設置事件的宏組成。這些函數(shù)將在下面進行簡要介紹。

  1.   int kqueue(void);
復制代碼


kqueue函數(shù)啟動一個新的kqueue。如果調(diào)用成功,返回值將是一個用來和新創(chuàng)建的kqueue交互的描述符。每個kqueue都有一個與之關(guān)聯(lián)的唯一的描述符。因此,一個程序可以同時打開多個kqueue。kqueue描述符的行為和常規(guī)文件描述符類似:它們也可以被復用。

最后一點,這些描述符是不能被fork創(chuàng)建的子進程繼承的。如果子進程是通過rfork調(diào)用創(chuàng)建的,那就需要設置RFFDG標志,以免這些描述符被子進程共享。如果kqueue函數(shù)失敗,將返回-1,同時相應的設置errno。

  1.   int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout);
復制代碼


kevent函數(shù)用于和kqueue的交互。第一個參數(shù)是kqueue返回的描述符。changelist參數(shù)是一個大小為nchanges的kevent結(jié)構(gòu)體數(shù)組。changelist參數(shù)用于注冊或修改事件,并且將在從kqueue讀出事件之前得到處理。

eventlist參數(shù)是一個大小為nevents的kevent結(jié)構(gòu)體數(shù)組。kevent通過把事件放在eventlist參數(shù)中來向調(diào)用進程返回事件。如果需要的話,eventlist和changelist參數(shù)可以指向同一個數(shù)組。最后一個參數(shù)是kevent所期待的超時時間。如果超時參數(shù)被指定為NULL,kevent將阻塞,直至有事件發(fā)生為止。如果超時參數(shù)不為NULL,則kevent將阻塞到超時為止。如果超時參數(shù)指定的是一個內(nèi)容為0的結(jié)構(gòu)體,kevent將立即返回所有當前尚未處理的事件。

kevent的返回值指定了放在eventlist數(shù)組中的事件的數(shù)目。如果事件數(shù)目超過了eventlist的大小,可以通過后續(xù)的kevent調(diào)用來獲得它們。在處理事件的過程中發(fā)生的錯誤也會在還有空間的前提下被放到eventlist參數(shù)中。帶有錯誤的事件會設置EV_ERROR位,系統(tǒng)錯誤也會被放到data成員中。對于其它的所有錯誤都將返回-1,并相應地設置errno。

kevent結(jié)構(gòu)體用于和kqueue的通信。FreeBSD上的頭文件位于/usr/include/sys/event.h。在這個文件中有對kevent結(jié)構(gòu)體的聲明,以及其它的一些選項和標志。和select和poll比起來,kqueue還相當?shù)哪贻p,所以它一直都在發(fā)展和添加新的特性。請查看你的系統(tǒng)頭文件以確定任何新的或者特定于系統(tǒng)的選項。

原始的kevent結(jié)構(gòu)體的聲明如下:

  1.   struct kevent {
  2.         uintptr_t       ident;
  3.         short           filter;
  4.         u_short         flags;
  5.         u_int           fflags;
  6.         intptr_t        data;
  7.         void            *udata;
  8.   };
復制代碼


現(xiàn)在,讓我們來看看各個成員:

ident

ident成員用于存儲kqueue的唯一標識。換句話說,如果你想給一個事件添加一個文件描述符的話,ident成員就應當被設置成目標描述符的值。

filter

filter成員用于指定你希望內(nèi)核用于ident成員的過濾器。

flags

flags成員將告訴內(nèi)核應當對該事件完成哪些操作和處理哪些必要的標志。在返回的時候,flags成員可用于保存錯誤條件。

fflags

fflags成員用于指定你想讓內(nèi)核使用的特定于過濾器的標志。在返回的時候,fflags成員可用于保存特定于過濾器的返回值。

data

data成員用于保存任何特定于過濾器的數(shù)據(jù)。

udata

udata成員并不由kqueue使用,kqueue會把它的值不加修改地透傳。這個成員可被進程用來發(fā)送信息甚至是一個函數(shù)給它自己,用于一些依賴于事件檢測的場合。

kqueue 過濾器

下面列出的是kqueue使用的過濾器。某些過濾器會有專用于它的標志。這些標志是在kevent結(jié)構(gòu)體的fflags成員中設置的。

  1.   #define EVFILT_READ     (-1)
復制代碼


EVFILT_READ過濾器用于檢測什么時候數(shù)據(jù)可讀。kevent的ident成員應當被設成一個有效的描述符。盡管這個過濾器的行為和select或這poll很像,但它返回的事件將是特定于所使用的描述符的類型的。

如果描述符引用的打開文件是一個vnode,該事件就表明讀取偏移量尚未到達文件末尾。data成員保存的是當前距文件末尾的偏移量,這可以是負值。如果描述符引用的是一個pipe或者fifo,那么過濾器將在有實際數(shù)據(jù)可讀時返回。data成員保存的是可供讀取的字節(jié)數(shù)目。EV_EOF bit用于表示是哪個寫入者關(guān)閉了連接。(關(guān)于使用socket時EVFILT_READ的行為細節(jié)請參見kqueue的手冊頁。)

  1.   #define EVFILT_WRITE    (-2)
復制代碼


EVFILT_WRITE過濾器用于檢測是否可以對描述符執(zhí)行寫操作。如果描述符引用的是一個pipe、fifo或者socket,則data成員將存有寫緩沖區(qū)中可用的字節(jié)數(shù)目。EV_EOF bit表示讀取方已經(jīng)關(guān)閉了連接。這個標志對于打開的文件描述符無效。

  1.   #define EVFILT_AIO      (-3)
復制代碼


EVFILT_AIO用于異步I/O操作,用于檢測和aio_error系統(tǒng)調(diào)用相似的條件。

  1.   #define EVFILT_VNODE    (-4)
復制代碼


EVFILT_VNODE過濾器用于檢測對文件系統(tǒng)上一個文件的某種改動。把ident成員設置成一個有效的打開文件描述符,用fflags成員指定所關(guān)心的事件。返回時,fflags成員將含有所發(fā)生事件的比特掩碼。這些事件如下:

  1.   #define NOTE_DELETE     0x0001
復制代碼


NOTE_DELETE fflag表示進程想知道該文件何時被刪。

  1.   #define NOTE_WRITE      0x0002
復制代碼


NOTE_WRITE fflag表示進程想知道該文件內(nèi)容何時被改變。

  1.   #define NOTE_EXTEND     0x0004
復制代碼


NOTE_EXTEND fflag表示進程想知道該文件何時被擴展。

  1.   #define NOTE_ATTRIB     0x0008
復制代碼


NOTE_ATTRIB fflag表示進程想知道該文件屬性何時被改變。

  1.   #define NOTE_LINK       0x0010
復制代碼


NOTE_LINK fflag表示進程想知道該文件的鏈接計數(shù)何時被改變。當文件通過link函數(shù)調(diào)用進行硬鏈接的時候,它的鏈接計數(shù)就會改變。(詳情請參見man(2) link。)

  1.   #define NOTE_RENAME     0x0020
復制代碼


NOTE_RENAME fflag表示進程想知道該文件是否被重新命名了。

  1.   #define NOTE_REVOKE     0x0040
復制代碼


NOTE_REVOKE fflag表示對文件的訪問被revoke了。詳情請見man(2) revoke。

  1.   #define EVFILT_PROC     (-5)  /* attached to struct proc */
復制代碼


EVLILT_PROC過濾器被進程用來檢測發(fā)生在另外一個進程里的事件。所關(guān)心進程的PID存儲在ident成員中,fflags成員則被設成所關(guān)心的事件。返回時,事件將被放在fflags成員中。這些事件由下列事件按比特OR的方式設置:

  1.   #define NOTE_EXIT       0x80000000
復制代碼


NOTE_EXIT fflag用于檢測該進程何時退出。

  1.   #define NOTE_FORK       0x40000000
復制代碼


NOTE_FORK fflag用于檢測該進程何時調(diào)用fork。

  1.   #define NOTE_EXEC       0x20000000
復制代碼


NOTE_EXEC fflag用于檢測該進程何時調(diào)用exec函數(shù)。

  1.   #define NOTE_TRACK      0x00000001
復制代碼


NOTE_TRACK fflag讓kqueue去跟蹤一個跨越fork調(diào)用的進程。子進程返回時將設置fflags中的NOTE_CHILD標志,父進程的PID將放在data成員中。

  1.   #define NOTE_TRACKERR   0x00000002
復制代碼


當在跟蹤子進程的過程中有錯誤發(fā)生時,就會設置NOTE_TRACKERR fflag。這是一個僅用于返回的fflag。

  1.   #define NOTE_CHILD      0x00000004
復制代碼


NOTE_CHILD fflag在子進程內(nèi)設置。這是一個僅用于返回的fflag。

  1.   #define EVFILT_SIGNAL      (-6)
復制代碼


EVFILT_SIGNAL過濾器用于檢測是否有信號發(fā)送給該進程。每當有信號發(fā)送時這個過濾器就會檢測到,并把計數(shù)值放在data成員中。這包括設置了SIG_IGN標志的信號。事件將在執(zhí)行完常規(guī)的信號處理過程之后放到kqueue上。注意,這個過濾器將在內(nèi)部設置EV_CLEAR標志。

  1.   #define EVFILT_TIMER    (-7)
復制代碼


EVFILT_TIMER過濾器會給kqueue創(chuàng)建一個定時器,用于記錄消逝的事件。如果需要一個一次性的定時器,可以設置EV_ONESHOT標志。這個定時器是在ident成員中指定的,data成員用來指定以毫秒為單位的超時時間。返回值放在data成員中。注意,這個過濾器將在內(nèi)部設置EV_CLEAR標志。

kqueue操作

kqueue操作由所需的操作和標志以比特OR的方式進行設置。

  1.   #define EV_ADD          0x0001
復制代碼


EV_ADD操作向kqueue添加事件。由于kqueue中不允許出現(xiàn)重復,所以如果你想添加一個已經(jīng)存在的事件的話,現(xiàn)有事件將被新的添加操作覆蓋。注意,在添加事件的時候,它們已經(jīng)被默認激活了,除非你設置了EV_DISABLE標志。

  1.   #define EV_DELETE       0x0002
復制代碼


EV_DELETE操作從kqueue中刪除事件。

  1.   #define EV_ENABLE       0x0004
復制代碼


EV_ENABLE用于激活kqueue中的事件。注意,新添加的事件默認就是激活的。

  1.   #define EV_DISABLE      0x0008
復制代碼


EV_DISABLE禁止kqueue返回某個事件的信息。注意,kqueue并不會刪除過濾器。

kqueue操作標志

kqueue的操作標志定義如下。它們和上面列出的操作結(jié)合使用。它們是通過和所需操作進行比特OR來設置的。

  1.   #define EV_ONESHOT      0x0010
復制代碼


EV_ONESHOT標志用于通知kqueue只返回第一個。

  1.   #define EV_CLEAR        0x0020
復制代碼


EV_CLEAR標志用于通知kqueue,一旦進程從kqueue中獲取到了該事件就將該事件的狀態(tài)復位。

kqueue返回值

僅用于返回的值是放在kevent結(jié)構(gòu)體的flags成員中的。這些值的定義如下:

  1.   #define EV_EOF          0x8000
復制代碼


EV_EOF用于表示文件結(jié)束的情況。

  1.   #define EV_ERROR        0x4000
復制代碼


EV_ERROR用于表示有錯誤發(fā)生了。系統(tǒng)錯誤將被放到data成員中。

6.5 結(jié)論

本章研究了BSD中的描述符復用。作為一個程序員,你可以選擇三個接口:select、poll和kqueue。對于小數(shù)量的描述符來說,這三者的性能差不多,但是當描述符數(shù)量很大時,kqueue則是最好的選擇。除此之外,kqueue還可以檢測比I/O事件更為豐富的條件。它可以檢測信號、文件修改以及子進程相關(guān)的事件。在下一章中,我們將針對FreeBSD 5.x中的新特性,研究其它的獲取子進程信息和當前進程統(tǒng)計信息的方法。

[ 本帖最后由 雨絲風片 于 2006-2-27 12:15 編輯 ]

論壇徽章:
0
96 [報告]
發(fā)表于 2006-02-17 09:13 |只看該作者
原帖由 雨絲風片 于 2006-2-16 18:30 發(fā)表


“close on exec”是文件的一個標志,如果設置了這個標志,那么在執(zhí)行exec系統(tǒng)調(diào)用的時候,
對應的文件描述符就會關(guān)閉。

事實上,當父進程派生(fork系統(tǒng)調(diào)用)出子進程的時候,子進程會把父進程的文件描 ...


這么說比較對。
后面文章中有 If 1, the close-on-exec flag is set, and the file descriptor will be closed on a successful call to one of the exec functions.
建議全部改成close-on-exec

[ 本帖最后由 孫軒 于 2006-2-17 09:20 編輯 ]

論壇徽章:
0
97 [報告]
發(fā)表于 2006-02-17 09:16 |只看該作者
第三章中有一段
All the processes listed above, with the exception of init, are all implemented within the kernel. That means there is no regular binary program for these processes. These processes only resemble userland processes and because they are implemented within the kernel, they operate within the kernel's privileged mode. Such architecture results from various design considerations. For example, the pagedaemon process, which prevents thrashing, is only awakened when the system is low on memory. So if the system has lots of free memory then it never needs to be awakened. Thus, the advantage for running the pagedaemon in userland is that it can avoid using the CPU unless its really necessary. However it does add another process to the system and thus will need to be scheduled. But the scheduler calculations are very small and thus almost insignificant.

紅字的如何說?

論壇徽章:
0
98 [報告]
發(fā)表于 2006-02-17 09:27 |只看該作者
原帖由 孫軒 于 2006-2-17 09:16 發(fā)表
第三章中有一段
All the processes listed above, with the exception of init, are all implemented within the kernel. That means there is no regular binary program for these processes. Thes ...


前面幾句,我覺得意思應該是這樣的:

上面列出的所有進程,除了init之外,都是在內(nèi)核中實現(xiàn)的。也就是說,并不存在對應于這些進程的常規(guī)的二進制程序。這些進程僅僅是類似于用戶層進程而已,而且由于它們是在內(nèi)核中實現(xiàn)的,所以它們都將運行在內(nèi)核的特權(quán)模式中。

論壇徽章:
0
99 [報告]
發(fā)表于 2006-02-17 09:29 |只看該作者
原帖由 孫軒 于 2006-2-17 09:13 發(fā)表


這么說比較對。
后面文章中有 If 1, the close-on-exec flag is set, and the file descriptor will be closed on a successful call to one of the exec functions.
建議全部改成close-on-exec


嗯,這是一個特定的標志名稱,不譯為好,

論壇徽章:
0
100 [報告]
發(fā)表于 2006-02-17 09:42 |只看該作者
原帖由 雨絲風片 于 2006-2-17 09:27 發(fā)表


前面幾句,我覺得意思應該是這樣的:

上面列出的所有進程,除了init之外,都是在內(nèi)核中實現(xiàn)的。也就是說,并不存在對應于這些進程的常規(guī)的二進制程序。這些進程僅僅是類似于用戶層進程而已,而且由于它們是 ...


為什么要說類似于用戶層進程,本來他們就是內(nèi)核進程?讀起來總覺得不順。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP