资讯专栏INFORMATION COLUMN

[Linux] RIO C++封装

makeFoxPlay / 1256人阅读

摘要:缩减了原程序的初始化等函数之后,主要有以下四个对外函数为通过得到的文件描述符,通常为一个小整数。该函数将中最多个字节写到文件中。该函数一次从缓冲区文件读取一行数据最长不超过该函数是带有缓冲区版本的,类似于。

RIO包是CSAPP中一个基于read和write函数实现的能够处理终端并提供了带缓冲区读取的IO包。代码很简单,但很巧妙。
缩减了原程序的初始化等函数之后,主要有以下四个对外函数:

1.ssize_t readn(int fd,void *usrbuf,size_t n);
fd为通过open得到的文件描述符,通常为一个小整数。该函数从指定文件读取n个byte到usrbuf中。如果成功执行,返回传输的字节数,如果读到EOF,返回0,如果出错,返回-1。

2.ssize_t writen(int fd,void *usrbuf,size_t n);
该函数将usebuf中最多n个字节写到文件中。如果成功,返回写入的字节数,如果出错返回-1.

3.ssize_t readlineb(rio_t rp,void usrbuf,size_t maxlen);
rio_t是一个定义乐缓冲区的结构体,具体实现见下面代码。该函数一次从缓冲区/文件读取一行数据(最长不超过maxlen)
4.ssize_t readnb(rio_t rp,void usrbuf,size_t n);
该函数是带有缓冲区版本的read,类似于readn。
myrio.h

#pragma once

#include 
#include 
#include 
#include 
#include 
#include 
//a buffer named rio_t
#define RIO_BUFSIZE 8192
typedef struct rio_t{
    int rio_fd; 
    int rio_cnt; //unread bytes in rio_buf
    char *rio_bufptr; //next unread byte in rio_buf
    char rio_buf[RIO_BUFSIZE]; //internal buffer
    
    rio_t(int fd)
        :rio_fd(fd),rio_cnt(0),rio_bufptr(rio_buf){ }
} rio_t;
class Rio{
public:
    //io function without internal buffer
    //Succeed: return the number of byte; EOF: return 0; Fail: return -1
    ssize_t readn(int fd,void *usrbuf,size_t n);
    ssize_t writen(int fd,void *usrbuf,size_t n);    

    //io function with internal buffer
    //Succeed: return the number of byte; EOF: return 0; Fail: return -1
    ssize_t readlineb(rio_t *rp,void *usrbuf,size_t maxlen);
    ssize_t readnb(rio_t *rp,void *usrbuf,size_t n);

private:
    //read with buffer
    ssize_t rio_read(rio_t *rp,char *usrbuf,size_t n);
};

myrio.cpp

#include "myrio.h"

//the difference between these function and system"s is that:
//this function can deal with the interrupt. 
ssize_t Rio::readn(int fd,void *usrbuf,size_t n){
    size_t nleft = n;
    ssize_t nread;
    char *buf = static_cast(usrbuf);
    while(nleft > 0){
        if((nread = read(fd,buf,nleft))<0){
            if(errno ==EINTR) nread = 0;
            else return -1;
        }else if(nleft == 0){
            break;
        }else{
            nleft -= nread;
            buf += nread;
        }
    }
    return (n - nleft);
}
ssize_t Rio::writen(int fd,void *usrbuf,size_t n){
    size_t nleft = n;
    ssize_t nwriten;
    char *buf = static_cast(usrbuf);

    while(nleft > 0){
        if((nwriten = write(fd,buf,nleft)) <= 0){
            if(errno == EINTR) nwriten = 0;
            else return -1;
        }else{
            nleft -= nwriten;
            buf += nwriten;
        }
        return n;
    }
}

