本章开始讨论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. 两步完美解决 androud 模拟器太慢的问题

    androud 开发环境默认的 avd 管理器下载并启动的模拟器,运行速度非常慢,有时不可忍受,用下面两步可以解决这个问题: 下载 genymotion-2.3.1 (注意,最好是这个版本,试过2.4 ...

  2. Webpack & The Hot Module Replacement热模块替换原理解析

    Webpack & The Hot Module Replacement热模块替换原理解析 The Hot Module Replacement(HMR)俗称热模块替换.主要用来当代码产生变化 ...

  3. Unicode 和 ANSI

    Project Properties -> General-> Character set,里面显示了是不是unicode. Unicode处理String的方式不一样,一定要注意!!   ...

  4. java中数组有没有length()方法?string没有lenght()方法?

    java中数组有没有length()方法,求数组的长度可以使用数组的length属性. int[] arr={1,2,3,4,5}; int length=arr.length;//求数组的长度 -- ...

  5. AJAX中的同步加载与异步加载

    AJAX是四个单词的简写,其中Asynchronous即异步的意思,异步的链接可以同时发起多个,并且不会阻止JS代码执行.与之对应的概念是同步,同步的链接在同一时刻只会有一个,并且会阻止后续JS代码的 ...

  6. Python的程序结构[2] -> 类/Class[3] -> 内建类与内建函数

    内建类与内建函数的区分 / Distinction of Built-in Type and Function 对于 Python,有许多可以不需要定义或引用就可以使用的函数(类)(参考内建模块),诸 ...

  7. 使用参数化SQL

    Java.C#等语言提供了参数化SQL机制,使用参数化SQL开发人员为在运行时才能确定的参数值设置占位符,在执行的时候再指定这些占位符所代表的值.示例代码如下: string user=txtUser ...

  8. [BZOJ 1567] Blue Mary的战役地图

    Link: BZOJ 1567 传送门 Solution: 矩阵Hash/二维$Hash$模板题 涉及到需要快速查询.匹配的题目,考虑直接上$Hash$ 矩阵$Hash$其实就是每行先各$Hash$一 ...

  9. 玩转Nuget服务器搭建(二)

    之所以分开来写这几部分,是因为今天搭建的过程中,碰到了几个问题,特别提一下,让大家省下这部分时间(毕竟人生苦短嘛,你如果就是闲的蛋疼,请给我你的GUID,我送你几瓶风油精). NugetServer ...

  10. 在Ubuntu Server 中安装图形用户界面

    使用ubuntu server安装lamp主机非常的方便,只要在安装系统的步骤中选择就是了 .但是很多时候我需要在图形界面下管理主机更加方便.今天的教程就是教大家安装图形界面. 首先你需要确定你的源文 ...