Linux IO函数

来源:互联网 发布:安卓ios数据互通手游 编辑:程序博客网 时间:2024/06/08 00:27

Linux网络编程中,针对套接字读写的函数有很多,下面介绍一些函数的常见用法;这里介绍的函数都是linux系统中的特有函数,与C标准库中的IO函数存在一定的区别。

1、read() 和 write()函数
  
read() 和 write() 函数是Linux中最基本的读写函数,可以用于各种数据的读写。

/* 返回值:成功则为读取或写入的字节个数,失败为-1;  * 定义: */#include <unistd.h>ssize_t read(int fd, void *buf, size_t nbyte); ssize_t write(int fd, const void* buf, size_t nbytes);/* 说明 * fd 为描述符,可以是文件描述符,也可以是套接字描述符; * buf 用于存储读取或写入的数据; * nbyte 记录字节数; * 根据不同的应用情况,返回值可能小于请求的字节数 */

一般来说,对于常规文件的读写不会阻塞,函数一定会在有限的时间内返回,但是从终端设备或网络读取时就不一定了,如果网络通信消息一直没有到达,那么读取函数就一直阻塞等待,终端还没有进行输入时,也是处于阻塞状态。
阻塞和非阻塞read/write ;

2、recv() 和 send() 函数

这两个函数类似于read() 和 write() 函数,但是这两个函数只用于套接字相关的数据处理。

/* 返回值:成功则为读取或写入的字节个数,失败为-1; * 定义: */ #include <sys/socket.h>ssize_t recv(int fd, void *buf, size_t n, int flags);ssize_t send(int fd, const void *buf, size_t n, int flags);/* 前面3个参数与read/write中参数一样,flags的值可为0或下面的值: * 1、MSG_DONTROUTE:绕过路由表查找,从直接连接的本机网络上处理数据; * 2、MSG_DONTWAIT:仅对本操作执行非阻塞; * 3、MSG_OOB:即将发送或接受带外数据; * 4、MSG_PEEK:查看已可读取的数据,且系统在recv或recvfrom返回后不丢弃这些数据; * 5、MSG_WAITALL:尚未读取请求数目的字节之前读取操作不要返回; */

3、readv() 和 writev() 函数

read() 和 write() 函数在处理数据时数据是连块的,即处理的数据是保存在一个连续的地址空间中的,但是有时候需要一次处理多个在不同地址空间的数据,readv函数可以将数据的输入分散到多个缓冲区中,称为分散读;writev函数可以将多个缓冲区的输出数据写入一个连续的缓冲区内,称为集中写;

/* 返回值:成功则为读入或写出的字节数,出错则为-1; * 定义: */#include <sys/uio.h>ssize_t readv(int fd, const struct iovec *iov, int iovcnt);ssize_t writev(int fd, const struct iovec *iov, int iovcnt);struct iovec{    void *iov_base;    size_t iov_len;}/* 说明: * 参数fd为文件或套接字描述符,iovcnt为结构指针iov中元素个数,最大一般不超过1024; * 结构iovec表示一个数据元素,iov_base为数据起始地址,iov_len为数据区大小; * 数组指针iov中有几个元素就有几块分散的缓冲区地址块; * 两个函数可以用于任何描述符。不仅限于套接字; */

参考:readv()和writev()函数;

4、recvmsg() 和 sendmsg() 函数

这两个函数只用于套件字的数据处理,是最通用的两个函数,包含前面的几个函数具有的各项功能。

/* 返回值:成功则为读入或写出的字节数,出错则为-1; * 定义: */#include <sys/socket.h>ssize_t  recvmsg(int sockfd, struct msghdr *msg, int flags);ssize_t  sendmsg(int sockfd, struct msghdr *msg, int flags);struct msghdr{    void        *msg_name;        /*protocol address*/    socklen_t   msg_namelen;      /*size of protocol address*/    struct iovec  *msg_iov;       /*scatter/gather array*/    int         msg_iovlen;       /*#elements in msg_iov*/    void        *msg_control;     /*ancillary data (cmsghdr struct)*/    socklen_t   msg_controllen;   /*length of ancillary data */    int         msg_flags;        /*flags returned by recvmsg()*/}/* 说明: * sockfd为套接字描述符,msg为结构参数指针,flags为标志; * msghdr中msg_name,msg_namelen为未连接的套接字地址及其长度; * 对于已连接的套接字msg_name直接设为NULL; * msgiov,msg_iovlen与readv函数第2,3个参数类似; * msg_control,msg_controllen为辅助数据,与结构cmsghdr相关; * msg_flags为标志,只有函数recvmsg使用; * flags用于输入一定的控制信息,而msg_falgs一般用于返回标志信息; * 函数send,recv;sendto,recvfrom,sengmsg,recvmsg都存在flags标志,部分标志在 * recv函数介绍时已列出,其它参考UNIX网络编程卷1; */

5组IO函数比较,yes表示符合说明,空格表示不符合。

函数 任何描述符 仅套接字描述符 单个读写缓冲区 分散/集中读写 可选标志 可选对端地址 可选控制信息 read,write yes yes readv,writev yes yes send,recv yes yes yes sendto,recvfrom yes yes yes yes sendmsg,recvmsg yes yes yes yes yes

上面介绍的几组IO函数都是围绕描述符工作的,通常是作为UNIX内核中的系统调用实现;执行IO的另一种方式是使用标准IO函数库,由ANSI C标准规范,便于移植到支持C的非Unix系统上。

  标准IO函数也可以用于套接字上:通过调用fdopen从任何描述符创建一个标准IO流;相反可以通过fileno获取任何一个给定标准IO流的描述符。
  标准IO函数执行以下3类缓冲:
  1、完全缓冲,只在下列情况下才发生IO(数据输出):缓冲区满,进程显式调用fflush,进程调用exit终止自身;标准缓冲区大小一般为8192字节。
  2、行缓冲,只在下列情况下才发生IO:碰到一个换行符,进程调用fflush,进程调用exit终止自身。
  3、不缓冲,每次调用标准IO输出函数都发生IO。
  标准IO函数大多数Unix实现遵循以下规则:
  - 标准错误输出总是不缓冲;
  - 标准输入标准输出完全缓冲,除非他们指代终端设备(这种情况下行缓冲);
  - 所有其他IO流都是完全缓冲,除非他们指代终端设备(这种情况下行缓冲);

因为套接字并不是终端设备,因此在用标准IO处理套接字数据IO时,需要考虑缓冲问题,然而这样可能会引起一些潜在问题,所以一般情况下尽量避免在套接字上使用标准IO函数库。

0 0
原创粉丝点击