本章开始讨论UNIX系统,先说明可用的文件I/O函数---打开文件、读写文件等

UNIX系统中的大多数文件I/O只需用到5个函数:open、read、write、lseek以及close

open函数  返回一个最小的未用描述符

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

其中path参数是打开或创建文件的名字,flags参数由下列一个或多个常量进行“或”运算得到:

O_RDONLY  只读打开

O_WRONLY  只写打开

O_RDWR     读、写打开

O_EXEC  只执行打开

O_SEARCH  只搜索打开(应用于目录)

这5个常量中必须指定一个,下列常量则是可选的:

O_APPEND  每次写时都追加到文件的尾端

O_CLOEXEC  把FD_CLOEXEC常量设置为文件描述符标志

O_CREAT  若此文件不存在则创建它。使用此选项时,open函数必须同时说明第三个参数mode

O_DIRECTORY  如果path引用的不是目录,则出错

O_EXEL  如果同时指定了O_CREAT,而文件已经存在,则出错

O_NOCTTY  如果path引用的是终端设备,则不讲该设备分配作为此进程的控制终端

O_NOFOLLOW  如果path应用的是一个符号链接,则出错

O_NONBLOCK  如果path引用的是一个FIFO、一个块特殊文件或一个字符特殊文件,则设置此文件本次打开操作跟后续的I/O操作为非阻塞方式

O_SYNC  使每次write等待物理I/O操作完成

O_TRUNC  如果此文件存在,而且为只写或读写成功打开,则将其长度截断为0

O_TTY_INIT  如果打开一个还未打开的终端设备,设置非标准termios参数值

creat函数

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

该函数相当于open(path,O_WRONLY|O_CREATE|O_TRUNC,mode);

在第四章我们会详细说明文件访问权限,并说明如何指定mode

close函数

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

close函数用于关闭一个打开文件

lseek函数

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

对参数offset的解释与参数whence的值有关。

若whence是SEEK_SET,则将该文件的偏移量设置为距距文件开始处offset个字节

若whence是SEEK_CUR,则将该文件的偏移量设置为其当前值加offset,offset可为正或负

若whence是SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负

若lseek成功执行,则返回新的文件偏移量,为此可以用下列方式确定打开文件的当前偏移量

off_t currpos;
currpos=lseek(fd,,SEEK_CUR);

如果文件描述符指向的是一个管道、FIFO、或者网络套接字,则lseek返回-1,并将errno设置为ESPIPE。

read函数

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

如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。

读操作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。

write函数

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

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

对于普通文件,写操作从文件的当前偏移量处开始,如果打开该文件时,指定了O_APPEND选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。

在一次成功写之后,该文件偏移量增加实际写得字节数。

文件共享

进程为打开文件维护3张表

如果两个独立进程各自打开了同一个文件,则有下图所示的关系

函数dup和dup2

#include <unistd.h>
int dup(int fd);
int dup2(int fd,int fd2);

两个函数都可用来复制一个现有的文件描述符

dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。

dup2可以用fd2参数指定新描述符的值。如果fd2已经打开,则先将其关闭。若fd等于fd2,则返回fd2,而不关闭它。

这些函数返回的新文件描述符与参数fd共享一个文件表项,如下图所示:

digit1>&digit2表示要将描述符digit1重定向至描述符digit2的同一文件

理解./a.out > outfile 2>&1与./a.out 2>&1 >outfile的区别

fcnt函数

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

fcntl函数可以改变已经打开文件的属性,它有以下5种功能

1 复制一个已有的描述符(cmd=F_DUPFD或F_DUPFD_CLOEXEC)

2 获取/设置文件描述符标志(cmd=F_GETFD或F_SETFD)

3 获取/设置文件状态标志(cmd=F_GETFL或F_SETFL)

4 获取/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN)

5 获取/设置记录锁(cmd=F_GETLK、F_SETLK或F_SETLKW)

我们先说明cmd中的前面8种

F_DUPFD  复制文件描述符fd,返回新的文件描述符。它是尚未打开的各描述符中大于或等于第三个参数值中各值的最小值

F_DUPFD_CLOEXEC  复制文件描述符,设置与新描述符关联的FD_CLOEXEC文件描述符标志的值,返回新的文件描述符

F_GETFD  对应于fd的文件描述符标志做为函数值返回,当前只定义了一个文件描述符标志FD_CLOEXEC

F_SETFD  对于fd设置文件描述符标志。

F_GETFL  对应于fd的文件状态标志作为函数值返回,下图列出fcntl的文件状态标志

其中,3种访问方式标志(O_RDONLY,O_WRONLY,O_RDWR)并不各占一位,因此首先必须用屏蔽字O_ACCMODE取得访问方式位,然后将结果与这3个值得每一个比较。

F_SETFL  将文件状态标志设置为第三个参数的值。可以更改的几个标志是O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC、O_FSYNC和O_ANSYNC

F_GETTOWN  获取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。

F_SETOWN  设置接收SIGIO和SIGURG信号的进程ID或进程组ID

下面程序将打印文件状态标志说明

#include "apue.h"
#include <fcntl.h> int
main(int argc, char *argv[])
{
int val; if (argc != )
err_quit("usage: a.out <descriptor#>"); if ((val = fcntl(atoi(argv[]), F_GETFL, )) < )
err_sys("fcntl error for fd %d", atoi(argv[])); switch (val & O_ACCMODE) {
case O_RDONLY:
printf("read only");
break; case O_WRONLY:
printf("write only");
break; case O_RDWR:
printf("read write");
break; default:
err_dump("unknown access mode");
} if (val & O_APPEND)
printf(", append");
if (val & O_NONBLOCK)
printf(", nonblocking");
if (val & O_SYNC)
printf(", synchronous writes"); #if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC) && (O_FSYNC != O_SYNC)
if (val & O_FSYNC)
printf(", synchronous writes");
#endif putchar('\n');
exit();
}

