UNIX高级环境编程(1)File I/O
引言:
Unix系统中主要的文件操作包括:
- open
- read
- write
- lseek
- close
unbuffered IO和standard I/O相对应,后面的章节我们会讨论这两者的区别。
在讨论open函数的时候,会引入原子操作,多进程通信(共享文件描述符)和内核相关的数据结构。
一,文件描述符
对应内核来说,每一个打开的文件都对应一个非负整数。
有三个特殊的文件描述符:
- 0表示标准输入
- 1表示标准输出
- 2表示标准错误输出
对于较新的内核来说(Linux3.2.0,Solaris10等),文件描述符的数量并没有明确的限制,受限于内存的大小。
二,常用的几个文件操作函数
常用的文件操作函数包括:open,read,write,lseek,close
1 open和openat函数
函数声明:
#include <fcntl.h>
int open (const char *path, int oflag, … /* mode_t mode */);
int openat (int fd, const char *path, int oflag, … /* mode_t mode */);
返回值:
OK:文件描述符(非负整数)
Error:-1
注:参数列表中,“...”表示不同的系统和标准中,该处的参数可能不相同。
参数说明:
path:文件名
oflag:打开创建文件的属性。
下面有五个必选的oflag参数值,这五个值有切只能选一个。另外还有若干个可选参数值,可以自行百度。

细节说明:
由open和openat返回的文件描述符保证为未使用的最小的文件描述。有的应用利用这一特性,先关闭标准输入描述符0,就可以在标准输入描述0上打开文件。
参数fd可以区分open和openat函数。其取值有三种可能:
- path表示一个绝对路径,则fd参数无用,openat的功能和open相同;
- path表示一个相对路径,则fd是一个文件描述符,指定了path在文件系统中的起始位置,fd为打开path父目录时获取的文件描述符;
- path表示一个相对路径,而fd的值为AT_FDCWD,这时,path的父目录为当前工作目录,openat和open的功能相同。
openat函数解决了两个问题:
- 在多线程条件下,默认各个线程的工作目录时相同的(当前工作目录),使用这个函数可以使得各个线程的指定不同的工作目录;
- 提供了一种方法解决TOCTTOU(time-of-check-to-time-of-use) error。
这里介绍一下TOCTTOU错误。该类错误指的是,程序是非常脆弱的(vulnerable)如果该程序调用了两个文件相关的函数,第二个函数依赖于第一个函数的结果。因为两个函数是非原子操作,被操作的文件可能被两个函数轮流操作(线程切换),导致第一个函数的结果出错,从而程序出错。
2 creat函数
函数声明:
#include <fcntl.h> int creat(const char* path, mode_t mode);
返回值:
- OK:文件描述符(只写)
- Error:-1
creat函数相当于下面这样调用open函数
open (path, O_WEONLY | O_CREAT | O_TRUNC, mode);
creat有一点不方便,因为它打开的文件描述符是只读的,如果希望写入之后读回,需要依次调用creat、close和open,才能实现。
因此,在这种场景下,一个更好的打开文件的方法是像下面这样调用open函数:
open (path, O_RDWR | O_CREAT | O_TRUNC, mode);
3 close函数
函数声明:
#include <unistd.h> int close(int fd);
返回值:
- 0 :OK
- -1:Error
关闭一个文件会释放所有当前进程加在该文件上的记录锁。
4 lseek函数
每一个打开的文件都有一个”当前文件偏移量(current file offset)“,该偏移量是一个非负整数,记录了从文件开始到当前位置的字节数。
函数声明:
#include <unistd.h> off_t lseek(int fd, off_t offset, int whence);
参数说明:
offset的作用取决于参数whence的值:
- 如果whence的值是SEEK_SET,文件的偏移量设置为offset个字节;
- 如果whence的值是SEEK_CUR,文件的偏移量设置为当前偏移量加上参数offset的值;
- 如果whence的值是SEEK_END,文件的偏移量设置为文件长度加上参数offset的值,offset可以是正值或负值。
细节说明:
获取当前文件偏移量的方法:
off_t currpos; currpos = lseek(fd, , SEEK_CUR);
lseek只记录当前文件在内核中的偏移量,并不会引起任何的IO操作。返回的offset将会在后面的read或write函数中使用。
偏移量可以比当前文件的长度大,这时,再调用write函数时,将扩展该文件的长度。这样的操作相当于在文件中建了一个洞,该洞范围内读时返回0。
使用od命令可以看到文件中的hole

