随笔-149  评论-223  文章-30  trackbacks-0
     由于read、readv、write和writev函数一次读或写有时并不能满足所要求的数据,因此需要多次调用直到要求的字节数或者出错。针对这4个系统调用,编写了对应的xxxn版本,实现如下
  1/**********************************************************************************************************
  2 In the following four functions,the optional parameter tran indicate the number of bytes read or written,or -1 if an error occurred.
  3 On success,return true indicate all data had been read or written successfully,otherwise in other cases,return false indicate error or partial success.
  4**********************************************************************************************************/

  5 
  6bool readn(int fd,void* buf,size_t cnt,ssize_t* tran/*=NULL*/)
  7{
  8    size_t left = cnt;
  9    ssize_t ret;
 10    char* ptr = (char*)buf;
 11    
 12    while(left > 0){
 13        ret = read(fd,ptr,left);
 14        if(ret > 0){
 15            left -= ret;
 16            ptr += ret;
 17        }
else if(0==ret || left != cnt)
 18            break;
 19        else{
 20            if(tran) *tran = -1;
 21            return false;        
 22        }

 23    }

 24    if(tran) *tran = cnt-left;
 25    return 0==left;
 26}

 27
 28bool writen(int fd,const void* buf,size_t cnt,ssize_t* tran/*=NULL*/)
 29{
 30    size_t left = cnt;
 31    ssize_t ret;
 32    char* ptr = (char*)buf;
 33
 34    while(left > 0){
 35        ret = write(fd,ptr,left);
 36        if(ret > 0){
 37            left -= ret;
 38            ptr += ret;
 39        }
else if(0==ret || left != cnt)
 40            break;
 41        else
 42            if(tran) *tran = -1;
 43            return false;        
 44    }

 45    if(tran) *tran = cnt-left;
 46    return 0==left;
 47}

 48
 49static int get_iov_tran_index(const struct iovec* iov,int iovcnt,size_t trans,size_t& tran)
 50{
 51    size_t cnt = 0;  int i;
 52
 53    for(i=0;i < iovcnt;++i){
 54        cnt += iov[i].iov_len;
 55        if(trans < cnt){
 56            tran = iov[i].iov_len - (cnt - tran);
 57            break;
 58        }

 59    }

 60    return i;
 61}

 62
 63bool readvn(int fd,const struct iovec* iov,int iovcnt,ssize_t* tran/*=NULL*/)
 64{
 65    if(iovcnt > IOV_MAX){
 66        if(tran) *tran = -1;
 67        errno = EINVAL;    
 68        return false;
 69    }

 70    size_t all_cnt = 0,all_tran = 0,one_tran;
 71    ssize_t ret;
 72
 73    struct iovec _iov[IOV_MAX];
 74    int i;
 75    for(i=0;i < iovcnt;++i)
 76        _iov[i] = iov[i];    
 77        all_cnt += iov[i].iov_len;
 78    }

 79
 80    i = 0;
 81    do{
 82        ret = readv(fd,&_iov[i],iovcnt-i);
 83        if(ret > 0){
 84            all_tran += ret;    
 85            if(all_tran==all_cnt)
 86                break;
 87
 88            i = get_iov_tran_index(iov,iovcnt,all_tran,one_tran);
 89            assert(i < iovcnt);
 90            _iov[i].iov_base = iov[i].iov_base + one_tran;                
 91            _iov[i].iov_len  = iov[i].iov_len - one_tran;
 92
 93        }
else if(0==ret)
 94            break;
 95        else{
 96            if(tran) *tran = -1;
 97            return false;
 98        }

 99    }
while(all_tran < all_cnt);
100
101    if(tran) *tran = all_tran;
102    return all_tran==all_cnt;
103}

104
105bool writevn(int fd,const struct iovec* iov,int iovcnt,ssize_t* tran/*=NULL*/)
106{
107    if(iovcnt > IOV_MAX){
108        if(tran) *tran = -1;
109        errno = EINVAL;    
110        return false;
111    }

112    size_t all_cnt = 0,all_tran = 0,one_tran;
113    ssize_t ret;
114
115    struct iovec _iov[IOV_MAX];
116    int i;
117    for(i=0;i < iovcnt;++i)
118        _iov[i] = iov[i];    
119        all_cnt += iov[i].iov_len;
120    }

121
122    i = 0;
123    do{
124        ret = writev(fd,&_iov[i],iovcnt-i);
125        if(ret > 0){
126            all_tran += ret;    
127            if(all_tran==all_cnt)
128                break;
129
130            i = get_iov_tran_index(iov,iovcnt,all_tran,one_tran);
131            assert(i < iovcnt);
132            _iov[i].iov_base = iov[i].iov_base + one_tran;                
133            _iov[i].iov_len  = iov[i].iov_len - one_tran;
134
135        }
else if(0==ret)
136            break;
137        else{
138            if(tran) *tran = -1;
139            return false;
140        }

141    }
while(all_tran < all_cnt);
142
143    if(tran) *tran = all_tran;
144    return all_tran==all_cnt;
145}
   从以上代码可看出,readvn和writevn的实现并不是循环对每一个缓冲区简单地调用readn或writen,而是多次调用原生的readv或writev,因为对于读写多个缓冲区,使用readv或writev的效率通常要比多次调用read或write高,所以这样做就会尽可能减少系统调用的次数,提高效率。
posted on 2013-08-02 19:44 春秋十二月 阅读(1684) 评论(0)  编辑 收藏 引用 所属分类: System

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理