1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 #include <sys/wait.h> 9 #include <errno.h> 10 #define ERR_EXIT(m) 11 do { 12 perror(m); 13 exit(EXIT_FAILURE); 14 }while(0) 15 16 #define BUFFERSIZE 65536 //缓冲区大小 17 18 typedef struct //缓冲区封装为一个结构体 19 { 20 int fd_; //fd 21 int cnt_; //缓冲区可用的字节数 22 char *ptr_; //指向缓冲区可用的第一个字节 23 char buffer_[BUFFERSIZE]; //缓冲区 24 } rio_t; 25 26 //初始化IO系统 27 void rio_init(rio_t *rp, int fd) 28 { 29 rp->fd_ = fd; 30 rp->cnt_ = 0; 31 rp->ptr_ = rp->buffer_; 32 memset(rp->buffer_, 0, BUFFERSIZE); 33 } 34 35 //用来替换read 36 ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n) 37 { 38 39 //缓冲区为空时,执行read操作 40 while(rp->cnt_ <= 0) 41 { 42 ssize_t nread = read(rp->fd_, rp->buffer_, BUFFERSIZE); 43 if(nread == -1) 44 { 45 if(errno == EINTR) 46 continue; 47 return -1; //ERROR 48 } 49 else if(nread == 0) 50 return 0; 51 52 //正常读取 53 rp->cnt_ = nread; 54 rp->ptr_ = rp->buffer_; //重置指针 55 } 56 57 //现有库存和用户要求的数量 取较小者 58 int cnt = (rp->cnt_ < n) ? rp->cnt_ : n; 59 memcpy(usrbuf, rp->ptr_, cnt); 60 rp->ptr_ += cnt; 61 rp->cnt_ -= cnt; 62 63 return cnt; //成功读取的字节数 64 } 65 66 67 ssize_t rio_readn(rio_t *rp, void *buf, size_t count) 68 { 69 size_t nleft = count; //剩余的字节数 70 ssize_t nread; //用作返回值 71 char *bufp = (char*)buf; //缓冲区的偏移量 72 73 while(nleft > 0) 74 { 75 //不再执行read系统调用 76 nread = rio_read(rp, bufp, nleft); 77 if(nread == -1) 78 { 79 if(errno == EINTR) 80 continue; 81 return -1; // ERROR 82 } 83 else if(nread == 0) //EOF 84 break; 85 86 nleft -= nread; 87 bufp += nread; 88 } 89 90 return (count - nleft); 91 } 92 93 ssize_t rio_readline(rio_t *rp, char *usrbuf, size_t maxlen) 94 { 95 int i; //计数 96 int nread; 97 98 char *bufp = usrbuf; 99 char c; //暂存字符 100 101 for(i = 0; i < maxlen - 1; ++i) 102 { 103 if((nread = rio_read(rp, &c, 1)) == -1) 104 return -1; 105 else if(nread == 0) //EOF 106 { 107 if(i == 0) 108 return 0; 109 break; 110 } 111 112 *bufp++ = c; //放入usrbuf 113 if(c == ' ') //碰到换行符直接退出循环 114 break; 115 } 116 *bufp = '