I_O —基础概念(参照 Ubuntu 16.04 版本)

一、文件的概念
  • 定义:
  1. 所谓文件是指一组相关数据的有序集合,这个数据集有一个名称,叫文件名。如源程序文件,目标文件,可执行文件,头文件等
  2. 文件通常是在驻留在外部介质上的,使用时才调入内存
  • 分类:
  1. 文件类型:
普通文件 -
指ASCII文本文件、二进制文件以及硬链接文件
目录文件 d
包含若干文件或子目录
符号链接
只保留所指向文件的地址而非文件本身
管道文件
用于进程间通信
字符设备文件
原始的I/O设备文件,每次操作仅操作1个字符(例如键盘)
块设备
按块 I/O 设备文件(例如硬盘)
套接字
进程间通信的特殊文件,与管道不同的是套接字能通过网络连接使不同的计算机的进程进行通信
  1. 从文件的编码方式划分:
文本文件(普通文件)
以ACSII 码格式存放,一个字节存放一个字符。文本文件的每一个字节存放一个ASCII码,代表一个字符。
特点:
便于对字符的逐个处理
占用存储空间较多
转换为二进制速度慢
直观易记。
实例:整数 10000 0011000100110000001100000011000000110000 A 65 a 97
二进制文件
把数据以二进制数的格式存放在文件中
特点:
占用存储空间较少
无需数据转换
按其内存中的存储形式原样存放,字节不对应字符。
不能直接输出字符形式。
实例:整数10000 0010011100010000
  • Linux 系统的文件目录结构
  1. 树形结构
  2. 目录分类
/etc 存放系统配置文件
/bin 存放常用指令
/sbin (root用户的)存放指令目录
/home 用户主目录,所有用户文件默认建立在此目录下
/boot 包含内核启动文件
/dev 存放设备文件(与底层驱动交互)
/usr 存放应用程序
/mnt 挂载目录
/root root用户主目录
/proc process的所写,存放描述系统进程的详细信息
/lib 存放常见库文件
/lost+found 可以找到一些误删除或丢失的文件并恢复它们


二、系统调用与用户编程接口(API)
  • 系统调用(System Call)
  1. 由操作系统实现提供的所有系统调用所构成的程序接口的集合
  2. 是应用程序与操作系统间的接口与纽带
  3. 主要功能:
为管理硬件资源和应用程序开发人员提供良好的环境
使应用程序具有良好的兼容性
内核提供一系列具备预定功能的函数,通过系统调用的接口呈现给用户
当用户访问系统调用,系统调用把应用程序的请求传递给内核,调用相应的内核函数完成所需处理,将处理结果返回给应用程序。
  • 应用程序编程接口(API,Application Programming Interface)
    1. 预定义的函数
    2. 提供基于软件/硬件的应用程序使开发人员具有访问一组例程的能力,同时开发人员又无需访问源码或理解内部工作原理机制
  • 系统调用与 API 比较
系统调用功能非常简单,有时无法满足程序的需求
不同操作系统的系统调用接口不兼容,若使用系统调用接口则程序移植工作量非常大
API 使用各种库中的函数
使用 API 程序开发者无需自己编写这些代码,直接可以调用函数就能实现功能,提高了编码效率和代码复用率
使用 API 一定程度上解决了程序的可移植性
通常情况下,API 在实现时需要依赖系统调用接口


三、POSIX 简介
  1. POSIX(Portable Operating System Interface):可移植操作系统接口
  2. POSIX 标准定义了操作系统应该为应用程序提供的接口标准,
  3. POSIX 标准是 IEEE 为要在各种 UNIX 操作系统上运行的软件而定义的一系列 API 标准的总称
  4. POSIX 标准正式称呼为IEEE 1003,而国际标准名称为 ISO/IEC 9945
  5. POSIX 标准意在期望获得源代码级别的软件可移植性
  6. 任何 POSIX 兼容的操作系统编写的程序,应该可以在任何其它的 POSIX 操作系统(即使是来自另一个厂商)上编译执行。


