NAIUI / CSAPP 第10章-系统级IO

Created Tue, 04 Jun 2024 22:15:17 -0700 Modified Tue, 04 Jun 2024 22:15:17 -0700

CSAPP的记录-第10章

前言

在Linux系统中,一般通过使用由内核提供的系统级Unix IO函数实现高级别的IO函数。本章主要介绍Unix IO和标准IO的一般概念,以及在C程序中如何可靠地使用它们。

1、Unix IO

Linux shell创建的每个进程都有三个打开的文件:标准输入0、标准输出1、标准错误2。定义在<unistd.h>中。

2、健壮读写

readwrite传送的字节比应用程序要求的少,这些不足值不代表有错误。

2-1、无缓冲的IO函数

当被一个信号处理程序的返回中断时,手动重启。

ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
    size_t nleft = n;
    ssize_t nread = 0;
    char *bufp = usrbuf;

    while (nleft > 0) {
        if (nread = read(fd, bufp, nleft) < 0) {
            if (errno == EINTR) nread = 0;
            else return -1;
        }
        else if (nread == 0) break;
        nleft -= nread;
        bufp += nread;
    }

    return n-nleft;
}
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
    size_t nleft = n;
    ssize_t nwriteen= 0;
    char *bufp = usrbuf;

    while (nleft > 0) {
        if (nread = write(fd, bufp, nleft) <= 0) {
            if (errno == EINTR) nwriteen = 0;
            else return -1;
        }
        else if (nwriteen == 0) break;
        nleft -= nwriteen;
        bufp += nwriteen;
    }

    return n;
}

2-2、带缓冲的I函数

由于每次读取文件都要陷入内核切换,效率不高。

int main()
{
    int n;
    rio_t rio;
    char buf[MAXLINE];

    Rio_readinitb(&rio, STDIN_FILENO);
    while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) 
        Rio_writen(STDOUT_FILENO, buf, n);    
}

rio结构体

#define RIO_BUFSIZE 8192
typedef struct {
    int  rio_fd;
    int  rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];
} rio_t;

初始化函数

void rio_readinitb(rio_t *rp, int fd) 
{
    rp->rio_fd = fd;
    rp->rio_cnt = 0;
    rp->rio_bufptr = rp->rio_buf;
} 

核心函数rio_read

static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
    int cnt;

    while (rp->rio_cnt <= 0) {
        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;
    }

    // copy min(n, cnt)
    cnt = min(n, rp->rio_cnt);
    memcpy(usrbuf, rp->rio_bufptr, cnt);
    rp->rio_bufptr += cnt;
    rp->rio_cnt -= cnt;

    return cnt;
}

函数rio_readlineb

ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
    int n, rc;
    char c, *bufp = usrbuf;

    for (n = 1; n < maxlen; n++) {
        if ((rc = rio_read(rp, &c, 1)) == 1) {
            *bufp++ = c;
            if (c == '\n') {
                n++;
                break;
            }
        } else if (rc == 0) {
            if (n == 1) return 0;
            else break;
        } else return -1;
    }

    *bufp = 0;
    return n-1;
}

函数rio_readnb

ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n) 
{
    size_t nleft = n;
    ssize_t nread;
    char *bufp = usrbuf;

    while (nleft > 0) {
        if ((nread = rio_read(rp, bufp, nleft)) < 0) return -1;
        else if (nread == 0) break;
        nleft -= nread;
        bufp += nread;
    }
    return n - nleft;
}

参考文献

深入理解计算机系统-第10章