UNIX系统中的大多数文件I/O仅仅须要用到5个函数:open、read、write、lseek以及close。本章说明的函数常常称为“不带缓冲的I/0”,术语不带缓冲指的是每一个read和write都调用内核中的一个系统调用。

这些不带缓冲的I/O函数不是ISO C的组成部分,可是它们是POSIX.1和Single UNIX Specification的组成部分。

文件描写叙述符:

对内核而言。全部打开的文件都通过文件描写叙述符引用。

文件描写叙述符是个非负整数。依照惯例,UNIX系统shell使用文件描写叙述符0与进程的标准输入相关联。文件描写叙述符1与标准输出相关联,文件描写叙述符2与标准出错相关联。这是各种shell以及很多应用程序使用的惯例。而与UNIX内核无关。在依从POSIX的应用程序中。幻数0、1、2应当替换成符号常量STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO,这些常量都定义在<unistd.h>中。

文件描写叙述符的变化范围是0-OPEN_MAX。

open函数:

调用open函数能够打开或创建一个文件:

#include <fcntl.h>

int open(const char *pathname,  int flag,  .../* mode_t mode */);

返回值,若成功则返回文件描写叙述符,若出错则返回-1

pathname:是要打开或创建文件的名字,flag參数能够说明此函数的多个选项,用下列一个或多个常量进行或运算,构成flag參数。

  • 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操作设置为非堵塞模式;

以下三个标志也是可选的。他们是SUS中同步输入和输出选项的一部分:

  • O_DSYNC:使每次write等物理I/O操作完毕,可是假设写操作并不影响读取刚写入的数据,则不等待文件属性被更新;
  • O_SYNC:使每次write都等到物理I/O操作完毕。包含由write操作引起的文件属性更新所需的I/O(数据和属性总是同步更新);
  • O_RSYNC:使每个以文件描写叙述符作为參数的read操作等待,直至不论什么对文件同一部分的未决写操作都完毕。

open函数返回的文件描写叙述符一定是最小的未用描写叙述符数值。这一点被某些应用程序用来在标准输入、标准输出或标准错误上打开新的文件。

文件名称与路径名截短:

在POSIX.1中,常量_POSIX_NO_TRRUNC决定了是否要截短过长的文件名称或路径名。还是返回一个出错。依据文件系统类型。此值可变。若_POSIX_NO_TRUNC有效。则在整个路径名超过PATH_MAX,或路径名中的随意文件名称超过NAME_MAX时。返回出错状态,并将errno设置为ENAMETOOLONG。

creat函数:

也能够调用creat函数创建一个新文件:

#include <fcntl.h>

int creat(const char *pathname, mode_t mode);

返回值:若成功,则返回仅仅写打开的文件描写叙述符,若出错则返回-1。

此函数等效于:open(pathname,O_WRONLY | O_CREAT | O_TRUNC, mode)。creat函数的一个不足之处是它以仅仅写方式打开所创建的文件。

close函数:

可调用close函数关闭一个打开的文件:

#include <unistd.h>

int close(int fieldes)

返回值:若成功则返回0,若出错则返回-1。

关闭一个文件时。还会释放该进程加在该文件上的全部记录锁。当一个进程终止时。内核自己主动关闭它全部打开的文件。非常多程序都利用这一功能而不显示地用close关闭打开文件。

lseek函数:

每一个打开的文件都有一个与其相关联的当前文件偏移量。

它一般是个非负整数,用以度量从文件開始处计算的字节数。通常,读写操作都从当前文件偏移量处開始,并使偏移量添加所读写的字节数。

依照系统默认情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量设置为0。可调用lseek函数显式地为一个打开的文件设置其偏移量:

#include <unistd.h>

off_t lseek(int fieldes, off_t offset, int whence);

返回值:若成功,则返回新的文件偏移量,若出错则返回-1。

对參数offset的解释与參数whence的值有关:

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

因此可用例如以下方式确定打开文件的当前偏移量:

offset currpos

currpos = lseek(fd, 0, SEEK_CUR);

用上述方法还能够确定所涉及的文件能否够设置偏移量。假设文件描写叙述符引用的是一个管道,FIFO或网络套接字,则leek返回-1,并将errno设置为ESPIPE。

下列程序用于測试是否能对其标准输入设置偏移值:

