文件I/O

文件描述符

对于内核而言,所有打开的文件都通过文件描述符引用。文件描述符是一个非负整数,每一个进程默认有三个已经打开的文件描述符与之关联,分别是标准输入0,标准输出1和标准错误2。POSIX规范在头文件unistd.h中对此定义了三个符号常量STDIN_FILENO,STDOUT_FILENO和STDERR_FILENO。

任何一个进程可以同时打开的文件数是有限制的,这个限制通常是由limits.h头文件中的常量OPEN_MAX定义的,它的值随系统的不同而不同,但POSIX规范要求它至少为16。

open函数

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

open函数用来打开或创建一个文件,若成功返回文件描述符,否则返回-1。

pathname是要打开或创建文件的名字。

oflag参数是下列一个或多个常量执行按位或运算的结果杀

  • O_RDONLY  只读打开
  • O_WRONLY    只写打开
  • O_RDWR           读写打开

上面三个常量必须指定一个并且只能指定一个,下面一些常量则是可选的:

  • O_APPEND  将写入追加到文件的尾端
  • O_CREAT          若文件不存在,则创建它。使用该选项时,需要第三个参数mode,用来指定新文件的访问权限位
  • O_EXCL             如果同时指定了O_CREAT,而文件已经存在,则会出错
  • O_TRUNC          如果此文件存在,而且为只写或读写模式成功打开,则将其长度截短为0
  • O_NOCTTY        如果pathname指的是终端设备,则不将该设备分配作为此进程的控制终端
  • O_NONBLOCK   如果pathname指的是一个FIFO文件、块设备文件或字符设备文件,则此选项将文件的本次打开操作和后续的I/O操作设置为非阻塞模式

下面三个标志也是可选的。它们是Single UNIX Specification(以及POSIX.1)中同步输入和输出选项的一部分:

  • O_DSYNC  使每次write等待物理I/O操作完成,但是如果写操作并不影响读取刚写入的数据,则不等待文件属性被更新
  • O_RSYNC       使每一个以文件描述符作为参数的read操作等待,直到任何对文件同一部分进行的未完成写操作都完成
  • O_SYNC          使每次write都等待物理I/O操作完成,包括由write操作引起的文件属性更新所需的I/O

mode参数仅在oflag参数指定了O_CREAT选项时才被使用,用来指定新文件的访问权限位,这些标志在头文件sys/stat.h中定义:

  • S_IRUSR  读权限,文件属主
  • S_IWUSR  写权限,文件属主
  • S_IXUSR        执行权限,文件属主
  • S_IRGRP       读权限,文件所属组
  • S_IWGRP       写权限,文件所属组
  • S_IXGRP        执行权限,文件所属组
  • S_IROTH        读权限,其他用户
  • S_IWOTH       写权限,其他用户
  • S_IROTH        执行权限,其他用户

有几个因素会对文件的访问权限产生影响。首先,指定的访问权限只有在创建文件时才会使用。其次,用户掩码会影响到被创建的文件的访问权限,也就是说,open给出的mode值与用户掩码的反值做AND运算后的结果,才是文件的真实访问权限。由open返回的文件描述符一定是最小的未被使用的描述符数值。

creat函数

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

也可以调用creat函数创建一个新文件,该函数等效于: open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode); 函数执行成功返回打开的文件描述符,否则返回-1。

creat的一个不足之处是它以只写方式打开所创建的文件。

close函数

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

close函数关闭一个打开的文件,执行成功返回0,否则返回-1。

关闭一个文件时还会释放该进程加在该文件上的所有锁。当一个进程终止时,内核会自动关闭它所有打开的文件。

lseek函数

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

每个打开的文件都有一个与其相关联的当前文件偏移量。它通常是一个非负整数,用以度量从文劲啊开始处计算的字节数。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。按系统的默认情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0。

可以调用lseek显示地为一个打开的文件设置其偏移量。对参数offset的解释与参数whence的值有关:

  • 若whence是SEEK_SET,则该文件的偏移量设置为距文件开始处offset个字节。
  • 若whence是SEEK_CUR,则该文件的偏移量设置为当前值加offset,offset可为正或负。
  • 若whence是SEEK_END,则该文件的偏移量设置为文件长度加offset,offset可为正或负。

若lseek执行成功,则返回新的文件偏移量,否则返回-1。

通常,文件的当前偏移量应当是一个非负整数,但是,某些设备也可能允许负的偏移量。但对于普通文件,则其偏移量必须是非负值。因为偏移量可能是负值,所以在比较lseek的返回值时应当谨慎,不要测试它是否小于0,而要测试它是否等于-1。

lseek仅将当前的文件偏移量记录在内核中,它并不引起任何I/O操作。然后,该偏移量用于下一个读或写操作。