下面函数用于设置文件状态标志

#include "apue.h"
#include <fcntl.h> void
set_fl(int fd, int flags) /* flags are file status flags to turn on */
{
int val; if ((val = fcntl(fd, F_GETFL, )) < )
err_sys("fcntl F_GETFL error"); val |= flags; /* turn on flags */ if (fcntl(fd, F_SETFL, val) < )
err_sys("fcntl F_SETFL error");
}

apue学习笔记(第三章 文件I/O)的更多相关文章

  1. The Road to learn React书籍学习笔记(第三章)

    The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...

  2. 《DOM Scripting》学习笔记-——第三章 DOM

    <Dom Scripting>学习笔记 第三章 DOM 本章内容: 1.节点的概念. 2.四个DOM方法:getElementById, getElementsByTagName, get ...

  3. [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设

    [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设 敲黑板!! <q>元素添加短引用,<blockquote>添加长引用 在段落里添加引用就使用< ...

  4. JVM学习笔记-第三章-垃圾收集器与内存分配策略

    JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...

  5. [HeadFirst-JSPServlet学习笔记][第三章:实战MVC]

    第三章 实战MVC J2EE如何集成一切 Java2企业版(Java 2 Enterprise Editon,J2EE)是一种超级规范.规定了servlets2.4,JSP2.0,EJB2.1(Ent ...

  6. python学习笔记——第三章 串

    第三章 字符串学习 1.字符串不灵活, 它不能被分割符值 >>> format = "hello, %s. %s enough for ya?" >> ...

  7. c#高级编程第七版 学习笔记 第三章 对象和类型

    第三章 对象和类型 本章的内容: 类和结构的区别 类成员 按值和按引用传送参数 方法重载 构造函数和静态构造函数 只读字段 部分类 静态类 Object类,其他类型都从该类派生而来 3.1 类和结构 ...

  8. JavaScript高级编程学习笔记(第三章之一)

    继续记笔记,JavaScript越来越有意思了. 继续... 第三章:JavaScript基础 ECMAScript语法在很大程度上借鉴了C和其它类似于C的语言,比如Java和Perl. 大小写敏感: ...

  9. python学习笔记(三)— 文件操作

    对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 现有以下文件a.txt: 登鹳雀楼 唐代:王之涣 白日依山尽,黄河入海流. 一.文件基 ...

  10. o'Reill的SVG精髓(第二版)学习笔记——第三章

    第三章:坐标系统 3.1视口 文档打算使用的画布区域称作视口.我们可以在<svg>元素上使用width和height属性确定视口的大小.属性的值可以是一个数字,该数字会被当作用户坐标下的像 ...

随机推荐

  1. 手一抖误删了根目录 /usr 之后的挽救过程

    一切悲剧来源于写的Shell没有好好检查,执行后把开发机的根目录 /usr 目录给删除了,而且是root执行,众所周知,/usr目录里有大量的应用层程序,删除之后导致大量命令无法使用,如 ssh / ...

  2. gdb 调试打印

    gdb查看指定地址的内存地址的值:examine 简写 x-----使用gdb> help x 来查看使用方式 x/ (n,f,u为可选参数) n: 需要显示的内存单元个数,也就是从当前地址向后 ...

  3. Linux Suspend过程【转】

    转自:http://blog.csdn.net/chen198746/article/details/15809363 目录(?)[-] Linux Suspend简介 Suspend流程 enter ...

  4. protobuf 中的嵌套消息的使用 主要对set_allocated_和mutable_的使用

    protobuf的简单的使用,不过还留下了一个问题,那就是之前主要介绍的都是对简单数据的赋值,简单数据直接采用set_xx()即可,但是如果不是简单变量而是自定义的复合类型变量,就没有简单的set函数 ...

  5. 洛谷——P2118 比例简化

    P2118 比例简化 题目描述 在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果.例如,对某一观点表示支持的有1498 人,反对的有 902人,那么赞同与反对的比例可以简单的记为149 ...

  6. POJ 3470 Walls(线段树+扫描线)

    [题目链接] http://poj.org/problem?id=3470 [题目大意] 给出几面墙,均垂直于x轴或者y轴,给出一些鸟的位置(二维坐标点), 鸟只会垂直x轴或者y轴飞行,并且会撞上最近 ...

  7. RMQ小结

    RMQ——区间最小查询,实际情况往往不是查询最小值,而是查询区间特定信息.一般要求在logn的级别实现查询or修改. RMQ三种实现 1.BIT BIT给我的感觉就是神迹一般数学的巧合,关于它的原理就 ...

  8. 初识交替最小二乘ALS

    ALS是alternating least squares的缩写 , 意为交替最小二乘法:而ALS-WR是alternating-least-squares with weighted-λ -regu ...

  9. 【转】Kriging插值法

    einyboy 原文LINK Kriging插值法 克里金法是通过一组具有 z 值的分散点生成估计表面的高级地统计过程.与插值工具集中的其他插值方法不同,选择用于生成输出表面的最佳估算方法之前,有效使 ...

  10. TDD的iOS开发初步以及Kiwi使用入门

    测试驱动开发(Test Driven Development,以下简称TDD)是保证代码质量的不二法则,也是先进程序开发的共识.Apple一直致力于在iOS开发中集成更加方便和可用的测试,在Xcode ...