ssize_t Rio::rio_read(rio_t *rp,char *usrbuf,size_t n){
    int cnt;
    while(rp->rio_cnt <= 0){ //refill rio_buf if buf is empty
        rp->rio_cnt = read(rp->rio_fd,rp->rio_buf,sizeof(rp->rio_buf));        
        if(rp->rio_cnt < 0){
            if(errno != EINTR) return -1;
        }else if(rp->rio_cnt == 0){
            return 0;
        }else{
            rp->rio_bufptr = rp->rio_buf;
        }
    }
    cnt = n;
    if(rp->rio_cnt < n)
        cnt = rp->rio_cnt;
    memcpy(usrbuf,rp->rio_bufptr,cnt);
    rp->rio_bufptr += cnt;
    rp->rio_cnt -= cnt;

    return cnt;
}
ssize_t Rio::readlineb(rio_t *rp,void *usrbuf,size_t maxlen){
    char c;
    char *buf = static_cast(usrbuf);
    int n,rc;
    for(n=1;n(usrbuf);
    while(nleft > 0){
        if((nread = rio_read(rp,buf,nleft)) < 0){
            if(errno == EINTR) nread = 0;
            else return -1;
        }else if(nread == 0){
            break;
        }else{
            nleft -= nread;
            buf += nread;
        }
    }
    return (n-nleft);
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/9467.html

相关文章

  • 后端研发菜鸟成长记 第三章 小试牛刀,编写性能测试工具

    摘要:命令参数功能和所有的命令一样,我们的工具也支持命令参数,在下有一个函数用于支持对命令行参数的解析,通过这个函数我们能轻易是实现对长短参数的解析和获取。 3 小试牛刀,编写性能测试工具 作为一名后端研发人员,必须具备系统性能评估和分析能力,因为只有对系统总体性能了如指掌,才能知道系统什么时候需要扩容,系统哪里有性能瓶颈需要优化。 本章将介绍如何宏观的评估系统的总体性能,并重点介绍如何编写...

    mating 评论0 收藏0
  • Lua的简单使用

    摘要:如将如下代码存储在名为的脚本文件中使用执行以上脚本,输出结果为也可以将代码修改为如下形式来执行脚本以上代码中指定了的解释器目录,加上号标记解释器会忽略它。 Lua是一门强大、快速、轻量的嵌入式脚本语言,它由巴西里约热内卢Pontifical Catholic大学的PUC-Rio团队开发。Lua是一个自由软件,广泛应用于世界上无数产品和项目。Lua的官方网站上提供了关于Lua的完整信息,...

    DevYK 评论0 收藏0
  • 面试官:我们只想要这样的C++工程师

    摘要:今天先奉上一篇关于方向的,,,,前端,测试这些方向的文章随后也会出来,欢迎大家关注呀一什么是研发工程师呢是最贴近底层编程语言。因此大部分公司的核心业务都是用进行开发,工程师掌握着公司最核心最重要的业务体系,有着十分重要的地位。 showImg(https://segmentfault.com/img/bVbv8Cq); 最近好多同学来找就就说,我想找 xxx 方向的工作,我怎么学习呀?...

    cppowboy 评论0 收藏0
  • 七个用于数据科学(Data Science)的命令行工具

    摘要:最近,介绍了可用于数据科学的经典命令行工具。下面我将介绍在我的日常工作中发现很有用的七个命令行工具。把转换成虽然适合交换数据,但是它不适合很多命令行工具。别人建议的命令行工具下面是其他朋友通过和推荐的工具,谢谢大家。 数据科学是OSEMN(和 awesome 相同发音),它包括获取(Obtaining)、整理(Scrubbing)、探索(Exploring)、建模(Modeling)和...

    wanglu1209 评论0 收藏0
  • Python的C/C++扩展——用SWIG封装C++为Python模块

    摘要:所以,最大的好处就是将脚本语言的开发效率和的运行效率有机的结合起来。前面的文章提到一个实现的双数组的实现,它在中文分词新词发现等算法中的应用。本文以的封装实现来说明的使用。编译生成动态库编译生成的使用的,可以参考的编写。 如果觉得文章对你有帮助,你也可以访问老猿的个人博客https://www.yuanrenxue.com/ Python调用C/C++代码的利器除了boost_pyt...

    邹强 评论0 收藏0

发表评论

0条评论

makeFoxPlay

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<