Pro_3_UNIX下read_write输入输出的字节数不足的问题

readline.c


/*
 * 抄自《UNIX网络编程:卷1》, 稍作修改。
 * 仅仅用于学习目的。学无止境,进步每一天。
 *  
 * slickedit编辑。 
 *  
 * 254008829@qq.com 
 *  
 */

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

ssize_t
readn(int fd, void *vptr, size_t n)
{
    size_t nleft;
    ssize_t nread;
    char *ptr;

    nleft = n;
    ptr = vptr;

    while (nleft > 0) {
        /*
        由于内核缓冲区的原因,一次系统调用read不一定可以读取到n个字节,nread>0的时候返回的是一次系统调用读到的实际 
        字节数。
        */
        if ( (nread = read(fd, ptr, nleft)) < 0) {
            if (errno == EINTR) {
                nread = 0; // call read() again.
            } else 
                return -1;
        } else if (nread == 0) { // 我们希望从fd指定的设备中读取n个字节,但是可能实际设备里面不足n,
                                 // 设备中没有可读数据了,就会返回0。这个就是EOF(end of file)。
            break;
        }
        nleft -= nread;
        ptr += nread;
    }

    return n - nleft; // 返回实际读取的字节数。
}

ssize_t 
writen(int fd, char *vptr, size_t n)
{
    size_t nleft;
    ssize_t nwrite;
    char *ptr;

    nleft = n;
    ptr = vptr;
    while (nleft > 0) {
        /*
           内核里面由于缓冲的原因,一次write可能没有写完我们所要求的n个字节。没有关系,返回nwrite>0,
           表明实际写了nwrite个字节。下次接着写。
           在不出错的情况下,writen返回的一定是n。这个和readn有区别。
         */
        if ( (nwrite = write(fd, ptr, nleft)) <= 0) {
            if ( (nwrite < 0 && nwrite == EINTR)) {
                nwrite = 0; // call write() again.
            } else 
                return -1;  // error
        } 
        nleft -= nwrite;
        ptr += nwrite;
    }

    return n;
}

/* 十分低效的readline函数,不带缓冲,每次只read一个字节, 每read一次都要进行一次系统调用。 */
ssize_t 
readline(int fd, void *vptr, size_t maxlen)
{
    ssize_t n, rc;
    char c, *ptr;

    ptr = vptr;

    for (n=1; n<maxlen; n++) {
    again:
        if ( (rc = read(fd, &c, 1)) == 1) {
            *ptr++ = c;
            if (c == '\n') {
                break;
            }
        } else if (rc == 0) { // eof
            return n-1; 
        } else {
            if (errno == EINTR) {
                goto again;
            }
            return -1;
        }

    }

    *ptr = 0;
    return n;
}

int main(int argc, char **argv)
{
    /* Test code */

    exit(0);
}
  1. read,write函数在实际应用过程中,应用层本身不带缓冲。每次read、write函数的执行会进行一次系统调用, 在第三个参数maxlen传到内核的时候,内核不一定一次可以处理这么大的数据量,所以可能只处理一部分。 根据read、write实际返回的值,来做多次系统调用,确保我们所要求写入或者读取的字节数满足我们的要求。
  2. readline函数是一个低效的版本,每次read只读一个字节,系统开销十分大。这个版本唯一的好处是可以确保我们所要求读取的行不会漏掉字节,在系统性能要求不高的时候可以用用。最好不要使用,只用了解我们的库函数readline的实现原理就行了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值