代码开源(2)——UNIX 健壮I/O函数
来源:互联网 发布:金融的网络销售 编辑:程序博客网 时间:2024/06/05 17:38
摘自《深入理解计算机系统》一书,几个IO读写的封装函数。一共是两类,一是无缓冲的输入输出函数;二是带缓冲的输入函数。这几个函数有一个共同点,就是比较好的处理了“不足值”的情况。所谓“不足值”是指read和write函数传送的字节比应用程序要求的要少。下面几种情况可能会出现不足值:(1)读时遇到EOF;(2)从终端读文本行;(3)读和写网络套接字,内部缓冲约束和较长的网络延迟会引起read和write返回不足值。
这几个函数自动处理了上述提到的不足值,在像网络程序这样容易出现不足值的应用中,提供了方便、健壮和高效的I/O。
#ifndef RIO_H_#define RIO_H_#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <string.h>#define RIO_BUFSIZE 8192typedef struct{int rio_fd;int rio_cnt;char *rio_pbuf;char rio_buf[RIO_BUFSIZE];}rio_t;//无缓冲输入输出ssize_t rio_readn(int fd, void *usrbuf, size_t n);ssize_t rio_writen(int fd, void *usrbuf, size_t n);//带缓冲输入void rio_readinitb(rio_t *pr, int fd);ssize_t rio_read(rio_t *pr, char *usrbuf, size_t n);ssize_t rio_readnb(rio_t *pr, void *usrbuf, size_t n);ssize_t rio_readlineb(rio_t *pr, void *usrbuf, size_t maxlen);//无缓冲输入函数//成功返回输入的字节数,若EOF返回0,出错返回-1ssize_t rio_readn(int fd, void *usrbuf, size_t n){size_t nleft = n;ssize_t nread;char *pbuf = usrbuf;while(nleft > 0){//在某些系统中,当处理程序捕捉到一个信号时,被中断的慢系统调用(read, write, accept)//在信号处理程序返回时不再继续,而是立即返回给客户一个错误条件,并将errno设置成为EINTRif((nread = read(fd, pbuf, nleft)) < 0){if(errno == EINTR)nread = 0; //中断造成的,再次调用readelsereturn -1; //出错}else if(nread == 0) //到了文件末尾break;nleft -= nread;pbuf += nread;}return n - nleft;}//无缓冲输出函数//成功返回输出的字节数,出错返回-1ssize_t rio_writen(int fd, void *usrbuf, size_t n){size_t nleft = n;ssize_t nwritten;char *pbuf = usrbuf;while(nleft > 0){//注意这里是小于等于,磁盘已满或超过一个给定进程的文件长度限制就出错了if((nwritten = write(fd, pbuf, nleft)) <= 0){if(errno == EINTR)nwritten = 0;elsereturn -1;}nleft -= nwritten;pbuf += nwritten;}return n; //注意与输入的区别,write不会返回不足值}//初始化rio_t结构void rio_readinitb(rio_t *pr, int fd){pr->rio_fd = fd;pr->rio_cnt = 0;pr->rio_pbuf = pr->rio_buf;}//带缓存函数 供内部调用ssize_t rio_read(rio_t *pr, char *usrbuf, size_t n){int cnt;while(pr->rio_cnt <= 0) //内部缓冲空了,进行重填{pr->rio_cnt = read(pr->rio_fd, pr->rio_buf, sizeof(pr->rio_buf)); //读到内部缓冲中if(pr->rio_cnt < 0) {if(errno != EINTR) //出错返回return -1;}else if(pr->rio_cnt == 0) //到文件末尾return 0;elsepr->rio_pbuf = pr->rio_buf; //重置指针位置}//从内部缓冲拷贝数据到用户缓冲中cnt = (pr->rio_cnt < n)? pr->rio_cnt: n; //取两者之间的小的memcpy(usrbuf, pr->rio_pbuf, cnt);pr->rio_pbuf += cnt;pr->rio_cnt -= cnt;return cnt;}//带缓冲输入函数ssize_t rio_readnb(rio_t *pr, void *usrbuf, size_t n){size_t nleft = n;ssize_t nread;char *pbuf = usrbuf;while(nleft > 0){//与无缓冲的区别在于这里调用的是rio_read而不是readif((nread = rio_read(pr, pbuf, nleft)) < 0){if(errno == EINTR)nread = 0; //中断造成的,再次调用readelsereturn -1; //出错}else if(nread == 0) //到了文件末尾break;nleft -= nread;pbuf += nread;}return n - nleft;}//带缓冲输入函数,每次输入一行ssize_t rio_readlineb(rio_t *pr, void *usrbuf, size_t maxlen){int i, n;char c, *pbuf = usrbuf;for(i = 1; i < maxlen; i++){if((n = rio_read(pr, &c, 1)) == 1) //读一个字符{*pbuf++ = c;if(c == '\n') //读到换行符break;}else if(n == 0){if(i == 1) //空文件return 0;else //读到了部分数据break;}else //出错return -1;}*pbuf = 0; //添加字符串结束符return i;}#endif /* RIO_H_ */
- 代码开源(2)——UNIX 健壮I/O函数
- RIO包 健壮的I/O函数代码
- UNIX环境高级编程——标准I/O库函数和Unbuffered I/O函数
- UNIX 环境高级编程(九)—— fork 函数与 I/O 函数
- UNIX环境高级编程——存储映射I/O(mmap函数)
- UNIX环境高级编程——存储映射I/O(mmap函数)
- UNIX网络编程——shutdown函数(I/O复用并发服务器)
- UNIX文件I/O函数
- UNIX环境编程学习笔记(2)——文件I/O之不带缓冲的 I/O
- UNIX环境编程—文件I/O
- unix 环境下c函数摘要( i/o部分)
- unix环境高级编程之一( 基本I/O函数)
- UNIX网络编程------高级I/O函数(十四)
- 标准I/O与Unix I/O函数整合
- UNIX环境编程学习笔记(11)——文件I/O之文件时间以及 utime 函数
- UNIX网络编程——I/O复用:select和poll函数
- 【Unix 网络编程】服务器网络编程模型——I/O复用:select 函数
- 《unix高级环境编程》高级 I/O—— readv 和 writev 函数
- Website Cookie Testing
- jQuery 设计思想
- 基于SOA的java语言开发环境-交付前持续集成
- 开源日志系统比较
- (重点)jQuery模板:jQuery Templates Proposal
- 代码开源(2)——UNIX 健壮I/O函数
- web test interview questions
- 2011-8-12 11:18:04
- spinEdit 限制只能输入非负值
- bcp 错误总结
- Linux环境进程间通信(二): 信号(下)
- Item:尽可能少做类型转换
- 最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用8
- 两道c++面试题