设为首页 加入收藏

TOP

C Linux read write function extension(一)
2019-06-01 20:07:58 】 浏览:118
Tags:Linux read write function extension

前言 - 赠送 readn / writen

  Linux 上默认的 read 和 write 函数会被信号软中断. 且 read 和 write 函数中第三个参数 count

#include <unistd.h>

extern ssize_t read(int fd, void * buf, size_t count);
extern ssize_t write(int fd, const void * buf, size_t count);

也会因内部缓冲机制, 不一定保证读取或写入到指定 count 大小数据.

这里将 read 和 write 拓展成 readn 和 writen

//
// readn - 力求读取 n 个字节
// fd       : 文件描述符
// buf      : 缓冲区
// n        : 读取长度
// return   : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n
//
ssize_t 
readn(int fd, void * buf, size_t n) {
    size_t div = n;
    char * ptr = buf;

    while (div > 0) {
        ssize_t ret = read(fd, ptr, div);
        if (ret < 0) {
            if (errno == EINTR)
                continue;
            return -1;
        }
        if (ret == 0) 
            break;
        ptr += ret;
        div -= ret;
    }

    return n - div;
}

//
// writen - 力求写入 n 个字节
// fd       : 文件描述符
// buf      : 缓冲区
// n        : 读取长度
// return   : 返回写入长度, -1 标识错误, 默认 n
//
ssize_t 
writen(int fd, const void * buf, size_t n) {
    size_t div = n;
    const char * ptr = buf;

    while (div > 0) {
        ssize_t ret = write(fd, ptr, div);
        if (ret <= 0) {
            if (errno == EINTR)
                continue;
            return -1;
        }
        ptr += ret;
        div -= ret;
    }

    return n;
}

有了这些收获, 不妨写个小测试

#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>

//
// readn - 力求读取 n 个字节
// fd       : 文件描述符
// buf      : 缓冲区
// n        : 读取长度
// return   : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n
//
extern ssize_t readn(int fd, void * buf, size_t n);

//
// writen - 力求写入 n 个字节
// fd       : 文件描述符
// buf      : 缓冲区
// n        : 读取长度
// return   : 返回写入长度, -1 标识错误, 默认 n
//
extern ssize_t writen(int fd, const void * buf, size_t n);

/*
                   _oo0oo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  0\  =  /0
                ___/`---'\___
              .' \\|     |// '.
             / \\|||  :  |||// \
            / _||||| -:- |||||- \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |_/ |
           \  .-\__  '-'  ___/-. /
         ___'. .'  /--.--\  `. .'___
       ."" '<  `.___\_<|>_/___.' >' "".
      | | :  `- \`.;`\ _ /`;.`/ - ` : | |
      \  \ `_.   \_ __\ /__ _/   .-` /  /
   =====`-.____`.___ \_____/___.-`___.-'=====
                     `=---='
 */
int main(int argc, char * argv[]) {
    ssize_t ret = writen(STDOUT_FILENO, "12345\n1", 6);
    printf("ret = %ld\n", ret);

    char buf[4];
    ret = readn(STDIN_FILENO, buf, 3);
    buf[3] = '\0';
    printf("ret = %ld, buf = %s\n", ret, buf);

    return 0;
}

一忧一喜皆心火,一荣一枯皆眼尘,静心看透炎凉事,千古不做梦里人。

聪明人,一味向前看;智慧人,事事向后看;聪明人,是战胜别人的人;智慧人,是战胜自己的人。

修心当以净心为要,修道当以无我为基。

过去事,过去心,不可记得;现在事,现在心,随缘即可;未来事,未来心,不必劳心。

 

正文 -  缓冲读

  在了解 readn 套路基础上, 你是否有所想过那缓冲读写的实现思路呢. 这里不妨借用深入理解计算机系统

书中的思路实现一番.

struct rio {
    int fd;             // 文件描述符
    char * ptr;         // 下一次读取缓冲池 buf 起点
    ssize_t cnt;        // 缓冲池 buf 字符数量
    char buf[BUFSIZ];   // 缓冲池
};

// rio_init - rio 初始化
inline void rio_init(struct rio * r, int fd) {
    assert(r && fd >= 0);
    r->fd = fd;
    r->cnt = 0;
    r->ptr = r->buf;
}

//
// readn - 力求读取 n 个字节
// r        : 缓冲读取对象
// buf      : 缓冲区
// n        : 读取长度
// return   : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n
//
extern ssize_t rio_readn(struct rio * r, void * buf, size_t n);

//
// rio_readline - 力求读取一行数据
// r        : 缓冲读取对象
// buf      : 缓冲区
// n        : 读取长度
// return   : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n
//
extern ssize_t rio_readline(struct rio * r, void * buf, size_t n);

实现了缓冲读固定字符和缓冲读一行. 额外的缓冲写也是相似的思路, 简单点写不了会进入写缓冲区,

可以当课外作业自行实现.

// rio_read - 带缓冲版本的 read
static ssize_t rio_read(struct rio * r, void * buf, size_t n) {
    // 当缓冲区中没有数据, 我们重新填充缓冲区
    while (r->cnt <= 0) {
        r->cnt = read(r->fd, r->buf, sizeof r->buf);
        if (r->cnt < 0) {
            if (errno == EINT  
		
C Linux read write function extension(一) https://www.cppentry.com/bencandy.php?fid=45&id=226253

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇小白入门.输入一个整数,判断他的.. 下一篇c,使用lib,dll