4 read函数
函数声明:
#include <unistd.h> ssize_t read(int fd, void *buf, size_t nbytes);
返回值:
- 正整数:读入的字节数
- 0:文件结尾
- -1: error
细节说明:
在一些情况下,函数返回的字节数比指定的读入字节数要小,多数是因为读到了文件末尾,或者指定的读取位置中包含的字节数小于指定的读入字节数,这时,read返回的为可读到的字节数。
5 write函数
函数声明:
#include <unistd.h> ssize_t write (int fd, const void *buf, size_t nbytes);
返回值:
- 非负整数:写入的字节数,OK
- -1: Error
返回值总是等于参数nbytes的值,否则就会报错。
对于常规的文件来说,写操作总是从当前文件偏移量开始。
三、小结
简单地介绍了一下常用的文件IO操作,并介绍了一些使用上的细节,比较常规。
下一篇讲介绍更多文件IO的特性,包括:dup,fcntl,sync,fsync和ioctl函数。。
好久没写博客了,又第一次用mac下的一个博客软件写,不太熟悉,所以写的比较简单,以后会写的更努力。
参考资料:
《Advanced Programming in the UNIX Envinronment 3rd》
UNIX高级环境编程(1)File I/O的更多相关文章
- UNIX高级环境编程1
UNIX高级环境编程1 故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表 ...
- UNIX高级环境编程(14)文件IO - O_DIRECT和O_SYNC详解 < 海棠花溪 >
春天来了,除了工作学习,大家也要注意锻炼身体,多出去运动运动. 上周末在元大都遗址公园海棠花溪拍的海棠花. 进入正题. O_DIRECT和O_SYNC是系统调用open的flag参数.通过指定o ...
- Unix高级环境编程
[07] Unix进程环境==================================1. 进程终止 atexit()函数注册终止处理程序. exit()或return语句: ...
- UNIX高级环境编程(2)FIle I/O - 原子操作、共享文件描述符和I/O控制函数
引言: 本篇通过对open函数的讨论,引入原子操作,多进程通信(共享文件描述符)和内核相关的数据结构. 还会讨论集中常见的文件IO控制函数,包括: dup和dup2 sync,fsync和fdatas ...
- UNIX高级环境编程(10)进程控制(Process Control)- 竞态条件,exec函数,解释器文件和system函数
本篇主要介绍一下几个内容: 竞态条件(race condition) exec系函数 解释器文件 1 竞态条件(Race Condition) 竞态条件:当多个进程共同操作一个数据,并且结果依赖 ...
- UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid
本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID 1 进程标识符(Process Identifie ...
- UNIX高级环境编程(4)Files And Directories - umask、chmod、文件系统组织结构和链接
本篇主要介绍文件和文件系统中常用的一些函数,文件系统的组织结构和硬链接.符号链接. 通过对这些知识的了解,可以对Linux文件系统有更为全面的了解. 1 umask函数 之前我们已经了解了每个文件 ...
- UNIX高级环境编程(3)Files And Directories - stat函数,文件类型,和各种ID
在前面的两篇,我们了解了IO操作的一些基本操作函数,包括open.read和write. 在本篇我们来学习一下文件系统的其他特性和一个文件的属性,涉及的函数功能包括: 查看文件的所有属性: 改变文件所 ...
- UNIX高级环境编程(16)文件系统 < 雨后 >
来点绿色放松一下眼睛吧 :) 文件系统是对文件和目录的组织集合. 一 设备文件 设备文件和系统的某个设备相对应. 设备驱动程序 处理设备的所有IO请求. 提供了一致的API接口,对应于系统调用的ope ...
随机推荐
- C++中虚函数的动态绑定和多态性
目录 静态类型 vs 动态类型.静态绑定 vs 动态绑定 虚函数动态绑定实现机制.虚析构函数 多态性 一.静态 vs 动态 静态类型 VS 动态类型.静态类型指的是对象声明的类型,在编译器确定的.动态 ...
- Zookeeper初见
这是Zookeeper学习总结 的系列文章. ZK简介 ZK部署及运行 ZK的常用API 创建会话 创建节点 删除节点 读取数据节点 更新数据 检测节点是否存在 ZK的开源封装
- (转) Java我的高效编程之环境搭建
前言:刚毕业, 工作之余写博客有利于提高技术,更是能帮助人,接下来会认认真真写好每一篇博客.希望大家多多支持.废话不多说,马上开始.这是一篇环境搭建的博客. jdk+eclipse+svn+maven ...
- 下拉加载dropload.js
使用下拉加载 使用需要引用的css <link rel="stylesheet" href="../dist/dropload.css"> 使用需要 ...
- Beta阶段——Scrum 冲刺博客第一天
一.当天站立式会议照片一张 二.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中 昨天已完成的工作 今日是Beta冲刺第一天,昨日没有完成的工作 今天计划完成的工作 实现对i ...
- H5开发中遇到的问题及解决办法
记不得什么时候进行H5开发的学习了,只知道是从2016年8月1日开始修复Bug,计划每天把学到的东西以及遇到问题时候的解决方案都记录下来,希望自己能够坚持下去,每天积累一点,希望有所进步吧. 1.Th ...
- Tomcat 配置上传文件到项目外的路径
使用 Tomcat 作为服务器的时候,将上传文件保存在项目路径下,每次重启服务或者打成 war 包的时候很容易丢失上传的文件,于是我们配置 Tomcat 把文件保存到项目外的其他磁盘路径: 1. 打开 ...
- 常用算法3 - 字符串查找/模式匹配算法(BF & KMP算法)
相信我们都有在linux下查找文本内容的经历,比如当我们使用vim查找文本文件中的某个字或者某段话时,Linux很快做出反应并给出相应结果,特别方便快捷! 那么,我们有木有想过linux是如何在浩如烟 ...
- [转] Linux Daemon Writing HOWTO
Linux Daemon Writing HOWTO Devin Watson v1.0, May 2004 This document shows how to write a daemon in ...
- python分布式爬虫打造搜索引擎--------scrapy实现
最近在网上学习一门关于scrapy爬虫的课程,觉得还不错,以下是目录还在更新中,我觉得有必要好好的做下笔记,研究研究. 第1章 课程介绍 1-1 python分布式爬虫打造搜索引擎简介 07:23 第 ...