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函数的使用和区别的更多相关文章

  1. Linux C _exit函数与exit函数的联系与区别

    一.联系 1.功能上,_exit和exit函数都是让进程正常退出,即关闭进程所打开的文件描述符,释放已占用内存和其他资源. 二.区别 1._exit函数在头文件unistd.h中声明,而exit在头文 ...

  2. linux网络编程之IO函数

    Linux操作系统中的IO函数主要有read(),write(),recv(),send(),recvmsg(),sendmsg(),readv(),writev(). 接收数据的recv()函数 # ...

  3. Linux网络IO函数以及TCP连接函数包装

    标准I/O VS 网络IO 标准I/O又称为标准I/O流,从某种意义上讲是全双工的,因为程序能够在同一个流上执行输入和输出. Unix/Linux对网络的抽象是一种称为套接字的文件类型.和任何Unix ...

  4. 文件IO函数和标准IO库的区别

    摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...

  5. 【知乎网】Linux IO 多路复用 是什么意思?

    提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...

  6. Linux IO模型和网络编程模型

    术语概念描述: IO有内存IO.网络IO和磁盘IO三种,通常我们说的IO指的是后两者. 阻塞和非阻塞,是函数/方法的实现方式,即在数据就绪之前是立刻返回还是等待. 以文件IO为例,一个IO读过程是文件 ...

  7. Linux io Model

    socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调 ...

  8. linux io的cfq代码理解

    内核版本: 3.10内核. CFQ,即Completely Fair Queueing绝对公平调度器,原理是基于时间片的角度去保证公平,其实如果一台设备既有单队列,又有多队列,既有快速的NVME,又有 ...

  9. Linux IO性能分析blktrace/blk跟踪器

    关键词:blktrace.blk tracer.blkparse.block traceevents.BIO. 本章只做一个记录,关于优化Block层IO性能方法工具. 对Block层没有详细分析,对 ...

随机推荐

  1. Java基础-继承-编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight。小车类Car是Vehicle的子类,其中包含的属性有载人数 loader。卡车类Truck是Car类的子类,其中包含的属性有载重量payload。每个 类都有构造方法和输出相关数据的方法。最后,写一个测试类来测试这些类的功 能。

    #29.编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight.小车类Car是Vehicle的子类,其中包含的属性有载人数 loader.卡车类T ...

  2. WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 菜单M ...

  3. 十款让 Web 前端开发人员更轻松的实用工具

    这篇文章介绍十款让 Web 前端开发人员生活更轻松的实用工具.每个 Web 开发人员都有自己的工具箱,这样工作中碰到的每个问题都有一个好的解决方案供选择. 对于每一项工作,开发人员需要特定的辅助工具, ...

  4. 15 Best Responsive HTML5 Frameworks 2014

    Best HTML5 frameworks are most popular because with the use of these frameworks you can create websi ...

  5. NODE.JS之我见

    NODE.JS之我见 先说说为什么有这篇文章,关注NODE.JS 也有一段时间了,不敢说大彻大悟,但是对于NODE.JS能干什么,还是有一定的了解,笔者多年以前就研究过JavaScript引擎V8,可 ...

  6. Elasticsearch 安装与启动

    平台支撑 ES支持在不同的平台上运行,下面这幅图中,对号标记的是经过测试的平台,其他的也可以运行,但是可能会出现BUG. 下载与安装 在官网下载地址就可以进行下载. 然后解压,进入bin目录,运行下面 ...

  7. 第17/24周 悲观并发控制(Pessimistic Concurrency)

    大家好,欢迎回到性能调优培训.今天标志着第5个月培训的开始,这个月我们会谈论SQL Server里的锁.阻塞和死锁(Locking, Blocking, and Deadlocking). SQL S ...

  8. SQL Server安全(8/11):数据加密(Data Encryption)

    在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切.但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念.这篇文章提供了基础,因此你可以对SQL Se ...

  9. BZOJ1088扫雷Mine 解析报告

    1088: [SCOI2005]扫雷Mine Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的扫 ...

  10. EDNS

    随着业务的复杂化和多样化,RFC1035中定义的DNS消息格式和它支持的消息内容已经不足以满足一些DNS服务器的需求,于是,RFC2671中提出了一种扩展DNS机制EDNS(Extension Mec ...