APUE读书笔记-3

Unix系统基础

Posted by Nathaniel on 2017-08-18

APUE读书笔记-3

第三章

本章主要讲了文件的I/O操作

Unix下主要有五个系统API接口用于操控文件,分别是openreadwritelseekclose,顾名思义,分别是用于打开、读取、写入、内部定位、关闭文件。

文件描述符

File Descriptors通常为一个非负整数,可以用于表示任何类型的文件(文件夹也是一种特殊的文件),操作系统的文件操作API通常以文件描述符作为参数。

参数选项

头文件<fcntl.h>中定义了一些常量,用作下面这些函数的参数,第一类参数选项为读写方式的选择,这些选项是互斥的

名称 意义
O_RDONLY 只读模式
O_WRONLY 只写模式
O_RDWR 读写模式
O_EXEC 仅执行模式
O_SEARCH 仅搜索模式

第二类选项则为随意选择,由于数量众多,再次仅选一部分介绍

名称 意义
O_APPEND 在文件末尾追加
O_CLOEXEC 设定“在多线程调用时不重复打开该文件”的FLAG
O_CREAT 如果文件不存在则创建文件
O_DIRECTORY 指定目标为目录,非目录则报错
O_EXCL 创建文件时如果文件已经存在则报错
O_NOFOLLOW 如果指向符号链接则报错

打开文件

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 */ );

Open函数即为最基本的打开文件函数,在早期的Unix版本中仅仅用于打开文件,后来随着Unix版本演进,拥有了许多其他的功能。

这里简单解释一下上述两个函数的区别:

open函数为基础的打开文件函数,可用于任何类型的文件,功能也正如其名,打开文件,然后你就可以对文件进行各种操作了。

Openat函数解决了open函数所不能解决的一个问题,那就是在多线程的情况下,在对一个文件进行open的同时,该文件所在的目录可能被其他的线程或进程修改,而如果使用openat函数的话,该目录会被锁定,这样系统API调用者就不用每次都检测该目录是否存在了。

创建文件

creat函数

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

早起的Unix系统下的open函数仅仅具备打开文件的功能,因此,一个单独的creat系统调用就显得十分必要,因为有了这个函数才能创建新的文件,而后来随着Unix系统的发展,creat的功能和指定了O_WRONLY|O_CREAT|O_TRUNCopen函数有这相同的功能。

关闭文件

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

关闭文件的实质就是释放文件上所加的锁,释放了锁之后,其他的程序便可以对该文件进行相应的读写操作了。

文件内部定位

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

每个文件都有一个当前文件偏移量,它通常来说是一个非负整数,用于表明当前j进行操作文件中的具体位置。使用 lseek可以把处理位置移动到指定的偏移量处。在调用lseek函数时可以使用一些FLAG,SEEK_SET表示移动到文件头+offset值的位置, SEEK_CUR表示移动到当前偏移量+offset值的位置, SEEK_END表示移动到文件末尾+offset值的位置。对于后两个FLAG,offset的值可以为负。

另外,lseek函数仅仅可以被用在普通文件上,对于管道、FIFO(命名的管道)、socket,则不能使用lseek