Unix环境之文件IO

Unix系统中的大多数文件IO只需用到5个函数:open、read、write、lseek以及close。这些函数是不带缓冲的IO,不带缓冲指的是每个read和write都调用内核中的一个系统调用,它们不是ISO/C的组成部分,而是POSIX和SUS的东西。

文件描述符——

对于内核而言,所有打开的文件都通过文件描述符引用。文件描述符是一个非负整数,按照惯例,文件描述符0、1、2分别表示的是标准输入、标准输出、标准出错,在依从POSIX的应用程序中,这3个幻数应当替换为符号常量STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO,这些常量定义在头文件

open函数——

#include <fcntl.h>
int open(const char *pathname, int flags[, mode_t mode]);

调用open函数可以打开或创建一个文件,若成功则返回文件描述符,一定是最小的未用描述符数值,若出错则返回-1。pathname是要打开或创建文件的名字,当整个路径名超过PATH_MAX或路径名中任一文件名超过NAME_MAX时,若_POSIX_NO_TRUNC有效,则返回出错状态,并将errno设置为ENAMETOOLONG,否则名字可能被截断。flags参数可用来说明函数的多个选项,用一个或多个常量进行“或”运算构成,常量如O_RDONLY等以大写字母O和一个下划线开头。mode参数仅当创建新文件时才使用,用于指定该新文件的访问权限位,与进程的umask值有关。

create函数——

#include <fcntl.h>
int create(const char *pathname, mode_t mode);

调用create函数也可以创建一个新文件,等效于如下open函数:

open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);

close函数——

#include <unistd.h>
int close(int fd);

调用close函数关闭一个打开的文件,成功返回0,出错返回-1。当一个进程终止时,内核会自动关闭它打开的所有文件,这样可不必显式地调用close关闭打开的文件,文件关闭时还会释放该进程加在它身上的所有记录锁。

lseek函数——

#include <unistd.h>
off_t lseek(int fd, off_t offset, in whence);

调用lseek函数为一个打开的文件设置偏移量,成功返回新的文件偏移量,出错返回-1。lseek仅将当前的文件偏移量记录在内核中,它并不引起任何IO操作,然后该偏移量用于下一个读或写操作。whence参数可以是SEEK_SET、SEEK_CUR、SEEK_END中的一个,分别表示偏移量的基准位置为文件开头、文件当前位置、文件结尾。offset可以大于文件的当前长度,在这种情况下,对该文件的下一次写将加长该文件,并在文件中构成一个空洞,位于文件中但没有写过的字节都被读为0,然而文件中的空洞并不要求在磁盘上占用存储区。

read函数——

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

调用read函数从打开的文件中读取数据,成功返回读到的字节数,到达文件末尾返回0,出错返回-1。

write函数——

#include <unistd.h>
ssize_t write(int fd, cosnt void *buf, size_t count);

调用write函数向打开的文件中写入数据,成功返回写入的字节数,出错返回-1。

IO效率——

《UNIX环境高级编程》一书描述了不同的buffer长度对IO效率的影响,例子中使用read和write函数复制一个文件,文件长度为103316352字节,buffer长度从1到512k,测试了不同buffer长度下的用户CPU时间、系统CPU时间、时钟时间以及循环次数,结果显示,buffer长度为4096字节时效率最高,即一个block的大小。大多数文件系统为改善其性能都采用某种预读技术,当检测到正进行顺序读取时,系统就试图读入比应用程序所要求的更多数据,并假想应用程序很快就会读这些数据。

文件共享——

UNIX系统支持在不同进程间共享打开的文件。内核使用三种数据结构表示打开的文件,分别是进程表记录项、文件表记录项、v节点,同一个文件共享一个v节点表项。文件共享必然是一个原子操作,即这个操作要么不执行,要么一次性执行完毕,执行过程中没有任何干扰,例如执行lseek和read函数,本意是先定位文件偏移量再读取数据,如果两个函数执行之间插入了别的操作就有可能带来副作用,正确的做法是对这个操作加锁,或者是使用一个等效的替代函数pread,这个函数就好像是把lseek和read当作一个原子操作一样。

文件操作——

#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);

dup和dup2两个函数都可以用来复制一个现有的文件描述符,它们共享同一个文件表项,这个操作还可以由fcntl函数实现。

#include <unistd.h>
void sync(void);
int fsync(int fd);
int fdatasync(int fd);

传统UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘IO都通过缓冲进行。当将数据写入文件时,内核通常先将数据复制到其中一个缓冲区中,如果该缓冲区尚未写满,则并不将其排入输出队列,而是等待其写满或者当内核需要重用该缓冲区以便存放其它磁盘数据时,再将该缓冲排入输出队列,然后待其到达队首时,才进行实际的IO操作。这种输出方式被称为延迟写。延迟写减少了磁盘读写次数,但是却降低了文件内容的更新速度,使得欲写到文件中的数据在一段时间内并没有写到磁盘上。当系统发生故障时,这种延迟可能造成文件更新内容的丢失。为了保证磁盘上实际文件系统与缓冲区高速缓存中内容的一致性,UNIX系统提供了sync、fsync和fdatasync三个函数。sync函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束,通常称为update的系统守护进程会周期性调用sync函数。fsync和fdatasync对指定的文件描述符起作用,并且等待写磁盘操作结束,后者只影响文件的数据部分。

#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */);

fcntl函数可以改变已打开文件的性质,重点是cmd参数,功能包括现有描述符的复制,获得和设置文件描述标记、文件状态标记、异步IO所有权、记录锁。

