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!

阻塞和非阻塞read/write

read函数 调用read函数从大
  • u012317833
  • u012317833
  • 2014年09月17日 16:13
  • 7752

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

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

linux设备驱动中的阻塞与非阻塞(一)

这两天在搞linux驱动的阻塞和非阻塞,困扰了两天,看了不少博客,有了点自己的想法,也不知是否对错,但还是写写吧,让各位大神给我指点指点。         首先说说什么是阻塞和非阻塞的概念:阻塞操作就...
  • u011756766
  • u011756766
  • 2015年11月23日 10:53
  • 1246

socket write read 阻塞 非阻塞

Linux调用read(int fd,char* buf,size_t len)、write(int fd,char* buf,size_t len)时,不管是作用于一个普通文件、管道或者socket...
  • u013827143
  • u013827143
  • 2015年07月09日 06:55
  • 1344

Linux下read和write的正确用法

我写这篇文章的目的是为了对read和write两个函数的用法做一个总结,同时提醒自己不要忘记: 一、原型介绍 #include ssize_t read(int fd, void *buf, s...
  • wswbdfei
  • wswbdfei
  • 2015年05月15日 11:37
  • 1251

Linux的write函数奥秘

write的奥秘     在Linux下我们在使用设备的时候,都会用到write这个函数,通过这个函数我们可以象使 用文件那样向设备传送数据。可是为什么用户使用write函数就可以把数据写到设备里...
  • fjt19900921
  • fjt19900921
  • 2012年12月13日 21:24
  • 9021

linux文件操作函数(open、write、read、close)

1. open()函数 功能描述:用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。 所需头文件:#include ,#include ,#include ...
  • u014650722
  • u014650722
  • 2016年06月02日 09:10
  • 7596

文件I/O函数(open,read,write,lseek,close)

大多数unix文件I/O只需要用到5个函数:open,read,write,lseek,close。这些函数都为不带缓存的I/O,不带缓存指的是每个read和write都调用内核中的一个系统调用。这些...
  • jiangqin115
  • jiangqin115
  • 2015年05月02日 12:28
  • 1035

Linux 中write()函数的出错情况及处理

write函数首先将进程需要发送的数据先放在进程缓冲区中,然后向socket的发送缓冲区进行拷贝,在此,可能出现这样情况,即当进程缓冲区中的数据量大于此时发送缓冲区中所能接受的数据量时,若此时处于阻塞...
  • yyxyong
  • yyxyong
  • 2017年03月17日 18:46
  • 164

linux c中write、read的用法

linux c中write、read的用法 ·write函数 1.功能 将数据写入已打开的文件内 2.相关函数 open,read,fcntl,close,lseek,sync,fsync,...
  • lyc_daniel
  • lyc_daniel
  • 2013年10月24日 15:02
  • 38563
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux下write操作原理、错误原因及处理方法
举报原因:
原因补充:

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