linux write方法,linux下write操作原理、錯誤原因及處理方法

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操作來介紹阻塞與非阻塞這兩種情況:

aHR0cDovL3VwLjJjdG8uY29tLzIwMTIvMDgxMC8yMDEyMDgxMDAyMTAxNTQxOC5qcGc=

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!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值