Linux IO函数的使用和区别
Linux系统中的IO函数主要有read、write、recv、send、recvmsg、sendmsg、readv、writev,本篇主要介绍他们的使用以及区别。
read函数:
#include <unistd.h>
ssize_t read(int fd,void *buf,size_t count);
read函数从文件描述符fd对应的文件中,读取count字节,放在buf缓冲区。如果count为0,read返回为0,不进行其他操作;如果count的值大于SSIZE_MAX,结果不能预料。在读取成功的时候,文件对应的读取位置指针,,向后移动位置,大小为成功读取的字节数。
如果read执行成功,访回读取的字节数;当返回为-1时候,读取函数有错误发生。如果已经达到文件的末尾,返回0;其中,ssize数据类型是不同于int、long类型,它是符号数,具体实现时,可能是int,也可能是long。
write函数:
#include <unistd.h>
ssize_t write(int fd,const void *buf,size_t count);
参数含义与read类似。
recv函数:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int s,void *buf,size_t len,int flags);
recv函数用于接受数据,该函数从套接字s中接收数据放到缓冲区buf中,buf长度为len,操作的方式由flags指定,第一个参数s是套接字文件描述符,它是由系统调用socket函数返回。第二个参数buf是一个指针,指向接收网络的缓冲区。第三个参数len表示缓冲区的大小,以字节为单位。第四个参数flags用于设置接收数据的方式:
recv()函数flasgs的值及含义 | |
MSG_DONTWAIT | 非阻塞,立即返回,不等待 |
MSG_ERRQUEUE | 错误消息从套接字错误队列中接收 |
MSG_OOB | 接收外部数据 |
MSG_PEEK | 查看数据,不进行数据缓冲区的清空 |
MSG_TRUNC | 返回所有数据,即使指定的缓冲区过小 |
MSG_WAITALL | 等待所有消息 |
MSG_DONTWAIT:这个标志将单个IO操作设为非阻塞,而不需要在套接字上打开非阻塞标志,执行IO,然后关闭非阻塞标志。
MSG_ERRQUEUE:该错误的传输依赖于所使用的协议。
MSG_OOB:这个标志可以接收带外的数据,而不是接收一般数据。
MSG_PEEK:这标志查看可读的数据,在recv函数执行后,内核不会将这些数据丢弃。
MSG_TRUNC:在接收数据后,如果用户的缓冲区大小不足以完全复制缓冲区里的数据,则将数据截掉,仅靠复制用户缓冲区大小的数据,其他的数据将丢弃。
MSG_WAITALL:告诉内核在没有读到请求的字节数之前不要读操作返回。如果系统支持这个标志,可以去掉readn()函数而用下面的替代:
#define readn(fd,ptr,n) recv(fd,ptr,n,MSG_WAITALL).
即使设置了MSG_WAITALL,如果发生以下情况:a扑捉一个信号;b连接终止;c在套接字上发生错误,这个函数返回的字节数仍然比请求的少。
当指定MSG_WAITALL标志时,函数会复制与用户指定的长度相等的数据。如果内核中的数据不能满足要求,会一直等待到数据足够的时候才返回。
函数recv()的返回值是成功接收到的字节数,当返回值为-1时错误发生。
recv函数errno的值及含义 | |
EAGAIN | 套接字定义为非阻塞,而操作采用了阻塞方式;或者定义了超时时间到了,而没有接收到数据 |
EBADF | 参数s不是合法的描述符 |
ECONNREFUSED | 远程主机不允许此操作 |
EFAULT | 接收缓冲区的指针,在此进程之外 |
EINTR | 接收到中断信号 |
EINVAL | 传递了不合法的参数 |
ENOTCONN | 套接字s表示流式套接字,此套接字没有连接 |
ENOTSOCK | 参数不是套接字描述符 |
recv()通常用于TCP,UDP使用recvfrom函数接收数据,当然在数据报套接字绑定了地址和端口后,也可以使用recv函数接收数据。
recv()从内核的接收缓冲区中复制数据到用户指定的缓冲区,当内核中的数据比指定的缓冲区小时,一般情况下(没有采用MSG_WAITALL标志)会复制缓冲区中的所有数据到用户缓冲区,并返回数据的长度。当内核中的数据比指定的缓冲区多时,会将用户指定的长度的接收缓冲区中的数据复制到用户指定地址,其余的数据需要下次调用接收函数时再复制,内核在复制用户指定的数据后,会销毁已经复制完毕的数据,并进行调整。
send函数:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int s,const void*buf,size_t len,int flags);
send函数将缓冲区buf中的大小为len的数据,通过套接字文件描述符s按照flasg指定的方式发生出去(其中的含义与recv()中一致),它的返回值是成功发生的字节数。
由于用户缓冲区buf中的数据通过send发送,不一定能够全部发送出去,所以要检查send()返回值。当send()的返回值小于len时,表面缓冲区中仍有部分数据没有发送成功,这时需要重新发送剩余部分的数据。通常的剩余数据发送方式是对原来的buf中的数据位置进行偏移,偏移的大小为已经发送成功的字节数。
当send()返回-1时,就错误了。
函数send()只能用于套接字处于连接状态的描述符,之前必须用connect()函数或者其他函数进行连接。对于send和write之间的差别是表示发送方式flag,当flag为0时,send()和write()完全一样的,且send(s,buf,len,flags)和sendto(s,buf,len,flags,NULL,0)是等价的。
readv函数:
#include <sys/uio.h>
ssize_t readv(int s,const struct iovec*vector,int count);
read()可以接收多个缓冲区的数据。readv函数从套接字描述符s中读取count块的数据放在缓冲区向量vector中。返回值为成功接收到的数据的字节数,当-1时,错误发生。
其中的参数vector为一个向量的指针,结构struct iover在文件<sys/uio.h>定义:
struct iovec
{
void*iov_base; // 向量的缓冲区地址
size_t iov_len; // 大小,字节为单位
}
在调用readv的时候必须指定iovec的iov_len长度,将值放在iov_len中。参数vector指向一块结构vector的内存,大小count定。如下图,其中阴影部分是需要设置的。
writev函数:
#include <sys/uio.h>
ssize_t writev(int s,const struct iovec*vector,int count);
//// 是不是觉得和readv一样
总结:
下表总结了各个函数的区别、特点:O标记的为具备此种属性
Linux IO函数的使用和区别的更多相关文章
- Linux C _exit函数与exit函数的联系与区别
一.联系 1.功能上,_exit和exit函数都是让进程正常退出,即关闭进程所打开的文件描述符,释放已占用内存和其他资源. 二.区别 1._exit函数在头文件unistd.h中声明,而exit在头文 ...
- linux网络编程之IO函数
Linux操作系统中的IO函数主要有read(),write(),recv(),send(),recvmsg(),sendmsg(),readv(),writev(). 接收数据的recv()函数 # ...
- Linux网络IO函数以及TCP连接函数包装
标准I/O VS 网络IO 标准I/O又称为标准I/O流,从某种意义上讲是全双工的,因为程序能够在同一个流上执行输入和输出. Unix/Linux对网络的抽象是一种称为套接字的文件类型.和任何Unix ...
- 文件IO函数和标准IO库的区别
摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...
- 【知乎网】Linux IO 多路复用 是什么意思?
提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...
- Linux IO模型和网络编程模型
术语概念描述: IO有内存IO.网络IO和磁盘IO三种,通常我们说的IO指的是后两者. 阻塞和非阻塞,是函数/方法的实现方式,即在数据就绪之前是立刻返回还是等待. 以文件IO为例,一个IO读过程是文件 ...
- Linux io Model
socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调 ...
- linux io的cfq代码理解
内核版本: 3.10内核. CFQ,即Completely Fair Queueing绝对公平调度器,原理是基于时间片的角度去保证公平,其实如果一台设备既有单队列,又有多队列,既有快速的NVME,又有 ...
- Linux IO性能分析blktrace/blk跟踪器
关键词:blktrace.blk tracer.blkparse.block traceevents.BIO. 本章只做一个记录,关于优化Block层IO性能方法工具. 对Block层没有详细分析,对 ...
随机推荐
- 让 “微软雅黑” 在IE6下完美显示
微软雅黑可以说是网页中最常见的字体了,但是往往在IE8+的浏览器上调试得很好,到了IE6则会变成默认的"宋体". 因为宋体字体宽度通常比雅黑的要宽,有时候会把页面都布局挤乱. 为了 ...
- KnockoutJS 3.X API 第四章 表单绑定(10) textInput、hasFocus、checked绑定
textInput绑定目的 textInput绑定主要用于<input>或者<textarea>元素.他提供了DOM和viewmodel的双向更新.不同于value绑定,tex ...
- KnockoutJS 3.X API 第五章 高级应用(4) 自定义处理逻辑
在典型的Knockout应用程序中,DOM元素是动态添加和删除的,例如使用模板绑定或通过控制流绑定(if,ifnot,with和foreach). 当创建自定义绑定时,通常需要添加清除逻辑,当Knoc ...
- struts之动态方法调用改变表单action属性
一.动态方法调用(DMI:Dynamic Method Invocation) ⒈struts2中同样提供了这个包含多个逻辑业处理的Action,这样就可以在一个Action中进行多个业务逻辑处理 ...
- Java多线程系列--“基础篇”04之 synchronized关键字
概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...
- 决战JS
经过这几日的学习,测试和摸索,算是了解了一些关于javascript 的相关知识吧.学习过程中做出了一些小DEMO,现总结一下实现这些DEMO的基本思路,如有不妥或更为简便的方法,还希望大神拍砖,共同 ...
- spring学习遇到的问题汇总
1.spring注解路由方面的误解 我一直以为在web.xml中配置拦截*.action后,在注解路由的时候必须要xxxx.action. 刚才发现,访问的时候xxxx.action,然后@Reque ...
- STM32L系列单片机内部EEPROM的读写
STM32L系列单片机内部提供了EEPROM存储区域,但实质上,其FLASH也是EEPROM类型,只不过有一块区域被开放出来专门用作EEPROM操作而已.STM32L的EEPROM使用寿命设计为100 ...
- ASP.NET MVC系列:开始
创建Asp.Net MVC项目 从visual studio主界面开始菜单中点击“新建项目”
- ASP.NET MVC系列:添加模型
模型(Model)是应用程序中用于处理应用程序数据逻辑的部分;通常模型对象在数据库中存取数据 添加模型类 在解决方案中右击Models文件夹,然后选择“添加”,在“添加”项里选择“类”:或者选中Mod ...