zoukankan      html  css  js  c++  java
  • 基于Linux平台的高级IO扩展函数

    由于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,buf,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,buf,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高,所以这样做就会尽可能减少系统调用的次数,提高效率。
  • 相关阅读:
    C primer plus 5 读书笔记2
    c primer plus 5 读书笔记1
    控制反转(IOC)模式
    软件设计原则
    springmvc跨域
    由阿里巴巴笔试题看java加载顺序
    spring各个包之间的依赖关系
    spring mvc 国际化
    git 笔记
    eclipse中maven项目部署到tomcat
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318870.html
Copyright © 2011-2022 走看看