目录
一、linux文件i/o概述
1、简介
2、文件和目录
3、系统调用和标准库函数库
二、底层文件访问
1、文件描述符
2、open
3、close
4、write
5、read
6、文件的定位 & lseek
7、fstat,stat,lstat
8、access
9、chown
10、chomd
11、rename
12、dup
13、flock
一、linux文件i/o概述
1、简介
在Linux中,几乎任何事物都可以用一个文件来表示,或者通过特殊的文件提供支持。
文件为操作系统服务和设备提供了一个简单而一致的接口。
大多数Linux文件I/O只需用到5个函数:open、read、write、lseek和close。
使用stat、access等其它I/O函数可以获取或设置文件的状态和权限等信息。
目录文件有一些简单而特殊的编程接口。
2、文件和目录 文件的属性(即 “ 管理信息 ” )被保存在文件的索引节点(inode)中。 索引节点是文件系统中的一个特殊数据块,用以保存文件自身的属性。 文件使用的设备号 索引节点号 文件访问权限和文件类型 文件的硬连接数 所有者用户ID 组ID 设备文件的设备号 文件大小(单位为字节) 包含该文件的磁盘块的大小 该文件所占的磁盘块 文件的最后访问时间 文件的最后修改时间
文件的状态最后改变时间
目录是用于保存其他文件的节点号和名字的文件,是将文件的名称和它的索引节点号结合在一起的一张表。 目录中每一对文件名称和索引节点号称为一个“ 连接 ” 。 目录文件中的每个数据项都是指向某个文件节点的连接。 磁盘中的普通文件和目录文件都有相应的磁盘区域存储数据。这些数据是存储在由索引节点指定的位置上的。
特殊文件(如设备文件)不具有相应的磁盘存储区域。
硬件设备在Unix/Linux中通常被映射为文件,即设备文件。设备文件放在/dev目录下. 硬件设备可分为字符设备和块设备. 终端设备 一种字符设备,有多种类型. 简称tty,tty是 Teletype的缩写. 几个重要的设备文件 控制终端 (/dev/tty) 代表进程的控制终端(键盘和显示屏或键盘和窗口)。 不是物理意义上的终端,/dev/tty映射到当前的设备。 在控制台界面下(即字符界面下),映射到dev/tty1-6上。 在图形界面(XWindows),映射到/dev/pts伪终端上。 使用命令 “ ps -ax ” 可查看进程与哪个控制终端相连。 使用命令 “ tty ” 可以查看它具体对应哪个实际终端设备的设备文件。3、系统调用和标准库函数库
系统调用是UNIX/Linux内核直接提供的编程接口,在内核空间运行。 C语言标准函数库是由一些函数构成的集合,完全运行在用户空间。 直接使用底层系统调用进行I/O操作的效率较低。 执行系统调用时,Linux必须从用户空间切换到内核空间,然后再切换回来。 硬件会限制系统调用一次须读写的数据块大小,如块设备。 应让每次系统调用完成尽可能多的工作。 C语言标准函数库带缓冲机制。 有关系统调用和标准函数库的文档一般分别放在手册页的第2和第3节。
二、底层文件访问
1、文件描述符
一个非负整数。对于内核而言,所有打开的文件都由文件描述符引用。
当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。
从内核源码的角度看,文件描述符其实是当前进程所打开的文件结构数组的下标。
3个特殊的文件描述符(头文件)
0 STDIN_FILENO 标准输入
1 STDOUT_FILENO 标准输出
2 STDERR_FILENO 标准错误输出
2、open
打开或创建一个文件.
pathname 要打开或创建的文件的名称.
flags 由下列一个或多个常数进行或运算构成.
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读、写
O_APPEND 每次写时追加到文件的尾端
O_CREAT 若此文件不存在则创建它,应结合第三个参数mode 使用
O_EXCL 给合O_CREATE,当文件不存在时,才创建文件。
O_TRUNC 如果此文件存在而且可写,则将其长度截短为0。
mode 存取许可权位,一个32位无符号整数,仅当创建新文 件时才使用。最终文件权限受系统变量umask限制, 为 “
mode & ~
umask
”。由以下值按位或得到。
S_IRUSR 文件所有者-读
S_IWUSR 文件所有者-写
S_IXUSR 文件所有者-执行
S_IRGRP 组用户-读
S_IWGRP 组用户-写
S_IXGRP 组用户-执行
S_IROTH 其他用户-读
S_IWOTH 其他用户-写
S_IXOTH 其他用户-执行
返回值
成功时返回一个文件描述符(非负整数)。
失败时返回-1,并设置全局变量errno指明失败原因。
由open返回的文件描述符一定是最小的未用描述符数字。
3、close
关闭已打开的文件。
filedes 待关闭的文件描述符。
返回值 成功时返回0,失败时返回-1。
调用close函数后,终止了文件描述符与文件之间的关联,被关闭的文件描述符重新变为可用。
同时,释放了该进程加在该文件上的所有记录锁。
当一个进程终止时,它所打开的所有文件都将由内核自动关闭。
4、write
向已打开的文件中写入数据
fd 文件描述符
buf 待写入文件的数据的缓冲区,常量指针
count 待写的字节数
返回值 成功为已写的字节数;出错为- 1,错误值记录在errno。
ssize_t在32位机中是int,在64位机中是long int。
5、read
从已打开的文件中读取数据.
fd 文件描述符.
buf 用于放置读取到的数据的缓冲区.
count 要读取的字节数.
返回值 若成功为已读取的字节数(0表示已到达文件尾); 若出错为-1,错误值记录在errno.
6、文件的定位 & lseek
每个已打开的文件都有一个与其相关联的“当前文件位移量”。
通常,读、写操作都从当前文件位移量处开始,并在读、写完成后使位移量增加所读或写的字节数。
当打开一个文件时,如果指定O_APPEND选项,该位移量被设置为文件的长度,否则该位移量被设置为0。
调用lseek函数显式地定位一个已打开文件的“当前文件位移量”。
fd 文件描述符
offset 位移量,相对于whence参数
whence 指定位移量相对于何处开始,可取三个常量值.
返回值 若成功为当前读写位置相对于文件头的位移量;若出错 为-1,错误值记录在errno.
lseek 仅将当前的文件位移量记录在内核变量内,并不引起任何I/O操作。
示例
7、fstat,stat,lstat
读取文件的属性.
file_name 文件名.
filedes 文件描述符。
buf 文件信息结构缓冲区.
返回值 成功为0;若出错为- 1,错误值记录在errno.
当文件是一个符号链接时,lstat返回的是该符号链接本身的信息,而stat返回的是该链接指向的文件的信息。
struct stat
struct stat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};
一般用法
8、access
判断文件是否存在及是否可访问
pathname 文件名.
mode 测试项.
返回值 成功(具有所有测试项权限)为0;若出错为- 1,错误 值记录在errno。
示例
9、chown
改变文件的所有者.
path 文件名。
owner 新文件所有者的用户ID,-1表示保持所有者不变。
group 新文件所属组的ID,-1表示保持所属组不变。
fd 文件描述符。
返回值 成功为0;若出错为- 1,错误值记录在errno.
当文件是一个符号链接时,lchown改变的该符号链接本身的所有者,而chown改变的是该链接指向的文件的所有者。
只有root用户才可以使用这些函数来改变任意文件的所有者和所属组,而普通用户只能改变属于自己的文件的所属组,并且指定的所属组只能是用户自身所在组之一。
示例
10、chomd
改变文件的访问权限.
path 文件名.
mode 文件的权限,由一组八进制数的“或”运算构成,其中的各个位表 示一种权限,称权限位。同open函数的struct stat结构参数的 st_mode.
fd 文件描述符.
返回值 成功为0;若出错为- 1,错误值记录在errno.
权限位
八进制常量值
含义
S_ISUID
04000
设置SUID
S_ISGID
02000
设置SGID
S_ISVTX
01000
设置粘滞位
S_IRUSR
00400
文件所有者可读
S_IWUSR
00200
文件所有者可写
S_IXUSR
00100
文件所有者可执行
S_IRGRP
00040
文件所属组可读
S_IWGRP
00020
文件所属组可写
S_IXGRP
00010
文件所属组可执行
S_IROTH
00004
其他用户可读
S_IWOTH
00002
其他用户可写
S_IXOTH
00001
其他用户可执行
示例
11、rename
重命名文件或目录
oldpath 旧文件名.
newpath 新文件名.
返回值 成功为0;若出错为- 1,错误值记录在errno.
旧文件名、新文件名与返回结果的关系.
oldpath
newpath文件不存在
newpath为普通文件
newpath为目录文件
普通文件
文件被重命名,返回成功
原newpath文件被删除,oldpath文件被重命名为newpath,返回成功
返回错误
目录文件
文件被重命名,返回成功
返回错误
newpath目录文件为空则该目录被删除,oldpath目录被重命名为newpath,返回成功。否则返回错误。
12、dup
复制文件描述符.
oldfd 旧文件描述符.
newfd 新文件描述符.
返回值 成功为新文件描述符;出错为- 1,错误值记录在errno.
注意
复制得到的文件描述符和旧文件描述符将指向同一个打开的文件。
dup函数返回的是最小未用的文件描述符,而dup2函数返回的是预先指定的文件描述符newfd。
如果newfd正在使用,则会先关闭newfd。如果newfd与oldfd一样,则关闭该文件正常返回
13、flock
上锁或解锁一个文件.
fd 文件描述符.
operation 上锁或解锁方式:
LOCK_SH 共享锁
LOCK_EX 独占锁
LOCK_UN 解锁
返回值 成功为0;出错为- 1,错误值记录在errno.
注意
:
一个进程对一个文件只能有一个独占锁,但可以有多个共享锁。
上锁的作用只有在别的进程要对该文件上锁时才能表现出来。
对文件的操纵本身与锁其实没有什么关系!无论文件是否被上锁,用户都可以随便对文件进行正常情况下的任何操纵。
上锁文件的目的是为了同步多个进程之间的操作。
默认情况下,flock是阻塞式的。如果要进行非阻塞式调用, 应将operation参数与常量“LOCK_NB” 进行二进制“或”。
非阻塞式调用flock后,flock会立即返回-1,并且errno的值将为EWOULDBLOCK。
2、open
打开或创建一个文件.
pathname 要打开或创建的文件的名称. flags 由下列一个或多个常数进行或运算构成. O_RDONLY 只读 O_WRONLY 只写 O_RDWR 读、写 O_APPEND 每次写时追加到文件的尾端 O_CREAT 若此文件不存在则创建它,应结合第三个参数mode 使用 O_EXCL 给合O_CREATE,当文件不存在时,才创建文件。 O_TRUNC 如果此文件存在而且可写,则将其长度截短为0。mode 存取许可权位,一个32位无符号整数,仅当创建新文 件时才使用。最终文件权限受系统变量umask限制, 为 “ mode & ~ umask ”。由以下值按位或得到。 S_IRUSR 文件所有者-读 S_IWUSR 文件所有者-写 S_IXUSR 文件所有者-执行 S_IRGRP 组用户-读 S_IWGRP 组用户-写 S_IXGRP 组用户-执行 S_IROTH 其他用户-读 S_IWOTH 其他用户-写 S_IXOTH 其他用户-执行 返回值 成功时返回一个文件描述符(非负整数)。 失败时返回-1,并设置全局变量errno指明失败原因。 由open返回的文件描述符一定是最小的未用描述符数字。
3、close
关闭已打开的文件。
filedes 待关闭的文件描述符。 返回值 成功时返回0,失败时返回-1。 调用close函数后,终止了文件描述符与文件之间的关联,被关闭的文件描述符重新变为可用。 同时,释放了该进程加在该文件上的所有记录锁。 当一个进程终止时,它所打开的所有文件都将由内核自动关闭。4、write
向已打开的文件中写入数据
fd 文件描述符 buf 待写入文件的数据的缓冲区,常量指针 count 待写的字节数 返回值 成功为已写的字节数;出错为- 1,错误值记录在errno。 ssize_t在32位机中是int,在64位机中是long int。
5、read
从已打开的文件中读取数据.
fd 文件描述符.
buf 用于放置读取到的数据的缓冲区.
count 要读取的字节数.
返回值 若成功为已读取的字节数(0表示已到达文件尾); 若出错为-1,错误值记录在errno.
6、文件的定位 & lseek 每个已打开的文件都有一个与其相关联的“当前文件位移量”。 通常,读、写操作都从当前文件位移量处开始,并在读、写完成后使位移量增加所读或写的字节数。 当打开一个文件时,如果指定O_APPEND选项,该位移量被设置为文件的长度,否则该位移量被设置为0。 调用lseek函数显式地定位一个已打开文件的“当前文件位移量”。
fd 文件描述符 offset 位移量,相对于whence参数 whence 指定位移量相对于何处开始,可取三个常量值. 返回值 若成功为当前读写位置相对于文件头的位移量;若出错 为-1,错误值记录在errno. lseek 仅将当前的文件位移量记录在内核变量内,并不引起任何I/O操作。
示例
7、fstat,stat,lstat 读取文件的属性.
file_name 文件名. filedes 文件描述符。 buf 文件信息结构缓冲区. 返回值 成功为0;若出错为- 1,错误值记录在errno. 当文件是一个符号链接时,lstat返回的是该符号链接本身的信息,而stat返回的是该链接指向的文件的信息。 struct stat
struct stat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};
一般用法
8、access 判断文件是否存在及是否可访问
pathname 文件名. mode 测试项. 返回值 成功(具有所有测试项权限)为0;若出错为- 1,错误 值记录在errno。
示例
9、chown 改变文件的所有者.
path 文件名。 owner 新文件所有者的用户ID,-1表示保持所有者不变。 group 新文件所属组的ID,-1表示保持所属组不变。 fd 文件描述符。 返回值 成功为0;若出错为- 1,错误值记录在errno. 当文件是一个符号链接时,lchown改变的该符号链接本身的所有者,而chown改变的是该链接指向的文件的所有者。 只有root用户才可以使用这些函数来改变任意文件的所有者和所属组,而普通用户只能改变属于自己的文件的所属组,并且指定的所属组只能是用户自身所在组之一。
示例
10、chomd 改变文件的访问权限.
path 文件名. mode 文件的权限,由一组八进制数的“或”运算构成,其中的各个位表 示一种权限,称权限位。同open函数的struct stat结构参数的 st_mode. fd 文件描述符. 返回值 成功为0;若出错为- 1,错误值记录在errno.
| 权限位 | 八进制常量值 | 含义 |
| S_ISUID | 04000 | 设置SUID |
| S_ISGID | 02000 | 设置SGID |
| S_ISVTX | 01000 | 设置粘滞位 |
| S_IRUSR | 00400 | 文件所有者可读 |
| S_IWUSR | 00200 | 文件所有者可写 |
| S_IXUSR | 00100 | 文件所有者可执行 |
| S_IRGRP | 00040 | 文件所属组可读 |
| S_IWGRP | 00020 | 文件所属组可写 |
| S_IXGRP | 00010 | 文件所属组可执行 |
| S_IROTH | 00004 | 其他用户可读 |
| S_IWOTH | 00002 | 其他用户可写 |
| S_IXOTH | 00001 | 其他用户可执行 |
示例
11、rename 重命名文件或目录
oldpath 旧文件名. newpath 新文件名. 返回值 成功为0;若出错为- 1,错误值记录在errno. 旧文件名、新文件名与返回结果的关系.| oldpath | newpath文件不存在 | newpath为普通文件 | newpath为目录文件 |
| 普通文件 | 文件被重命名,返回成功 | 原newpath文件被删除,oldpath文件被重命名为newpath,返回成功 | 返回错误 |
| 目录文件 | 文件被重命名,返回成功 | 返回错误 | newpath目录文件为空则该目录被删除,oldpath目录被重命名为newpath,返回成功。否则返回错误。 |
12、dup 复制文件描述符.
oldfd 旧文件描述符. newfd 新文件描述符. 返回值 成功为新文件描述符;出错为- 1,错误值记录在errno. 注意 复制得到的文件描述符和旧文件描述符将指向同一个打开的文件。 dup函数返回的是最小未用的文件描述符,而dup2函数返回的是预先指定的文件描述符newfd。 如果newfd正在使用,则会先关闭newfd。如果newfd与oldfd一样,则关闭该文件正常返回
13、flock 上锁或解锁一个文件.
fd 文件描述符. operation 上锁或解锁方式: LOCK_SH 共享锁 LOCK_EX 独占锁 LOCK_UN 解锁 返回值 成功为0;出错为- 1,错误值记录在errno. 注意 : 一个进程对一个文件只能有一个独占锁,但可以有多个共享锁。 上锁的作用只有在别的进程要对该文件上锁时才能表现出来。 对文件的操纵本身与锁其实没有什么关系!无论文件是否被上锁,用户都可以随便对文件进行正常情况下的任何操纵。 上锁文件的目的是为了同步多个进程之间的操作。 默认情况下,flock是阻塞式的。如果要进行非阻塞式调用, 应将operation参数与常量“LOCK_NB” 进行二进制“或”。 非阻塞式调用flock后,flock会立即返回-1,并且errno的值将为EWOULDBLOCK。



