什么是I/O?
I/O即输入/输出(Input/Output),是在主存和外部设备(如磁盘驱动器、终端和网络)之间拷贝数据的过程。输入操作时从I/O设备拷贝数据到主存,而输出操作是从主存拷贝数据到I/O设备。
什么是UnixI/O?
要知道I/O设备都是千差万别的,有磁带、有磁盘、有光驱、有终端、有网络,但这些设备无外乎就做两件事,输入和输出。所以在Unix的对此就设计得非常聪明,将所有的I/O设备,如网络、磁盘和终端,都模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来执行。这种将设备优雅地映射为文件的方式,允许Unix内核引出一个简单、低级的应用接口,称为Unix I/O。这使得所有的输入和输出都能以一种统一且一致的方式来执行。这样就极大程度地简化了提供给程序员的设备接口。
一切皆文件
前面也提到了一切设备都映射为文件,文件可以分为如下几类:
特殊文件(special file):所有的设备都用文件来表示,这些文件被称为特殊文件(special file),存放在/dev中。因此,磁盘文件和其他设备都用同一的方式来命名和访问。
正常文件(regular file): 只是磁盘上的一个普通文件。
块特殊文件(block special file):表示特性与磁盘类似的设备。磁盘驱动程序以块或者组块的形式从块特殊设备中传送信息,这些设备通常具有从设备任何地方检索块的能力。
字符特殊文件(character special file):表示特性和终端类似的设备。这些设备看起来表示的是一串必须按照顺序访问的字节流。
文件描述符
一个应用程序通过要求内核打开相应的一个文件,来宣告他要访问一个I/O设备。内核返回一个非负整数,叫做文件描述符。文件描述符相当于一个逻辑句柄,以此将文件或物理设备进行关联,操作这个文件描述符就等同于操作这个文件或物理设备。
Unix Shell创建的每个进程开始时都有三个打开的文件:标准输入、标准输出、标准错误
文件描述符 |
对应的数字 |
STDIN_FILENO 标准输入设备 |
0 |
STDOUT_FILENO 标准输出设备 |
1 |
STDERR_FILENO 标准错误设备 |
2 |
描述符表(descriptor table)
每个进程又有它独立的描述符表,它的表项是由进程打开的文件描述符来索引的。每个打开的描述符表项指向文件表中的一个表项。
文件表(file table)
打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。每个文件表的一个条目包含有当前的文件位置、引用计数(reference count)(即当前有多少个描述符指向了这个文件),以及一个指向v-node表中对应条目的指针。关闭一个描述符会减少相应的文件表条目中的引用计数。内核不会删除这个文件表的单条记录,直到它的引用计数为0.
v-node表(v-node table)
同文件表一样,所有的进程共享这张v-node表。每个表项包含stat结构中的大多数信息,包括st_mode和st_size成员。当程序打开一个当前没有打开的特定物理文件时,内核会在v-node表中创建一个条目。
上图为典型的打开文件的内核数据结构,两个描述符引用不同的文件。
了解了上面的概念之后,再进一步熟悉一下Unix I/O的API
Unix I/O API
1.打开和关闭文件
open函数:
open函数将一个文件描述符与一个文件或物理设备关联起来。程序可以通过调用open函数来打开或创建一个文件
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
int open(char *path , int flags, mode_t mode);
返回:成功的话返回打开的文件描述符(filedes),失败返回-1并设置errno.
path
指向文件或设备的路径名。
flags
为打开的文件指定状态标识符和访问模式。
可以通过对访问模式标识符和附加标识符进行按位或(|)的方式来构建oflag。访问模式标识符的POSIX值为O_RDONLY,O_WRONLY,O_RDWR。必须指定其中一个来说明只读,只写或读写访问。
附加标识符包括
O_APPEND 写操作之前使文件偏移到文件末端,用于向一个已存在文件添加内容
O_CREAT, 如果文件不存在,则创建之,同时必须向open函数传递第三个参数来指定权限
O_EXCL, 避免重写文件,使用O_CREAT | O_EXCL的形式。如果文件已存在,则报错
O_NOCTTY, 防止一个已打开的设备变成一个控制终端
O_NONBLOCK, 控制open是立即返回还是阻塞到设备维持好
O_TRUNC 与APPEND相反,将写操作打开的文件长度删减为0
mode
为访问权限。如果要创建一个文件,就要包含第三个参数来指定访问权限。
比如以只读方式打开:
int fd;
fd = open("foo.txt",O_RDONLY);
用户可以对新文件进行读写,所有其他人则只有读权限:
int fd;
mode_ t fdmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_ IROTH);
if((fd = open("info.dat",O_RDWR | O_CREAT , fdmode))==-1)
perror("...");
close函数:
用于关闭一个打开的文件
#include <unistd.h>
int close(int fd);
返回:成功为0,出错为-1
用户可以对新文件进行读写
2.读和写文件
用户可以对新文件进应用程序通过调用read和write函数来执行输入和输出的。
read函数:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t n);
返回:若成功则为读的字节数,若EOF则为0,若出错为-1
read函数从描述符为fd的当前文件位置拷贝最多n个字节到存储器位置buf。
write函数:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t n);
返回:若成功则为写的字节数,若出错则为-1
write函数从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。
Standard I/O(标准I/O)
ANSI C定义了一组高级输入输出函数,称为标准I/O库,为程序员提供了Unix I/O的较高级别的替代。这个库(libc)提供了打开和关闭文件的函数(fopen 和 fclose)、读和写字节的函数(fread和fwrite)、读和写字符串的函数(fgets和fputs),以及复杂的格式化的I/O函数(scanf和printf)。
标准I/O函数是磁盘和终端设备I/O之选。大多数C程序员在他们的职业生涯中只使用标准I/O,大多数情况下也推荐使用标准I/O。
- 大小: 46 KB
分享到:
相关推荐
本篇文章将探讨BIOS的入门知识,特别是与I/O(输入输出)相关的部分,并提供相关的参考代码实现。本文会涉及到C语言编程、CMOS配置以及SupperIO技术。 首先,我们来理解一下C语言在BIOS编程中的作用。C语言是一种...
这篇文章探讨了在集群平台上芯片多处理器系统上对批处理模式应用程序进行动态I/O感知调度的重要性。文章提出了一种动态I/O感知调度算法,旨在减少I/O竞争的影响,并提高批处理中应用程序的并发运行性能。 首先,...
本篇文章以西门子的S7-200 PLC为研究对象,探讨了三种扩展PLC I/O点的方法。 首先,硬件电路设计是扩展I/O点的基础。通过合理的设计,可以有效地解决点数不足的问题。一种常见的方法是分时分组,即通过PLC的内部...
本篇文章将深入探讨Java I/O中的过滤流,以及如何利用它们进行带格式的读写操作。 过滤流是一种特殊的流,它不直接与原始数据源或目的地交互,而是建立在其他流之上,对数据进行处理或添加额外功能。Java I/O库中的...
在微控制器或嵌入式系统中,数字I/O接口是实现与外部世界交互的基础。 3. 数据采集: 在更广泛的上下文中,"更多官方数据采集相关资料.htm"可能提供关于如何有效地收集、存储和处理来自模拟和数字传感器的数据的...
本篇“常用医学英语构词索引表”旨在帮助读者掌握这些基础,以便更好地阅读、理解和交流医学信息。以下是一些关键的医学英语构词元素及其含义: 1. **前缀**: - `a-`, `an-`:表示“无”,如`anemia`(贫血) - ...
开发环境是基于Dynamic C的,提供了完整的TCP/IP协议栈和各种I/O驱动,有利于EPA通信协议的快速开发和调试。 最后,文章讨论了选用占先式多任务模式(μC/OS-II)的原因,主要是因为实时性的要求,确保功能块模块...
本篇文章将深入探讨Java I/O系统的核心概念、主要类库以及常见使用场景。 首先,Java I/O系统的基础是`java.io`包,它提供了许多用于处理不同类型的流的类。这些流分为字符流和字节流两大类。字符流处理的是Unicode...
Java语言程序设计的基础篇中,第十九章主要探讨了二进制输入/输出(I/O)的概念和使用。在Java中,I/O操作涉及到文件的读取和写入,这对于任何程序设计都至关重要。本章主要涵盖了以下几个核心知识点: 1. **Java中的...
本篇文章将深入探讨Windows Socket的五种I/O模型,包括同步阻塞、同步非阻塞、异步非阻塞(即I/O重叠)、多路复用(select/poll)以及完成端口(IOCP)模型。这些模型各有优缺点,适应不同的应用场景。 首先,我们...
- dog 和 bird:发音不同,dog中的"o"发短元音/ɒ/,bird中的"i"发短元音/ɪ/。 - like 和 big:发音不同,like中的"i"发长元音/aɪ/,big中的"i"发短元音/ɪ/。 - five 和 photo:发音相同,两词的"o"都发长元音...
【文件I/O基础】 在UNIX环境中,文件I/O是程序与存储设备交互的基本方式,主要涉及五个核心函数:`open`、`read`、`write`、`lseek`和`close`。这些函数构成了不带缓存的I/O(unbuffered I/O),即每次读写操作都会...
本篇文章主要探讨了I/O阻塞与非阻塞操作的应用,以及socket多路复用技术,包括socket信号驱动、UDP广播与组播通信。这些概念和技术在开发高性能服务器和实时通信系统中尤为重要。 首先,I/O阻塞和非阻塞操作是两种...
本篇将重点讲解飞思卡尔单片机(以Freescale品牌为例)的I/O口操作以及基本的程序框架。 一、飞思卡尔单片机I/O口 I/O口是单片机与外部世界交互的关键部分,它允许单片机读取外部设备的状态或向外部设备发送命令。...
这篇PPT教案主要针对小学阶段的学生,旨在帮助他们学习和练习英语中的元音音标。元音音标是英语发音的基础,对于正确发音和理解英语至关重要。以下是对内容的详细解释: 1. 练习一的目标是让学生辨别同音字母或字母...
1. **基础篇**(01): - **Python安装与环境配置**:介绍如何下载Python安装包,进行安装,并设置环境变量。 - **基本语法**:包括变量、数据类型(如整型、浮点型、字符串、布尔型、列表、元组、字典和集合)、...
9. **输入/输出(I/O)**:Java的I/O流系统支持对文件、网络和其他数据源的数据读写。了解InputStream和OutputStream,以及BufferedReader和PrintWriter等类的使用是必不可少的。 10. **字符串处理**:String类是不...
1. **Java I/O基础** - Java I/O库提供了大量的类和接口,如InputStream、OutputStream、Reader、Writer等,用于处理不同类型的输入和输出操作。 - FileInputStream和FileOutputStream用于与文件进行字节流通信,...
Java语言中的二进制输入/输出(Binary I/O)是程序设计中不可或缺的一部分,尤其是在处理非文本数据如图像、音频或自定义数据结构时。在本章中,我们将深入理解二进制I/O与文本I/O的区别,并探讨Java I/O框架如何...
随着Google I/O 2010大会上正式发布代号为“Froyo(冻酸奶)”的Android 2.2操作系统,随之而来的是Android SDK 2.2的推出。新版本不仅带来了性能上的显著提升,还增加了对Flash 10.1的支持,并在用户界面与功能上做...