文件基本概念
文件
可被读写的对象
具备一定权属性,包括访问权限、类型等
文件系统
文件及其属性的集合,提供了命名及管理机制
文件结构
字节流,没有特定内部结构
文件类型
普通文件
目录
设备文件
字符文件/块文件
FIFO文件(如管道文件)
Socket文件
符号链接
硬连接
不同的文件名对应同一个inode
不能跨越文件系统
相应系统调用
link()
[root@localhost link]# ls -l
total 1
-rw-r--r-- 1 root root 667 Oct 15 13:39 a
[root@localhost link]# ln a b
[root@localhost link]# ls -l
total 2
-rw-r--r-- 2 root root 667 Oct 15 13:39 a
-rw-r--r-- 2 root root 667 Oct 15 13:39 b
[root@localhost link]# rm a
rm: remove `a‘? y
[[email protected] link]# ls -l
total 1
-rw-r--r-- 1 root root 667 Oct 15 13:39 b
符号链接
存储被链接文件的文件名(而不是inode)实现链接
可跨越文件系统
相应系统调用
symlink()
[root@localhost symlink]# ls -l
total 1
-rw-r--r-- 1 root root 667 Oct 15 13:39 a
[root@localhost symlink]# ln -s a b
[root@localhost symlink]# ls -l
total 1
-rw-r--r-- 1 root root 667 Oct 15 13:39 a
lrwxrwxrwx 1 root root 1 Oct 15 14:20 b -> a
[root@localhost yy]# rm a
rm: remove `a‘? y
[[email protected] symlink]# ls -l
total 0
lrwxrwxrwx 1 root root 1 Oct 15 14:20 b -> a
[[email protected] symlink]# cat b
cat: b: No such file or directory
文件系统类型
Windows文件系统
FAT16,FAT32,NTFS
传统UNIX:UFS (Unix File System)
BSD文件系统:FFS(Fast File System)
Proc文件系统:只存在于内存中
Linux文件系统
ext2(在Linux 2.0.x中首次使用)
reiserfs(在Linux 2.2.x中首次使用)
ext3(在Linux 2.4.x中首次使用)
xfs(源于SGI )
Jfs(源于IBM )
嵌入式小型文件系统
CRAMFS
JFFS2
虚拟化
只存在于内存中
组成
超级块
存储已安装文件系统的信息
通常对应磁盘文件系统的文件系统控制块
文件对象
inode对象
存储单个文件的信息
通常对应磁盘文件系统的文件控制块
dentry对象
描述文件名及相关联的inode信息
虚拟文件的目录项
dentry定义位置:include/linux/dcache.h
描述目录与文件的关系树
目录高速缓存(directory cache)
保存每一个曾被读取的目录/文件的dentry项
加快文件查找效率
虚拟文件系统各对象之间关系
inode对象与文件:一对一
dentry对象与inode对象:多对一(硬连接)
文件对象与dentry对象:多对一
EXT2文件系统
第一个磁盘块用于引导,其余部分被分成若干组
各组大小相同且顺序存放
可通过组序号确定组在磁盘上的位置
组的构成
文件系统超级块
所有组描述符
数据块位图
inode位图
inode表
数据块
EXT2文件系统体系结构
每组都有一份超级块和所有组描述信息的拷贝
正常情况下内核只使用第0组的信息
当组0的拷贝遭到损坏时便可根据其它组的拷贝恢复
数据块位图
大小为一个块
每一位顺序对应组中的一个块
0表示可用
1表示已用
inode表
存放文件及目录的inode数据
inode位图
表示对应的inode表空间是否已被占用
EXT3文件
日志文件系统(journaling file system)
利用数据库的日志技术(log, checkpoint)
3种日志方式
journal, ordered, writeback
日志记录在/.journal中(隐藏文件)
Kjournald—5s
proc文件系统
虚拟文件系统,只存在于内存中
可查询、设置系统的运行情况及各种系统参数
系统中的很多应用都依赖于proc文件系统
如命令lsmod等同于 cat /proc/modules
文件大小为0
很多文件名反映了内核的相应参数
可通过该文件名修改参数值
如#echo 2048 > /proc/sys/shmmni,修改共享内存段的限制
/proc下的“数字目录”指代相应pid的进程
如目录“1”下的内容就是1号进程的各种信息
系统调用与库函数的基本概念
均以C函数形式出现
系统调用
Linux内核的对外接口
用户程序与内核之间的唯一接口
提供最小接口
程序员手册第二节
库函数
依赖于系统调用
提供较复杂功能
例:标准I/O库
程序员手册第三节
无缓存I/O与有缓存I/O
无缓存I/O
读/写 ->设备
文件描述符
ANSI C不支持、POSIX支持
设备文件访问时使用
有缓存I/O
标准 I/O库提供
处理很多细节
缓存分配
以优化长度执行I/O
流 -> FILE指针
普通文件
基本I/O系统调用
文件描述符
基本I/O
open() / creat(), close(), read(), write(), lseek()
dup()/dup2()
fcntl()
ioctl()
文件描述符
非负整数
定义形式
int fd;
标准文件描述符定义(
STDIN_FILENO (0)
STDOUT_FILENO (1)
STDERR_FILENO (2)
文件操作的一般过程
打开-读/写-[定位]-关闭
/* a rudimentary example program */
#include <fcntl.h>
main()
{
int fd, nread;
char buf[1024];
/*open file “data” for reading */
fd = open(“data”, O_RDONLY);
/* read in the data */
nread = read(fd, buf, 1024);
/* close the file */
close(fd);
}
出错处理
UNIX风格
返回值
“errno” 变量(/usr/include/errno.h)
extern int errno;
strerror
#include <string.h>
char *strerror(int errnum);
返回出错的字符串描述
perror()
#include <stdio.h>
void perror(const char *msg);
打印错误原因字符串
open()/creat()系统调用
功能
打开或创建一个文件或设备
头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
返回值
成功时返回新文件描述符
否则返回-1
功能
文件访问模式
取值说明(/usr/include/fcntl.h)
O_RDONLY:只读形式打开
O_WRONLY:只读形式打开
O_RDWR:读写形式打开
O_APPEND:追加模式打开
O_TRUNC :若文件存在且为只读或只写成功打开,则将长度截为0
O_CREAT:若文件不存在则创建之
使用此选项时,需同时说明参数mode,说明文件的存取许可权位
O_EXCL:若同时指定O_CREAT,而文件已经存在,则出错
该参数可测试文件是否存在,如果不存在则创建此文件
creat()函数说明
等价于已参数O_CREAT|O_WRONLY|O_TRUNC执行open()
close()系统调用
功能
关闭文件描述符
头文件
#include <unistd.h>
函数原型
int close(int fd);
成功:返回0
失败:返回-1
read()/write()系统调用
read()
功能
从文件描述符读取数据
头文件
#include <unistd.h>
函数原型
ssize_t read(int fd, void *buf, size_t count);
返回值: 读到的字节数,若已到文件尾为0,若出错为-1
write()
功能
将数据写入文件描述符
头文件
#include <unistd.h>
函数原型
ssize_t write(int fd, const void *buf, size_t count);
返回值: 若成功为已写的字节数,若出错为-1
lseek()系统调用
功能
调节读写的偏移量
头文件
#include <sys/types.h>
#include <unistd.h>
函数原型
off_t lseek(int fildes, off_t offset, int whence);
返回值
成功时返回偏移量位置
否则返回-1
whence说明
SEEK_SET: 从文件头开始的偏移量
SEEK_CUR: 从当前位置开始加offset后的偏移值
SEEK_END: 从文件末开始加offset后的偏移值
dup()系统调用
功能
复制文件描述符
头文件
#include <unistd.h>
函数原型
int dup(int oldfd);
传给该函数一个现有描述符,返回一个新的描述符
新描述符是传给它的描述符的拷贝,即两描述符共享同一数据结构
如果对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的
返回值
成功时返回新文件描述符
否则-1
功能
复制文件描述符
头文件
#include <unistd.h>
函数原型
int dup2(int oldfd, int newfd);
允许规定一个有效描述符( oldfd )和目标描述符( newfd )
目标描述符将变成源描述符的复制品,即两个文件描述符指向同一文件,且是源描述符指向的文件
返回值
成功时返回新文件描述符
否则-1
fcntl()系统调用
功能
根据文件描述符来操作文件的特性
头文件
#include <unistd.h>
#include <fcntl.h>
函数原型
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
参数说明
fd:文件描述符
cmd:操作命令
arg:命令使用的参数
lock:同上
返回值
若成功,则依赖于cmd
若出错为-1
cmd参数说明
F_DUPFD:复制文件描述符
FD_CLOEXEC:设置close-on-exec标志
F_GETFD:读取文件描述符标志
F_SETFD:设置文件描述符标志
F_GETFL:读取文件状态标志
F_SETFL:设置文件状态标志
F_GETLK:获取记录锁
F_SETLK :释放记录锁
F_SETLKW:测试记录锁