I/O: 是一切实现的基础!!!
文件IO:(man 2)文件描述符是文件IO中贯穿始终的类型
- 文件描述符的概念
-
- 整型数,数组[1024]的下标,文件描述符优先使用小的
- 当没有指针指向文件结构体时(计数器为0时),结构体才会被释放
- /dev/fd 虚拟目录
- 文件IO的操作
-
- open(); 使用变参函数实现 (有creat则可使用三参形式(0666))
-
int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);
-
flags是一个位图
- 必选项三选一:O_RDONLY只读, O_WRONLY只写, O_RDWR读写
- 可选项
- O_TRUNC 截断
- O_CREAT 创建
- O_EXCL 只创建
- O_APPEND 追加
- O_DIRECTORY 只打开目录
- O_NOATIME 不更新访问时间
- O_NONBLOCK 非阻塞
- O_NOFOLLOW 不打开符号链接
buf是写的缓冲区,cache是读的缓冲区
-
- close();
-
int close(int fd);
-
- read();
-
ssize_t read(int fd, void *buf, size_t count);
-
- write();
-
ssize_t write(int fd, const void *buf, size_t count);
-
- lseek(); = fseek() + ftell()定位指针并返回当前位置
-
off_t lseek(int fd, off_t offset, int whence);
-
- open(); 使用变参函数实现 (有creat则可使用三参形式(0666))
- 文件IO/标准IO区别(!)
-
- 举例:传达室老大爷跑邮局(系统调用IO没有缓冲机制)
- 区别:响应速度(系统调用IO快) 和 吞吐量(标准IO大:合并系统调用)
- 面试:如何使程序变快? 一分为二 什么是快?
- 转化
-
int fileno(FILE * stream); FILE * fdopen(int fd, const char * mode);
-
- 提醒:不可混用(二者不同步)
- strace命令 strace ./ab可以查看一个可执行程序如何进行系统调用
- IO的效率问题
-
- 习题:mycp程序中,把BUFSIZE之逐渐放大,观察消耗的时间(用大文件)
- 注意性能最佳拐点以及程序何时出问题
- 文件共享
-
- 面试:删除一个文件的第10行
- 补充:截断truncate/ftruncate
- 原子操作:不可分割的操作
-
- 作用:解决竞争和冲突
- 别人只能看到我执行操作之前和执行之后
- write函数没有原子性
- 重定向
-
- 把旧的fd复制一份
-
int dup(int oldfd);
-
- 把旧的fd复制新的位置上 (新位置原本的fd被关闭)
-
int dup2(int oldfd, int newfd);
-
- 把旧的fd复制一份
- 同步 (暂时用不到)
-
-
commit buffer cache to disk 通常关机(解除设备挂载)的时候同步void sync(void);
-
同步指定文件int fsync(int fd);
-
只刷数据,不刷亚数据。int fdatasync(int fd);
-
- fcntl();
-
int fcntl(int fd, int cmd, ...);
- 文件描述符相关的魔术都来源于fcntl(功能杂杂杂杂杂杂)
- ioctl();
-
int ioctl(int fd, int request, ...);
- 设备相关的内容(瑞士)
- "一切皆文件"唯独损害了设备相关程序员的利益(介绍很少很少)
-
虚目录:/dev/fd/(当前进程的文件描述符信息)(当前进程:谁访问/dev/fd谁就是当前进程 例如ls -al就是ls进程)
-
文件描述符:
- 内核里为每个进程分配进程控制块
- 进程控制块中有一个指针指向文件描述符表(实质为数组)
- 文件描述符表是一个指针数组,每个元素指向一个文件表
- 文件表包含 pos inode 等信息
- 文件描述符表的下标就是文件描述符