linux下write操作原理、错误原因及处理方法

转载 2016年08月29日 17:22:44
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!

相关文章推荐

c/c++ 学习-read 函数和 write 函数

read 函数和 write 函数 最近开始从事搜索引擎的工作,所以又重新开始了c/c++的旅程,时隔4年 不得不复习一下c/c++其中的内容,以下内容有网上别的朋友发表的,也有我自己总结的. ...

网络编程(24)—— linux中write和read函数的阻塞试验

刚刚接触网络编程时,很容易被客户端和服务器之间的交互搞晕,例如各种函数的阻塞和非阻塞就让人头疼。例如在我的印象中linux中用于用于对文件描述符进行读写的write()函数和read()函数是非阻塞函...

阻塞和非阻塞read/write

read函数 调用read函数从大

linux文件设备与I/O:read/write函数 与 阻塞 Block

一,read 函数从打开的设备或文件中读取数据 #include        ssize_t read(int fd, void *buf, size_t count);     ...

Linux中的可重入函数和不可重入函数

Linux中的可重入函数和不可重入函数                                 &#...
  • ASKLW
  • ASKLW
  • 2016-10-13 09:13
  • 372

linux下write操作原理、错误原因及处理方法

1. write函数介绍 (1)文件I/O与标准I/O之争:       根据《UNIX环境高级编程》中介绍,文件I/O与标准I/O之间的差别主要有以下几点:其一,文件I/O是在系统的内核中实现的...

fstat、stat和lstat用法

stat系统调用系列包括了fstat、stat和lstat,它们都是用来返回“相关文件状态信息”的,三者的不同之处在于设定源文件的方式不同。首先介绍的是一个非常重要的结构体类型,名字叫做struct ...

linux 下各errno的意义

strerror(errno):获取errno对应的错误/****************************获取错误代码描述**************/#include /* for str...

std::vector介绍

vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vec...
  • armman
  • armman
  • 2007-02-04 00:15
  • 49064

GRE 协议rfc总结

一、简介 GRE(Generic Routing Encapsulation):通用路由封装。 GRE是一个通用的路由封装协议,它描述在任意的网络层之上封装另一个网络协议。 RFC:2784. 二...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)