/*
* Copyright (C) fuchencong@163.com
*/ #include <unistd.h>
#include <stdlib.h>
#include <stdio.h> int
main(void)
{
if (lseek(STDIN_FILENO, 0, SEEK_CUR) < 0) {
printf("can't seek\n");
} else {
printf("seek ok\n");
}
exit(0);
}

通常文件的当前偏移量应当是个非负整数。可是某些设备也可能同意负的偏移量。

可是对于普通文件,其偏移量必须是非负值。lseek仅将当前的文件偏移量记录在内核中,它并不引起不论什么I/O操作。

文件偏移量能够大于文件的当前长度,这样的情况下,对该文件的下一次写将加长该文件。并在文件里构成一个空洞。位于文件里但没有写过的字节都被读为0。文件里的空洞并不要求在磁盘上占用存储区,详细处理方式与文件系统的实现有关。

下列程序用于创建一个具有空洞的文件:

/*
* Copyright (C) fuchencong@163.com
*/ #include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h> #define FILE_NAME "file.hole" int
main(void)
{
char buf_one[] = "abcdefghij";
char buf_two[] = "ABCDEFGHIJ";
int fd; if ( (fd = creat(FILE_NAME, S_IRUSR | S_IWUSR)) < 0) {
printf("create file %s error: %s\n", FILE_NAME, strerror(errno));
exit(1);
} if (write(fd, buf_one, 10) != 10) {
printf("write error: %s\n", strerror(errno));
exit(2);
} if (lseek(fd, 16384, SEEK_SET) == -1) {
printf("lseek error: %s\n", strerror(errno));
exit(3);
} if (write(fd, buf_two, 10) != 10) {
printf("write error: %s\n", strerror(errno));
exit(4);
} exit(0);
}

read函数:

调用read函数从打开文件里读取数据:

#include <unistd.h>

ssize_t read(int fields, void *buf, size_t nbytes);

返回值:若成功则返回读到的字节数。若已到文件结尾则返回0,若出错返回-1。

ssize_t和size_t都是基本系统数据类型,ssize_t为带符号的整数,size_t为不带符号的整数。

有多种情况可使实际读到的字节数少于要求读的字节数:

  • 在读普通文件时。在读到要求的字节数之前已经到达了文件尾端;
  • 从终端设备读时,通常一次最多读一行;
  • 当从网络读时。网络中的缓冲机构可能造成返回值小于所要求读的字节数;
  • 当从管道或FIFO读时。假设管道包括的字节少于所需的数量,那么read将仅仅返回实际可用的字节数。
  • 当从某些面向记录的设备(比如磁带)读时,一次最多返回一个记录;
  • 当某一信号造成中断。而已经读了部分数据量时;

write函数:

调用write函数向打开的文件写数据:

#include <unistd.h>

sszie_t write(int fields。const void *buf, size_t nbytes)

若成功则返回已写的字节数,若出错则返回-1。

其返回值通常与參数nbytes的值同样,否则表示出错。write出错的一个常见原因是:磁盘已写满,或者超过了一个给定进程的文件长度限制。

I/O的效率:

下列程序使用read和write函数复制一个文件:

/*
* Copyright (C) fuchencong@163.com
*/ #include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h> #define BUFSIZE 4096 int
main(void)
{
int n;
char buf[BUFSIZE]; while ( (n = read(STDIN_FILENO, buf, BUFSIZE)) > 0) {
if (write(STDOUT_FILENO, buf, n) != n) {
printf("write error: %s\n", strerror(errno));
exit(1);
}
} if (n < 0) {
printf("read error: %s\n", strerror(errno));
exit(2);
} exit(0);
}

不同的BUFSIZE对程序的执行时间有很大的影响。

系统CPU时间的最小值出如今BUFFSIZE为4096处(一个block的大小),继续增大缓冲区长度对此时间差点儿没有影响。

