Linux:基础IO

打印 上一主题 下一主题

主题 1049|帖子 1049|积分 3147

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录
文件的明白
open函数
文件描述符
0 & 1 & 2
重定向
dup2体系调用
缓冲区
缓冲区的概念
为什么要引入缓冲区机制?
缓冲范例


文件的明白

文件 = 文件内容 + 文件属性
文件是存储在磁盘中的,磁盘是外设,磁盘上文件全部的操作本质都是对外设的输入和输出,简称IO
Linux下齐备皆文件
全部的文件操作本质是文件内容操作和文件属性操作
open函数

  1. int open(const char *pathname, int flags);
  2. int open(const char *pathname, int flags, mode_t mode);
复制代码
pathname表示要打开或创建的目标文件
flags表示打开文件时传入必要的参数,具体如下:


  • O_RDONLY:只读打开
  • O_WRONLY:只写打开
  • O_RDWR:读,写打开
  • (以上只能且必须三选一)
  • O_CREAT:若文件不存在,则创建。创建的文件权限必要用到mode选项
  • O_APPEND:追加写
mode表示若创建文件则权限的巨细
返回值:


  • 成功:新打开的文件描述符
  • 失败:-1
mode_t范例是一个整数范例
文件描述符

文件描述符fd就是一个小整数,从0开始
0 & 1 & 2

Linux进程默认情况下会有3个缺省打开的文件描述符fd,分别是尺度输入0,尺度输出1,尺度错误2
0,1,2分别对应的物理设备为:键盘,表现器,表现器

当我们打开文件时,操作体系在内存中要创建相应的数据结构来描述目标文件,于是就有了file结构体
每个进程都有一个*files指针,它指向了一张表files_struct,该表包含了一个指针数组,这个指针数组每一个元素都是指向打开文件的指针,本质上文件描述符就是该指针数组的下标,这样有文件描述符就能找到相应的文件了
文件描述符的分配规则:
在flies_struct数组中,找到当前没有被利用的最小的一个下标,作为新的文件描述符
所以0,1,2关闭后是可以被替换的,这也是重定向的原理
重定向

常见的重定向有:>,>>,<

 

我们正常的echo后面的内容是直接打印到表现器上

但是当我们重定向后表现器上就没有打印该文字了,而是将文字直接写到了重定向的文件中
本质上是把文件描述符1关闭,变成了我们新创建的test.txt文件,这样只要是即将在表现器1号文件描述符上输出的就都会写到test.txt文件中
dup2体系调用

  1. #include <unistd.h>
  2. int dup2(int oldfd, int newfd);
复制代码
 我们在代码中也想重定向就可以利用dup2体系调用
echo "hello world" > test.txt就相当于dup2(fd, 1); fd表示test.txt的文件描述符,1是我们要替换的文件描述符
缓冲区

缓冲区的概念

缓冲区是内存空间的一部分,在内存空间中预留了一定的空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫缓冲区
缓冲区分为输入缓冲区和输出缓冲区
为什么要引入缓冲区机制?

如果没有缓冲区,直接通过体系调用对磁盘进行操作,那么每一次对文件进行一次读或写的时间都必要调用读写体系调用来处理,执行一次体系调用将涉及到CPU状态的切换,即从用户空间切换到内核空间,实现进程上下文的切换,这样频繁的磁盘访问对程序的执行效率会造成很大的影响
为了解决以上题目,我们就可以引入缓冲区机制,我们可以一次从文件中读出大量的数据到缓冲区中,这部分的访问都不必要体系调用,等缓冲区的数据读取完成后再去磁盘中读取,这样可以极大的淘汰调用体系调用的次数,大大提高了计算机的运行速度
缓冲范例

尺度I/O提供了3种范例的缓冲区


  • 全缓冲区:这种缓冲方式要求填满整个缓冲区后才进行I/O体系调用操作。对于磁盘文件的操作通常利用全缓冲的方式访问。这也是效率最高的一种范例
  • 行缓冲区:当输入和输出种遇到换行符时,尺度I/O库函数将会执行体系调用操作。当所操作的流涉及一个终端时,利用行缓冲方式
  • 无缓冲区:无缓冲区是指尺度I/O库不对字符进行缓存,直接调用体系调用
如果我们想强制刷新缓冲区,可以利用fflush强制刷新缓冲区
  1. fflush(stdout);
复制代码

有如下代码: 
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5.     const char *msg0="hello printf\n";
  6.     const char *msg1="hello fwrite\n";
  7.     const char *msg2="hello write\n";
  8.     printf("%s", msg0);
  9.     fwrite(msg1, strlen(msg0), 1, stdout);
  10.     write(1, msg2, strlen(msg2));
  11.     fork();
  12.     return 0;
  13. }
复制代码
运行结果:
  1. hello printf
  2. hello fwrite
  3. hello write
复制代码
但当我们重定向到file文件后,结果变成了:
  1. hello write
  2. hello printf
  3. hello fwrite
  4. hello printf
  5. hello fwrite
复制代码
这是因为:
printf和fwrite这些库函数会自带缓冲区,当重定向到普通文件时,缓冲方式由行缓冲变成了全缓冲,所以我们放在缓冲区的数据并不会被立即刷新
当我们fork的时间,父子数据会发生写时拷贝,父进程预备刷新的时间,子进程也具有雷同的数据(缓冲区),所以就刷新了两份数据到内核级缓冲区中,write没有变化,write是没有缓冲区的
库函数在体系调用的上层,是对体系调用的封装

完 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

麻花痒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表