文件描述符

文件描述符 一.linux 打开文件三层结构关系图文件描述符、打开文件表、inode 关系图进程文件描述符表fd_array []属于进程 PCBtask_struct私有fd 就是数组下标0/1/2 标准输入输出错误系统打开文件表struct file /file_struct全局内核共享保存读写偏移量、打开标志、引用计数inode 表inode代表磁盘上真实文件存放文件元信息其中磁盘文件属性在inode,内容在缓冲区1. 文件打开与创建通过文件名来打开文件不存在文件就会创建新的文件。文件都是具有权限的所以我们需要进行权限的定义。#include sys/types.h #include sys/stat.h #include fcntl.h // 打开已有文件 int open(const char *pathname, int flags); // 创建打开文件带权限mode int open(const char *pathname, int flags, mode_t mode);第一个参数是文件名第二个参数是文件的打开方式第三个参数是文件权限掩码。2. 文件关闭文件打开后需要及时关闭。#include unistd.h int close(int fd);参数是文件描述符一个进程的整数编号。3. 文件写入文件需要进行写入操作。#include unistd.h ssize_t write(int fd, const void *buf, size_t count);4. 文件再次写入4.1 清空写入与常规语言不一样很多是默认清空的但是这里需要手动清空要不然会出现覆盖之前的内容。第一个参数是文件描述符第二个参数是需要写入内容缓冲区的起始地址第三个参数是写入内容的大小。使用宏定义映射 O_TRUNC 选项。// 再次打开O_TRUNC 会清空之前文字重新写 int fd2 open(test.txt, O_WRONLY | O_CREAT | O_TRUNC, 0666); char buf2[] 覆盖后的新内容\n; write(fd2, buf2, strlen(buf2)); close(fd2); return 0;4.2 结尾追加写入使用宏定义映射 O_APPEND 选项。// 再次打开追加 int fd2 open(log.txt, O_WRONLY | O_CREAT | O_APPEND, 0666); write(fd2, 第二条日志\n, strlen(第二条日志\n)); close(fd2); return 0;默认写入的是字符串将整数写入会变成乱码需要写入时还是需要转化为字符串。5. 文件读取#include unistd.h ssize_t read(int fd, void *buf, size_t count);fd 参数是文件描述符一个进程的整数编号。6. 文件描述符与标准流FILE* 返回值里面封装了文件描述符 fd例如 stdin、stdout、stderr 这些对应的是 0、1、2。7. 重定向更改文件描述符的指针指向。8. 重定向原理文件描述符的分配规则最小的、没有被使用的作为新的 fd 给用户。int dup2(int oldfd, int newfd);作用让newfd指向oldfd所关联的文件fd 0 — stdin 标准输入默认键盘fd 1 — stdout 标准输出默认终端屏幕fd 2 — stderr 标准错误默认终端屏幕fd 3第一个空闲可用的文件描述符进程新建文件、socket优先分配最小空闲 fd0/1/2 被占用所以新打开文件一般拿到 3。例子:int dup2(3, 1);重定向之后可以进行close(oldfd)重定向的方式可以是清空重定向,追加重定向,同样的使用O_TRUNC,O_APPEND选项.所以重定向就是:打开文件的方式(追加,只读等)dup2(从哪里到哪里,使用文件描述符)标准输出重定向覆盖标准输出重定向追加标准输入重定向重定向一定是子进程进行重定向重定向细节当从标准输出重定向到一个指定文件log.txt时,1和2指向的标准输出和错误都是同一个显示器./out.cc log.txt //其中的1会省略,即标准输出 ./out.cc 1 log.txt //当你使用标准erro时,还是会显示到显示器上面 ./out.cc 1 log.normal 2log.erro为什么需要存在一个标准错误:可以通过重定向的能力,把常规消息和错误消息进行分离.如果我们不想将标准错误和标准输出的内容进行分开./out 1log.txt 2log.txt //使用追加重定向 ./out 1log.txt 21 //让2标准错误完全复制 1 号通道。9.引用计数基础定义引用计数内核给「文件表项」设置一个数字记录当前有多少个文件描述符指向这同一个文件表。二.理解一切皆文件我们只要拿到上层的文件描述符就可以通过struct file里面的函数指针(指向函数方法,读写等)来访问不同的硬件(键盘,磁盘等),就是c版本的多态1.缓冲区缓冲区就像一个快递站,在你忙碌的时候可以将你的包裹暂存,不至于停下手中的工作. 提高各方的效率.什么是缓冲区:内存的一段空间在c标准库中会有用户级的语言缓冲区,使用库函数(printf,fprintf.fput,fwrite)并不是直接到文件内核缓冲区,当用户(强制刷新,刷新条件满足,进程退出)的时候才会通过(fd系统调用write等)进入到内核缓冲区,fd可以找到对应文件,在满足条件的时候就可以通过fd找到对应文件写入内核缓冲区再写入到对应的硬件一个文件都要有自己的缓冲区,FILE是一个结构体,里面有fd和缓冲区指针2.缓冲的几种方式:1.立即刷新---无缓冲---写透模式WT2.缓冲区满了---全缓冲---缓冲区最满,效率最高!(普通文件)3.行刷新---行缓冲(显示器)系统调用是有成本的,所以我们通过语言缓冲区来加快效率我们只要将数据交给OS,就相当于交给了硬件!数据交给系统,交给硬件---本质全是拷贝!计算机流动的本质:一切皆拷贝