CSAPP笔记(第十章 系统级I/O)

第十章的内容为p657~p675.

摘要

Unix将所有I/O抽象为文件, 将所有输入/输出操作抽象为read/write. 最底层的方法为Unix I/O, 之上为了提高效率避免多次调用Unix I/O, 以及处理不足值的清空, 出了有带缓冲区健壮的RIO,
还有之上更加完善的C的标准I/O.

Unix I/O

  • 打开文件, 返回一个描述符
  • 默认3个打开的文件, StdIn, StdOut, StdErr.
  • Seek, 改变当前位置
  • Read/Write
  • Close

文件类型

  • 普通文件, 分文本文件和二进制文件
  • 目录, 是包含一组链接的文件, 每个链接都将一个文件名链接到文件, 每个目录至少包含2个条目, "."和"..", 分别链接自己和父目录
  • 套接字, 是用来与另一个进程进行跨网络通信的文件

打开和关闭文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcnt1.h>

int open(char *filename, int flags, mode_t mode); //若成功返回新文件描述符, 出错返回 -1

flags有几种类型, O_RDONLY(只读), O_WRONLY(只写), O_RDWR(可读写), O_CREAT(创建新文件), O_TRUNC(清空文件), O_APPEND(写内容到文件结尾)

mode有几种类型, S_IRUSR(所有者拥有读权限), S_IWGRP(群组拥有写权限), S_IXOTH(其他用户拥有执行权限). 模式S_I [RWX] [USR|GRP|OTH].

#include <unistd.h>

int close(int fd);

读写文件

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t n); //成功返回读的字节数, EOF则为0, 错误为-1
ssize_t write(int fd, const void *buf, size_t n); //成功返回写的字节数, 错位为-1

RIO包

#include "csapp.h"

ssize_t rio_readn(int fd, void *usrbuf, size_t n);
ssize_t rio_writen(int fd, void *usrbuf, size_t n);

相比Unix I/O, RIO有2个优点, 1是带缓冲区, 避免过于频繁的调用Unix I/O接口; 2是处理好了不足值的情况, 尤其是处理网络程序.

读取文件元数据

#include <unistd.h>
#include <sys/stat.h>

int stat(const char * filename, struct stat *buf);
int fstat(int fd, struct stat *buf);

这个方法只存在Unix I/O, 不存在于RIO和标准I/O.
S_ISREG(是否普通文件), S_ISDIR(是否目录文件), S_ISSOCK(是否网络套接字).

读取目录

#include <sys/types.h>
#include <dirent.h>

DIR *opendir(const char *name); //成功返回处理的指针, 错误返回NULL
struct dirent *readdir(DIR *dirp); //读取目录下的所有文件.
int closedir(DIR *dirp);//成功为0, 错误-1.

共享文件

  • 描述符表. 每个进程独享一个描述符表, 每一个Item指向file table的一个item.
  • File Table. 打开文件的集合由一个File Table表示, 所有进程共享一个表, 每个Item由当前的文件位置, 引用计数, 以及一个指向v-node表item的指针. 关闭一个描述符会减少相应File Table的item的引用计数, 直到引用计数为0, 系统才会删除这个File table item.
  • V-node表. 所有进程共享. 每个item包含文件的stat信息.

I/O重定向

#include <unistd.h>

int dup2(int oldfd, int newfd); //成功返回非负描述符, 错误返回-1.

标准I/O

C语言定义的高级函数库, 提供了

  • 打开关闭函数fopen 和 fclose
  • 读写字节的函数fread 和 fwrite
  • 读写字符串的函数fgets 和 fputs
  • 格式化函数 scanf 和 printf

总结

  • 尽可能使用标准I/O, 除stat外, 标准I/O没有对应的函数
  • 不要使用scanf或rio_readlineb来读二进制文件, 而是用来读文本文件
  • 对网络套接字使用RIO

CSAPP笔记(第十章 系统级I/O)

上一篇:tornado的Application的一些事儿


下一篇:Android View 的测量流程详解