文件偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将加长该文件,并在文件中构成一个空洞,所有位于文件中但并没有写过的字节都被读为0。

read函数

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

调用read函数从打开的文件中读取数据,如果执行成功,则返回读到的字节数,若已到文件末尾则返回0,出错则返回-1。

write函数

#include <unistd.h>
ssize_t write(int filedes, const void *buf, size_t nbytes);

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

其返回值通常与参数nbytes的值相同,否则表示出错。

下面是一个示例程序,用来演示底层I/O函数的用法。

 1 #include <unistd.h>
 2 #include <sys/stat.h>
 3 #include <fcntl.h>
 4 #include <stdlib.h>
 5
 6 int main(void)
 7 {
 8     char block[4096];
 9     int in, out;
10     int nread;
11
12     in  = open("file.in", O_RDONLY);
13     out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP);
14     while ((nread = read(in, block, 4096)) > 0) {
15         write(out, block, nread);
16     }
17
18     exit(0);
19 }
时间: 2024-10-07 08:52:00

文件I/O的相关文章

UNIX 环境高级编程 文件和目录

函数stat , fstat , fstatat , lstat stat函数返回与此文件有关的信息结构. fstat函数使用已打开的文件描述符(而stat则使用文件名) fstatat函数 为一个相对于当前打开目录的路径名返回文件信息. lstat函数返回该符号链接的有关信息,而不是该符号链接引用的文件的信息. 使用stat最多的地方可能就是 ls -l 命令. st_mode  与 S_IFMT 进行 与 运算 在与 S_IFXXX常量相比较,来判断类型. 文件类型 1.普通文件: 无论是文

unix环境高级编程——文件i/o

一.文件描述符 对于内核,通过文件描述符来管理文件.什么是文件描述符? 在unix中,用open或者create建立几个文件时候,内核向进程返回一个整数,用来记录此文件. 以后对文件进行操作的时候,就用此文件描述符做引用. 二.open函数 open函数用于建立一个文件,函数返回文件描述符. [cpp] view plaincopy #include <fcntl.h> int open(const char *pathname, int flag); int open(const char 

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

大多数文件I/O 只需要用到 5个函数 :    open , read , write , lseek , close 本章描述的都是不带缓冲的I/O(read write 都调用内核中的一个系统调用) 文件描述符 对于内核而言,所有文件都通过文件描述符引用. 文件描述符是一个非负整数 打开或创建一个新文件时,内核都将返回一个文件描述符 文件描述符的范围是 0~OPEN_MAX-1 函数 open 和 openat 调用 open 或 openat 可以打开或创建一个文件 int open(

unix环境高级编程——文件操作

一.阻塞io操作和非阻塞io操作 对于阻塞io操作:当cpu得不到需要的文件数据的时候,则将自己挂起,直到有了数据,才能执行下面的操作. 非阻塞io:  当cpu得不到文件时候,其一直在轮询cpu,直达得到数据. 二.文件描述符 对于内核而言,所有打开的文件,都用文件描述符来引用.所有的文件操作都是由内核态完成的,当一个用户的进程创建一个文件时候,内核会给其返回一个文件描述符. 而当用户进程,对文件进行各类读写操作的时候,也是给内核传入文件描述符.这样,就可以对其文件进行操作了. 三.open函

Unix 环境高级编程-----文件操作函数

1. open()   O_RONLY O_WONLY O_RDWR 返回值为 文件描述符fd 2. creat()   创建新文件,这个函数的产生是因为最开始open函数没有O_CREAT 功能,所以单独开发的该函数 注:不是create,没有e 3. read()  读取fd对应的文件内容 4. write() 写信息到fd对应的文件中 5. lseek()  设置当前文件偏移量 SEEK_SET, SEEK_CUR, SEEK_END 6. close()  关闭fd对应的描述符 小结:

UNIX环境高级编程---标准I/O库

前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压根不是一码事.Unix I/O也叫低级I/O,也叫Unbuffered I/O,是操作系统内核部分,也是系统调用:而C标准I/O函数相对也成Buffered I/O,高级I/O,一般是为了效率考虑对这些系统调用的封装.以前使用getchar()经常为输入完后的回车而出错.那是不理解标准I/O实现时的

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

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

《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地址,和登录用

《UNIX环境高级编程》读书笔记 —— 文件 I/O

一.打开或创建一个文件 #include <fcntl.h> int open(const char *pathname, int oflag, .../*mode_t mode*/); 返回值:若成功则返回文件描述符,若出错则返回-1 oflag选项: O_RDONLY O_WRONLY O_RDWR 以上三个常量中必须指定一个,且只能指定一个. 以下常量都是可选的: O_APPED     每次写时追加到文件尾 O_CREAT     若文件不存在,则创建 O_EXCL      若同时指