《unix環境進階編程》 讀書筆記 (1)

來源:互聯網
上載者:User

標籤:des   style   blog   http   os   io   使用   ar   for   



近來讀書,做些筆記,來年好翻翻。
本文所使用的作業系統為 CentOS7.0,如果不想裝雙系統的可以裝虛擬機器,可以參考這裡:
http://blog.csdn.net/alex_my/article/details/38142229

當然啦,直接裝個再好不過了。
File I/O
1 file descriptor
// 查看當前session中的fd數量限制 ulimit -n
// 修改當前session中的fd數量限制ulimit -n your_need
可以在一個終端使用以上命令,另外再開啟一個進行查看。
在程式中,可以使用系統函數進行修改#include <sys/resource.h>
struct rlimit{     rlim_t rlim_cur;     rlim_t rlim_max;}
int getrlimit(int resource, struct rlimit* rlim);int setrlimit(int resource, const struct rlimit* rlim);
ext:
resource可選擇的有:
RLIMIT_CORE: 設定core檔案的大小,0表示禁止建立core檔案。一個程式崩潰的時候,會在指定目錄產生一個core檔案,主要是用於調試。
RLIMIT_CPU: 設定每秒內的cpu Time,如果超過這個限制,則會發送SIGXCPU訊號。
RLIMIT_DATA: 設定進程中data segment大小,單位為bytes。如果超過這個限制,malloc()會失敗。具體關於data segment 參考這裡: http://blog.csdn.net/fatshaw/article/details/6294557
RLIMIT_FSIZE: 設定進程內檔案最大長度,如果超過這個長度,則產生SIGXFSZ訊號。如果線程阻塞,或者進程抓取或者忽略了這個訊號,則會從底部減少檔案大小並設定EFBIG錯誤。
RLIMIT_NOFILE: 設定檔案描述符大小,比最大檔案描述符大一,如果超過了這個限制,則申請檔案描述符失敗,並且設定EMFILE錯誤。
RLIMIT_STACK: 設定進程最大堆棧,單位為bytes。
RLIMIT_AS: 設定進程可用記憶體,單位為bytes。如果超過這個限制,malloc()和mmap()將會失敗,並設定ENOMEM錯誤。
2 lseek function
off_t lseek(int fildes, off_t offset, int whence)    移動讀/寫位移量 
whence可選擇的有:
SEEK_SET: 檔案位移量設定為 offset
SEEK_CUR: 檔案位移量設定為 當前位移量 + offset
SEEK_END: 檔案位移量設定為 檔案大小 + offset
擷取當前位移量的方法:
offset value = lseek(fd, 0, SEEK_CUR);
當操作的檔案為 pipe, FIFO, socket時,返回-1,並設定錯誤為ESPIPE。
其它錯誤可以man 3 lseek查閱
程式用例:test2.1.cc
#include <stdio.h>#include <unistd.h>
int main(int argc, char** argv){     if(lseek(STDIN_FILENO, 0, SEEK_CUR) == -1)          printf("Seek Failed\n");     else          printf("Seek OK\n");
     return 0;}
g++ -o test2.1 test2.1.cc
./test2.1輸出:Seek Failed。原因:參數1 fildes必須是已經開啟的檔案描述符.
./test2.1 < /etc/passwd輸出:Seek OK


3 File Sharing -- close-on-exec
當使用fork建立子線程後,子線程獲得父進程的資料空間,堆和棧的副本,也包含檔案描述符,共用共同的開啟檔案標記,當前的位移量等。
當在子進程中調用exec執行另一個程式時,替換了當前進程的本文,資料,堆和棧,即原先的子進程中的檔案描述符丟失了(並未關閉),無法再關閉這些在子進程中不再使用到的檔案描述符。而檔案描述符是系統珍貴資源,數量有限。
一種辦法是在執行exec之前先把這些檔案描述符關閉,但在複雜的系統中,這是一件比較麻煩的事情。
另一種辦法是開啟檔案的時候就指定好,當子進程執行exec的時候,這個檔案關閉。即所謂的close-on-exec。
// 通過fcntl實現int flags = fcntl(fd, F_GETFD);flags |= FD_CLOEXEC;fcntl(fd, F_SETFD, flags);
// 在建立或開啟檔案的時候指定int fd = open("text.log", O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC);
具體查看man 2 open或者man 2 creat

