CSAPP 学习记录 10章 系统IO

系统IO:
        系统IO一般由系统调用所使用,由文件描述符,open,write,read等方法和结构组成。返回值为-1(发生错误或者中断),0(文件结束EOF),实际读取的字节数。
        一般而言每个进城开始是都会有三个打开的文件,分别为标准输入,标准输出,标准错误;用文件描述符来表示即为0 (STDIN_FILENO),1(STDOUT_FILENO),2(STDERR_FILENO);用流来表示则为stdin,stdout,stderr。
        对于目录来说,每个目录最少有两个条目,“.”表示带文件本身,“..”表示到上级目录。对于路径名,以”/“开头的为绝对目录,以其他开头的为相对目录
        对于打开文件命令open(char * filename ,int flags,mode_t mode) 来说,filename是文件路径,flags是打开方式,mode用于在使用open创建新文件时置顶文件的读写执行权限。  
        对于已经打开的文件描述符,或者网络通讯socket描述符,可以使用fcntl来进行设置,fcntl(connfd,F_GETFL,0) 第二个参数为F_GETFL用于获取文件描述符的flags,同理第二个参数为F_SETFL用于设置文件描述符的flags  fcntl(connfd,F_SETFL,O_NONBLOCK );

RIO健壮读写包:
        RIO写包是CSAPP封装的健壮的读写函数,使用循环读取的方式处理了不足值的情况(读写遇到EOF,从终端读取文本行,读网络套接字有延迟都能够倒置不足值的出现)
        RIO读写函数分为无缓冲读写函数(rio_readn,rio_writen)和有缓冲读写函数(rio_readinitb,rio_writenb,rio_readnb,rio_readlineb);其中rio_readinitb(rio_t * rio,int fd) 通过传入参数fd来对传入的文件描述符创建缓冲区以及返回缓冲区结构体指针rio_t *rio。因此对于无缓冲rio以及有缓冲rio来说,数据读取的位置都是不相同的,一个是直接根据文件描述符从对应的文件表的指针进行读取,而带缓冲的rio函数是对于缓冲区进行读取,因此带缓冲区的函数不可以与不带缓冲区的函数进行交叉使用,而同类型是可以进行交叉使用的。
        Rio_readlineb 是 rio_readlineb 函数的带异常处理的版本,因此不会返回-1,只会返回 0(读到EOF)和 >0(读取的字节数)
        rio_readnb 和 rio_readlineb 这些带缓冲区的读函数 核心都是调用 rio_read函数进行读操作,rio_read函数 如果缓冲区为空的话,会调用unix的read函数来填充缓冲区,填充大小为缓冲区大小,直到遇到EOF或者遇到read返回-1,或者缓冲区被填充满之后停止。然后通过传入的rio_read读取长度(读取长度如果大于缓冲区的大小,会取两者最小值),从缓冲区直接通过memcpy来读取缓冲区中的内容。
        rio_readnb 调用rio_read,读取时通过计数来判断是否读取完毕
rio_readlineb 诸位进行调用rio_read函数,每次读取一个字节,通过判断字节是否是'\n'来判断是否读取结束,或者读到传入的最大长度也会结束

读取文件元数据:
        stat(const char * filename ,struct stat *buf) 和 fstat(int fd,struct stat * buf) 可以用来读取文件元数据,结构体struct stat 用于存储文件元数据,可以使用宏S_ISREG(),S_ISDIR(),S_ISSOCK()来判断文件描述符是否是普通文件,目录文件或者是网络套接字。

读取目录内容:
        opendir(const char * filename) 和  readdir(DIR* dirp) 两个函数可以用来读取目录的内容,opendir用于打开目录,返回目录处理指针DIR * p,readdir返回下一个目录项(目录中的文件)的指针,closedir用于关闭目录。

共享文件:
        内核使用三个相关的数据结构来表示已经打开的文件从而进行文件共享:
1、描述符表:每个进程有一个独立的描述符表,记录描述符指向文件表表项目的指针
2、打开文件表:所有进程共享,表项包括文件位置(读取位置),引用计数和对应v-node表项的指针;每个打开的文件都会具有一个在打开文件表的表项,同一个文件可以被打开多次
3、v-node表:所有进程共享,表项包括stat文件结构中的大部分内容;v-node表对应磁盘文件,因此每个文件只能拥有一个v-node表的表项。

IO重定向:
        Linux shell 提供了IO重定向的操作付,允许用户将磁盘文件和标准输入输出联系起来(> ,<)。在程序中也可以使用 dup2(int oldfd ,int newfd) 来对于newfd进行覆盖,执行的操作是利用oldfd的描述符表表项覆盖newfd的表项标准IO:

        对于标准IO来说,是C语言定义的一组高级输入输出函数,称为标准IO库,为程序员的Linux IO提供了较高级别的替代。
        标准的IO库将打开的文件模型化为一个IO流的形式,在程序上一个流就表现为一个FILE*类型的变量。FILE*类型的流是对于文件描述符和流缓冲区的上层抽象,对于流缓冲有三种不同情况,无缓冲,行缓冲(遇到换行符就进行IO),满缓冲(达到一定数量之后IO),可以使用setvbuf()函数来进行设置流缓冲的方式。
        对于IO函数的使用,
        1、尽可能使用标准IO;
        2、不要使用文本文件IO函数来读取二进制文件;
        3、对于网络套接字要使用RIO而不是标准IO,因为标准IO的限制原因,所以在使用标准IO对于网络套接字进行使用时需要创建两个IO流,并在输出文件后重置文件位置来进行IO操作(因为有些对于标准流的函数不能在网络套接字上进行使用)。
        对于交互型的设备来说,流缓冲的形式默认是行缓冲的,而其他文件形式的IO流的缓冲形式默认是满缓冲的,需要值得注意

关于EOF
        在使用标准IO时,EOF代表了文件达到了末尾,或者文件读写出现了错误,比如磁盘没有了空间等。在网络IO中,EOF代表通信的另一端断开了连接,因此read函数会返回0.read函数为0表示遇到了EOF即文件结束,read函数返回-1表示出现了异常,例如信号中断等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值