linux下write操作原理、錯誤原因及處理方法
1. write函式介紹
(1)檔案i/o與標準i/o之爭:
根據《unix環境高階
程式設計》中介紹,檔案i/o與準備i/o之間的差別主要有以下幾點:其一,檔案i/o是在
系統的核心中實現的,而標準i/o函式則提供了檔案i/o函式的乙個完整的帶緩衝的替代品。因此說,檔案i/o是一種較低階的i/o操作函式,而標準i/o則是一種相對較高的i/o。標準i/o函式將開啟的檔案模型抽象成「檔案流」。常見的檔案i/o有:open, write, create, close, read等;標準i/o有:fopen,freopen, fdopen, getc等。第二,標準i/o一般是磁碟和終端裝置i/o的首選,而當試圖用於網路i/o,即對網路socket進行操作時,應該應用檔案i/o。
(2)檔案i/o的阻塞與非阻塞(以write函式為例): www.2cto.com
前面已經說過,檔案i/o是一種帶有緩衝區的操作函式,而在實際的操作過程中,勢必會出現阻塞與非阻塞相關的問題。下面以write操作來介紹阻塞與非阻塞這兩種情況:
write函式首先將程序需要傳送的資料先放在程序緩衝區中,然後向socket的傳送緩衝區進行拷貝,在此,可能出現這樣情況,即當程序緩衝區中的資料量大於此時傳送緩衝區中所能接受的資料量時,若此時處於阻塞模式,應用程序將會被掛起,直到程序緩衝區中的資料全部拷貝到傳送緩衝區中,注意此時核心也不會返回write函式,因此,在阻塞模式下,若write函式正常返回,這也並不代表資料已經完成被對方程序接收,至多只能說明資料已經被傳送緩衝區完全接受;若是處於非阻塞模式,此時write操作將會失敗,核心會立即返回eagain錯誤,在此需要宣告的是,有時候在某些地方說會返回ewouldblock錯誤,其實二者本質一樣,只是分別用於不同的系統罷了,前者主要是出現於gnu系統,,而後者主要出現在類bsd系統。 www.2cto.com
【引申1】阻塞與非阻塞的轉換:切換socket fd的阻塞標誌。
int fcntl(int fd , int cmd)
int fcntl(int fd,int cmd,long arg)
其中cmd代表要操作的命令,常見有:
f_getfl:取得fd的當前狀態標誌
f_setfl:設定fd的當前狀態標誌
[cpp]
flags = (long) fcntl(pc->fd, f_getfl);
bflags = flags & ~o_nonblock; /* clear non-block flag, i.e. block */
fcntl(pc->fd, f_setfl, bflags);
【引申2】
linux中傳送快取大小的檢視:
sysctl -a | grep net.ipv4.tcp_wmem
net.ipv4.tcp_wmem = 4096 16384 81920 (這三個值分別代表傳送緩衝區的最少位元組數,預設位元組數以及最多位元組數) www.2cto.com
2. write常見錯誤以及原因分析:
前面已經說過eagain錯誤出現的原因,下面主要講解epipe錯誤是在何種情景下產生的。
我們知道tcp連線需要三次握手,而退出需要四個過程,而epipe則是產生於程序socket的退出過程中,對應上面的原理圖,若b端的程序已經主動關閉(傳送fin),但是a端因為各種原因(主要是未同步),未能知曉並仍然向對方傳送資料,此時a端核心會返回epipe錯誤,它會傳送sigpipe訊號給程序a,預設情況下,程序將會自動退出。
最近在做專案過程中,因為apache server端的keep-alive配置時間過短,導致過早發出fin,而使得client端的socket出現epipe錯誤,最後將keep-alive時間配置稍長點,一切問題ok!
檔案程式設計 write和複製操作
1 write 寫 系統呼叫向開啟的檔案寫資料,顧名思義往檔案寫東西,這裡也是需要緩衝區,獲取你要寫的東西到緩衝區,再從緩衝區寫入到檔案當中 這裡write往檔案寫資料是通過二進位制的形式寫的 1 write 格式 include ssize t write int fd,const void bu...
linux驅動中的write函式
用檔案那樣向裝置傳送資料。可是為什麼使用者使用write函式就可以把資料寫到裝置裡面 去,這個過程到底是怎麼實現的呢?這個奧秘就在於裝置驅動程式的write實現中,這裡我結合一些源 來解釋如何使得一 個簡簡單單的write函式能夠完成向裝置裡面寫資料的複雜過程。這裡的源 主要來自兩個地方。第一是or...
linux驅動中的write函式
linux下我們在使用裝置的時候,都會用到write這個函式,通過這個函式我們可以象使 用檔案那樣向裝置傳送資料。可是為什麼使用者使用write函式就可以把資料寫到裝置裡面 去,這個過程到底是怎麼實現的呢?這個奧秘就在於裝置驅動程式的write實現中,這裡我結合一些源 來解釋如何使得一 個簡簡單單的...