4 Atomic Operations -- O_APPEND
有這樣一個例子:
程式A和程式B對同一個檔案進行寫操作。程式A先寫入1500位元組,程式B開啟,調用lseek,得到檔案末尾為1500, 寫入100位元組。程式A執行,此時,程式A的file table entry記錄檔案末尾為1500,寫入100位元組。此時,覆蓋了程式B寫入的內容。
解決方案:
// 每次write的時候,都調用lseek,擷取檔案末尾位移量。
// 在建立或者開啟的時候設定參數O_APPEND, 設定此標記後,每次調用write,檔案位移量都會更新到檔案末尾。

5 Atomic Operations -- pthread, pwrite
對一個檔案指定位置進行寫入或者讀取,有兩個步驟:
-1: 調用lseek,設定位移量-2: 調用read或者write操作。
兩步操作在過程中可能被打斷,得到的不是需要的結果。
而pthread/pwrite可以解決這個問題:
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); 
使用pthread/pwrite並不會改變當前檔案位移量。
當開啟檔案時指定了參數O_APPEND時,pwrite總是添加到檔案末尾,而不會按照參數offset指定位置。 
6 dup, dup2, dup3
int dup(int oldfd);
int dup2(int oldfd, int newfd);
int dup3(int oldfd, int newfd, int flags);

這些系統調用將會建立一個檔案描述符的副本。
dup將返回一個未使用的最小的檔案描述符
dup2將返回一個指定的檔案描述符。如果oldfd指定了檔案描述標記(close-on-exec),newfd並不會擁有。需要重新使用fcntl指定。
如果newfd已經存在,則會先被關閉。如果oldfd和newfd數值相同,且oldfd是有效檔案描述符,則dup2不做任何事情,返回newfd。如果oldfd和newfd數值相同,且oldfd是無效的檔案描述符,則調用失敗, 不會調用newfd關閉的步驟。
dup3效果與dup2相同,但可以通過指定flags為O_CLOEXEC,使得newfd具有close-on-exec功能。
如果oldfd和newfd數值相同,則調用失敗,並設定錯誤為INVAL。
7 fcntl function
#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

可以改變一個已經開啟的檔案的屬性 
其中, cmd 可選擇的有:
F_DUPFD: 返回一個大於等於參數3且最小未使用的檔案描述符,與fd共用一個檔案表項,如果fd有檔案描述符標誌(目前只有一個,FD_CLOEXEC),則此標誌會被清除。可以查看dup2相關。
F_DUPFD_CLOEXEC: (since Linux 2.6.24) 效果等同於F_DUPFD,但會給返回的檔案描述符添加close-on-exce標誌。
F_GETFD: 返回fd的檔案描述符標誌。目前僅有一個標誌:FD_CLOEXEC
F_SETFD: 將參數3設定為fd的檔案描述符標誌。
F_GETFL: 返回fd的檔案狀態標誌,即open時候的flags標記。               O_RDONLY, O_WDONLY, O_RDWR, O_EXEC, O_SEARCH, O_APPEND, O_NONBLOCK, O_SYNC, O_DSYNC, O_RSYNC, O_FSYNC, O_ASYNC
F_SETFL: 設定fd的檔案狀態標誌,可設定的值有(Linux下, 本機為CentOS7.0, Mac和FreeBSD有不同的選項):
O_APPEND, 每次write的時候都將添加到檔案的末尾,效果等同於open的時候添加O_APPEND標記。
O_NONBLOCK, 非阻塞IO,如果read沒有資料可讀,或者write操作阻塞,則返回-1並且設定錯誤為EAGAIN。           O_ASYNC, 當IO可用時,允許發送SIGIO訊號到進程組。
O_DIRECT, 直接進行檔案IO,系統盡量不進行緩衝。具體可參考以下連結:http://blog.csdn.net/zhangxinrun/article/details/7635570http://laokaddk.blog.51cto.com/368606/699563/http://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html                                                       O_NOATIME, 讀檔案不改變最後訪問時間。
另外還有F_GETOWN, F_SETOWN, F_GETOWN_EX等等,具體查看fcntl(2)
8 ioctl function
ioctl 是裝置驅動程式中對裝置的IO通道進行管理的函數。不同的裝置驅動都會定義自己的ioctl指令。後邊講到通訊端的時候再具體詳述。
再詳細點的講述可以看這裡:http://www.linuxidc.com/Linux/2007-12/9623.htm



參考:
http://blog.csdn.net/fatshaw/article/details/6294557
http://laokaddk.blog.51cto.com/368606/699563/
http://blog.csdn.net/zhangxinrun/article/details/7635570
http://www.ukuug.org/events/linux2001/papers/html/AArcangeli-o_direct.html
http://www.linuxidc.com/Linux/2007-12/9623.htm

《unix環境進階編程》 讀書筆記 (1)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.