基于Linux平台的高级IO扩展函数

本文介绍了一种通过多次调用readv和writev系统调用来高效处理多个缓冲区的方法,相较于传统的read和write调用,这种方法能显著减少系统调用次数,提升程序效率。
由于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高,所以这样做就会尽可能减少系统调用的次数,提高效率。
下载方式:https://pan.quark.cn/s/a4b39357ea24 布线问题(分支限界算法)是计算机科学和电子工程领域中一个广为人知的议题,它主要探讨如何在印刷电路板上定位两个节点间最短的连接路径。 在这一议题中,电路板被构建为一个包含 n×m 个方格的矩阵,每个方格能够被界定为可通行或不可通行,其核心任务是定位从初始点到最终点的最短路径。 分支限界算法是处理布线问题的一种常用策略。 该算法与回溯法有相似之处,但存在差异,分支限界法仅需获取满足约束条件的一个最优路径,并按照广度优先或最小成本优先的原则来探索解空间树。 树 T 被构建为子集树或排列树,在探索过程中,每个节点仅被赋予一次成为扩展节点的机会,且会一次性生成其全部子节点。 针对布线问题的解决,队列式分支限界法可以被采用。 从起始位置 a 出发,将其设定为首个扩展节点,并将与该扩展节点相邻且可通行的方格加入至活跃节点队列中,将这些方格标记为 1,即从起始方格 a 到这些方格的距离为 1。 随后,从活跃节点队列中提取队首节点作为下一个扩展节点,并将与当前扩展节点相邻且未标记的方格标记为 2,随后将这些方格存入活跃节点队列。 这一过程将持续进行,直至算法探测到目标方格 b 或活跃节点队列为空。 在实现上述算法时,必须定义一个类 Position 来表征电路板上方格的位置,其成员 row 和 col 分别指示方格所在的行和列。 在方格位置上,布线能够沿右、下、左、上四个方向展开。 这四个方向的移动分别被记为 0、1、2、3。 下述表格中,offset[i].row 和 offset[i].col(i=0,1,2,3)分别提供了沿这四个方向前进 1 步相对于当前方格的相对位移。 在 Java 编程语言中,可以使用二维数组...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值