UNIX环境高级编程(5):文件I/O(1)的更多相关文章

  1. 【UNIX环境高级编程】文件I/O

    [UNIX环境高级编程]文件I/O大多数文件I/O只需要5个函数: open.read.write.lseek以及close 不带缓冲的I/O: 每个read和write都调用内核中的一个系统调用 1 ...

  2. Unix环境高级编程:文件 IO 原子性 与 状态 共享

    参考 UnixUnix环境高级编程 第三章 文件IO 偏移共享 单进程单文件描述符 在只有一个进程时,打开一个文件,对该文件描述符进行写入操作后,后续的写入操作会在原来偏移的基础上进行,这样就可以实现 ...

  3. Unix环境高级编程(二)文件和目录

    本章主要介绍的是文件结构及目录.重点是通过stat函数获取文件的结构信息,然后是文件目录及其遍历.学完本章后,编写了一个输出给的目录下的文件信息的程序. 首先是包含在<sys/stat.h> ...

  4. Unix环境高级编程(一)文件I/O

    Unix系统中大多数文件I/O只需用到五个函数:open.read.write.lseek.close.本章说介绍的I/O是不带缓冲的,即:每个read和write都调用内核中的一个系统调用.不是IS ...

  5. 【UNIX环境高级编程】文件 IO 操作 一 ( open | close | creat | lseek | write | read )

    博客地址 : http://blog.csdn.net/shulianghan/article/details/46980271 一. 文件打开关闭操作相关函数介绍 1. open 函数 (1) op ...

  6. (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  7. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  8. (四) 一起学 Unix 环境高级编程(APUE) 之 系统数据文件和信息

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

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

    一.总结 在写之前,先唠几句,<UNIX环境高级编程>,简称APUE,这本书简直是本神书,像我这种小白,基本上每看完一章都是“哇”这种很吃惊的表情.其实大概三年前,那会大三,我就买了这本书 ...

  10. [置顶] 文件和目录(二)--unix环境高级编程读书笔记

    在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...

随机推荐

  1. C++_class_powerpoint_1.1

    Types and Declarations Boolean Type bool type – boolean , logic type bool literal – true, falseint a ...

  2. Redis(三)、Redis主从复制

    一.主从复制 主从复制:主节点负责写数据,从节点负责读数据,从而实现读写分离,提高redis的高可用性. 让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主节点(mast ...

  3. 第5章分布式系统模式 使用服务器激活对象通过 .NET Remoting 实现 Broker

    正在使用 Microsoft? .NET Framework 构建一个需要使用分布式对象的应用程序.您的要求包括能够按值或按引用来传递对象,无论这些对象驻留在同一台计算机上,还是驻留在同一个局域网 ( ...

  4. java集合的学习笔记

    不知不觉也到了java集合这一章的学习,这因该是挺重要的一个章节,因为所有的程序都离不开数据,而一个良好的数据结构和算法应该是程序的灵魂吧. 今天对自己所初步了解的做一个总结: 数据结构是计算机存储. ...

  5. javascript实现双击网页自动滚动,单击滚动停止

    当网页中有长篇文章时,浏览起来就比较吃劲了,想想一边忙着拖动滚动条,一边忙着浏览,确实挺累人的.为了客人能够轻松的浏览,我们可以使用script代码实现网页的自动滚屏,当双击网页的时候,网页将会自动向 ...

  6. LeetCode 75. Sort Colors (python一次遍历,模拟三路快排)

    LeetCode 75. Sort Colors (python一次遍历,模拟三路快排) 题目分析: 本题需要实现数字只包含0,1,2的排序,并且要求一次遍历. 由于只用把数字隔离开,很容易想到快排的 ...

  7. 把pcl的VTK显示融合到MFC(代码找原作者)

    转自PCL中国,原文链接:http://www.pclcn.org/bbs/forum.php?mod=viewthread&tid=223&extra=page%3D1 本人做了少量 ...

  8. Windows 10 常用软件推荐

    QQ/TIM 大众的通讯工具,十多年之后的今天,依然是国内常驻用户第一的通讯工具 截图.远程桌面.视频会议.文件传送依旧是非常好用 TIM 算是轻聊版的升级版 微信 for Windows 近年新兴的 ...

  9. 杭电 1002 A + B Problem II【大数相加】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1002 解题思路:就是把大的数用数组存放起来,像小学的时候用竖式加法来算两个数相加那样算: 反思:思路很 ...

  10. mindmanager 2018 中文破解版_注册码_免激活

    MindManager 2018是一个可视化的工具,可以用在脑力风暴(brainstorm)和计划(plan)当中.为商务人士提供更有效的.电子化手段捕捉.组织和联系信息(information)和想 ...