CSAPP的记录-第10章
前言
在Linux系统中,一般通过使用由内核提供的系统级Unix IO函数实现高级别的IO函数。本章主要介绍Unix IO和标准IO的一般概念,以及在C程序中如何可靠地使用它们。
1、Unix IO
Linux shell创建的每个进程都有三个打开的文件:标准输入0、标准输出1、标准错误2。定义在<unistd.h>
中。
2、健壮读写
read
和write
传送的字节比应用程序要求的少,这些不足值不代表有错误。
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章