四、文件系统和 IO
  • 分类:
  1. 缓冲文件系统
  2. 非缓冲文件系统
  • 缓冲文件系统:
  1. 系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区。从磁盘向内存读入数据时,则一次从磁盘文件将一些数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送给接收变量。向磁盘文件输出数据时,先将数据送到内存中的缓冲区,装满缓冲区后才一起送到磁盘区
  2. 用缓冲区可以一次读入一批数据,或输出一批数据,而不是执行一次输入或输出函数就去访问一次磁盘,这样做的目的是减少对磁盘的实际读写次数,提高读写效率
  • 非缓冲文件系统:
  1. 用户根据需要设置的,非系统自动设置的缓冲区
  2. 在传统的UNIX系统下,用缓冲文件系统处理文本文件,用非缓冲文件系统处理二进制文件
  3. 1983年ANSI C 标准决定不采用非缓冲文件系统,而只采用缓冲文件系统。即用缓冲文件系统处理文本文件,也用它来处理二进制文件。也就是将缓冲文件系统扩充为可以处理二进制文件
  • 输入输出分类:
标准输入输出(标准 I/O):缓冲文件系统的输入输出
文件输入输出(文件 I/O):非缓冲文件系统的输入输出
  • 标准 I/O 特点:
标准 I/O 是 ANSI C 中定义的用于 I/O 操作的一系列函数
标准 I/O 称为高级磁盘 I/O,遵循 ANSI C 相关标准
只要开发环境有标准 C 库,标准 I/O 就可以使用
标准 I/O 在文件 I/O 的基础上封装了缓冲机制,每次先操作缓冲区,必要时再访问文件,从而减少了系统调用的次数
标准 I/O 使用 FILE 指针来表示一个打开的文件,通常只能访问普通文件
  • 文件 I/O 特点:
文件I/O 是基于文件描述符的 I/O 操作
文件 I/O 称为低级磁盘 I/O,遵循 POSIX 标准
任何兼容 POSIX 标准的操作系统都支持文件 I/O
文件 I/O 读写文件时,每次都会执行相关系统调用(执行系统调用时,Linux 系统必须从用户态切换到内核态处理相应的请求,然后再返回用户态),因此会增加系统的开销
文件I/O使用文件描述符打开操作一个文件,可以访问不同类型的文件
  • Linux 系统下的 I/O:
在Linux系统中使用 GLIBC 标准,它是标准C库的超集
GLIBC 标准既支持 ANSI C 中定义的函数又支持 POSIX 中定义的函数
Linux 下既可以使用标准 I/O,也可以使用文件 I/O。


五、Linux标准 I/O
  • 文件流
  1. 含义:
标准I/O的核心对象是流
用标准 I/O 打开一个文件时,就会创建一个 FILE 结构体描述该文件
这个FILE结构体称为“流”
标准 I/O 函数都是基于流进行各种操作的
  1. 分类
文本流
二进制流
在 Linux/Unix 系统中,文本流与二进制流没有差异,但是在 Windows 中稍有差异,所以标准 C 库定义了两种流
  1. 文本流
由字符文件组成的序列
每一行包含 0 个或多个字符并以 \n 结尾
在流处理过程中所有数据以字符形式出现,\n 被当做回车符 CR 和换行符 LF 两个字符处理,即 \n 在 ASCII 码存储形式是 0x0D 和 0x0A,当输出时,0x0D 和0x0A 转换成 \n
  1. 二进制流
未经处理的字节组成的序列
在流处理过程中把数据当做二进制序列,若流中有字符则把字符当做ASCII 码的二进制数表示。\n 不进行变换。
  1. 实例比较文本流和二进制流
文本流:201---->'2''0''1''6'---->00110010 00110000 00110001 00110110
二进制流:2016---->数字2016---->0000 0111 1110 0000
  1. 三个标准流(FILE*类型指针)
标准输入流(stdin):针对标准输入键盘 scanf
标准输出流(stdout):针对标准输出屏幕 printf
标准错误流(stderr):针对标准输出屏幕
  1. 流的缓冲类型
全缓冲:当缓冲区被填满后才进行实际的 I/O 操作
对于存放在磁盘上的普通文件用标准 I/O 打开时默认是全缓冲的。当缓冲区满或者执行刷新缓冲区(fflush)操作才会进行磁盘操作
行缓冲:当在输入/输出中遇到换行符时执行I/O操作
标准输入/输出流(stdin/stdout)就是使用行缓冲。
无缓冲:不使用缓冲区进行 I/O 操作,即对流的读写操作会立即操作实际文件
标准错误流(stderr)是不带缓冲的,这就使得当发生错误时,错误信息能第一时间显示在终端上,而不管错误信息是否包含换行符。