#include <sys/ioctl.h>
int ioctl(int fd, int request, …);

ioctl函数是IO操作的杂物箱,不能用上面列出的函数表示的IO操作都能用ioctl表示。终端IO是ioctl的最大使用方面。

/dev/fd目录——

/dev/fd目录下是一些名为0、1、2等的文件,打开文件/dev/fd/n等效于复制描述符n,共享同一文件表项。/dev/fd文件主要由shell使用,如下两个命令行等效:

cat file | cat - > tmp
cat file | cat /dev/fd/0 > tmp

cat命令把命令行参数的字符“-”解释为标准输入,等效于使用/dev/fd/0,而后者提高了文件名参数的一致性,看起来更加清晰。

时间: 2024-10-26 09:32:11

Unix环境之文件IO的相关文章

unix环境编程 文件操作

1.  文件的打开读写 关闭 int open(const char *pathname,int flag,-)   打开一个文件 成功则返回文件描述符,若出现则返回-1 flag可以取下面的常量 O_RDONLY  只读打开 O_WRONLY  只写打开 O_RDWR    读写打开 其它的常量 O_APPEND,O_CREAT,O_EXCL,O_TRUNC,O_NOCTTY,O_NONBLOCK是可选的. int create(const char *pathname,mode_t mode

Unix环境之标准IO库

UNIX的文件IO都是针对文件描述符的,而标准IO的操作则是围绕流进行的.当一个流最初被创建时,它并没有定向.若在未定向的流上使用一个多字节IO函数,则将该流的定向设置为宽定向:若在未定向的流上使用一个单字节IO函数,则将该流的定向设置为字节定向. stdio.h定义了三个标准流,stdin.stdout和stderr,分别是标准输入.标准输出和标准出错. 缓冲-- 标准IO库提供缓冲的目的是尽可能减少使用read和write调用的次数.它也对每个IO流自动地进行缓冲管理,从而避免了应用程序需要

Unix环境之文件和目录

文件结构stat-- 下面三个函数可以获取文件的状态信息: #include <sys/stat.h> int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *path, struct stat *buf); stat函数指定文件路径,fstat指定文件描述符,lstat类似于stat,但对于符号链接文件来说,lstat获取的是符号链接文件本

(十一) 一起学 Unix 环境高级编程 (APUE) 之 高级 IO

. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录 (四) 一起学 Unix 环境高级编程 (APUE) 之 系统数据文件和信息 (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境 (六) 一起学 Unix 环境高级编程 (APUE) 之 进程控制 (七) 一起学 Unix 环境高级编程 (APUE)

《UNIX环境高级编程》--5 标准IO库

标准IO库 流和 FILE对象 标准IO库与文件IO区别: 标准IO库处理很多细节,如缓冲区分片.以优化的块长度执行IO等. 文件IO函数都是围绕文件描述符进行.首先打开一个文件,返回一个文件描述符:后续的文件IO操作都使用该文件描述符 标准IO库是围绕流进行的.当用标准IO库打开或者创建一个文件时,就有一个内建的流与之相关联 标准IO库的函数很多都是以 f开头,如fopen.fclose 对于ASCII字符集,一个字符用一个字节表示:对于国际字符集,一个字符可以用多个字节表示. 标准IO文件流

UNIX环境高级编程笔记之文件I/O

一.看图说话 一图胜过千言,看图! 二.唠一唠 在写之前,先唠几句,<UNIX环境高级编程>,简称APUE,这本书简直是本神书,像我这种小白,基本上每看完一章都是“哇”这种很吃惊的表情.其实大概三年前,那会大三,我就买了这本书,也看过一些,但好像没有留下什么印象,今天再看,依然觉得像新的一样.很大的原因我想是一直以来都在用windows(用windows做开发为什么学不到真正的技术,我想大家都懂的),当然知识结构不完整,学习能力这些就不说了.所以,对于那些致力于想在Linux下做开发的人来说,

UNIX,基础知识,文件IO,文件和目录

2015.1.27星期二,早晨阴天,中午下雪了今天上午老师不上课,程序语句,记一下:main(void){ int c; while((c = getc(stdin)) != EOF) if(putc(c,stdout) == EOF) 将字符写到标准输出 err_sys("output error"); if(ferror(stdin)) err_sys("input error"); exit(0);} 从标准输入读命令并执行:int main(){ char

《Unix环境高级编程》读书笔记 第3章-文件I/O

1. 引言 Unix系统的大多数文件I/O只需用到5个函数:open.read.write.lseek以及close 本章描述的函数经常被称为不带缓冲的I/O.术语不带缓冲指的是在用户的进程中对其不会自动缓冲,每个read和write都调用内核中的一个系统调用.但是,所有磁盘I/O都要经过内核的块缓存区(也称为内核的缓冲区高速缓存).唯一例外的是对原始磁盘设备的I/O. 2. 文件描述符 对于内核而言,所有打开的文件都通过文件描述符引用.文件描述符是一个非负整数,其变化范围是0~OPEN_MAX

unix环境高级编程(第三版)中apue.h文件的配置问题

最近刚开始学习unix环境高级编程(第三版),其中有个作者自己写的apue.h文件,在这归总下相应的配置方法,希望对有需要的朋友们有所帮助 首先http://www.apuebook.com/code3e.html 上去下载相应的压缩包,注意自己书的版本. 下载完成之后,鉴于大多数朋友学习linux都是基于虚拟机的,所以顺便附上虚拟机与本地主机传输文件的方式 首先下载SSH Secure Shell 这个工具,然后直接点击quick connect, 弹出如下界面,输入虚拟机的ip地址,和登录用