六、文件操作
  • 文件操作流程:
  1. 标准 I/O 调用流程:
FILE * spIn;
size_t num;
int ret;
spIn = fopen(const char *filename, const char *mode);
#if 1 //以下内容是根据需要进行的相关的操作
num = fread(void *ptr, size_t size, size_t nmemb, spIn);
num = fwrite(const void *ptr, size_t size,size_t nmemb, spIn);
ret = fseek(spIn, long offset, int whence);
ret = ftell(spIn);
rewind(spIn);
……
#endif
fclose(spIn);
  1. 文件 I/O 调用流程:
int fd;
ssize_t size;
fd = open(const char *filename, int flags, mode_t mode);
#if 1//以下内容是根据需要进行的相关的操作
size = read(fd, void *buf, size_t count);
size = write(fd, const void *buf, size_t count);
int creat(const char *filename, mode_t mode);
off_t lseek(fd, off_t offset, int whence);
……
#endif
close(fd);
  • 文件操作相关说明:
  1. 文件类型结构体 FILE 和文件指针
VS2010 里 FILE 结构体:
typedef struct
{
short level;//缓冲区满/空的状态
unsigned flags;//文件状态标志
char fd;//文件描述符
unsigned char hold;//如缓冲区无内容则不读取字符
short bsize;//缓冲区的大小
unsigned char *buffer;//数据缓冲区的位置
unsigned char *curp;//指针当前的指向
unsigned istemp;//临时文件指示器
short token;//用于有效性检查
}FILE;
Linux 里 FILE 结构体:
struct _IO_FILE
{
int _flags; //High-order word is _IO_MAGIC; rest is flags
char* _IO_read_ptr; //Current read pointer
char* _IO_read_end; //End of get area
char* _IO_read_base; //Start of putback+get area
char* _IO_write_base; //Start of put area
char* _IO_write_ptr; //Current put pointer
char* _IO_write_end; // End of put area
char* _IO_buf_base; // Start of reserve area
char* _IO_buf_end; // End of reserve area
char *_IO_save_base; // Pointer to start of non-current get area
char *_IO_backup_base; //Pointer to first valid character of backup area
char *_IO_save_end; //Pointer to end of non-current get area
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
int _flags2;
_IO_off_t _old_offset;` //This used to be _offset but it's too small. _IO_off_t is unsigned long int
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
_IO_lock_t *_lock;
}; //摘自 <libio.h>
typedef struct _IO_FILE FILE; //摘自 <stdio.h>
FILE 的作用:
缓冲文件系统为每个正使用的文件在内存开辟文件信息区
文件信息用系统定义的名为FILE的结构体描述
文件指针 FILE * 的定义:
文件指针实际上是一个文件类型的结构体指针
通过文件指针即可找到存放某个文件信息的文件类型结构体变量,然后按结构体变量提供的信息找到该文件,实施对文件的操作
文件打开时,系统自动创建文件类型结构体变量,并把指向它的指针返回来,程序通过这个指针获得文件信息并访问文件
文件关闭后,文件指针指向的结构体变量会被释放
  • 文件在内核中数据结构表示
  1. 文件描述符(file descriptor)
对于内核而言,所有打开的文件都有文件描述符应用。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读写一个文件时,用 open 或 create 返回的文件描述符标识该文件,将其作为参数传送给 read 或 write
在 POSIX 应用程序中,整数 0,1,2 被替换成符号常数STDIN_FILENO, STDOUT_FILENO 和 STDERR_FILENO,这些常数都定义在头文件<unistd.h>中,见下图
文件描述符的范围是 0-OPEN_MAX。早期的 UNIX 版本采用的上限是 19,允许每个进程打开 20 个文件。现在很多系统将其增加到 1024,查看方法 ulimit -a ,值可修改,但只能对当前进程和子进程有效
文件表项指针
  1. 文件表项
文件状态标志
读写追加,同步和非阻塞等状态标志
当前文件偏移量。
i 节点表项指针
引用计数器
  1. i 节点
文件类型和该文件的操作函数指针
当前文件长度
文件所以者
文件所在设备,文件访问权限
指向文件数据在磁盘块上所在位置的指针等


















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值