第 6 章 Linux文件系统_第1页
第 6 章 Linux文件系统_第2页
第 6 章 Linux文件系统_第3页
第 6 章 Linux文件系统_第4页
第 6 章 Linux文件系统_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章文件系统内筒提要Linux文件系统概述文件的基本操作文件属性操作目录操作文件系统操作标准I/O函数库6.1Linux文件系统概述文件系统概述

文件系统将文件作为用户存储数据的基本单位,文件可视作由若干字节构成的字节流,并将字节流以文件名的形式加以标识,为了便于管理,引入目录,将文件以层次结构分类组织;,目录可看做一种特殊类型的文件,其内容由若干目录项组成,目录项建立文件名与i节点的映射关系。

Linux系统支持多种类型的文件系统,为了封装特定文件系统的特性,Linux内核将各种文件系统统一在虚拟文件系统的框架下。文件系统架构页高速缓存(pagecache)硬件设备系统调用接口层虚拟文件系统(VFS)字符设备驱动通用块设备层网络设备驱动ext2fatnfsminix网络协议I/O调度层底层块设备驱动1底层块设备驱动n底层块设备驱动2openreadwriteclosestatlseek虚拟文件系统VFS

虚拟文件系统(VFS)是一种基于内存的抽象文件系统,它提供了一种将各种真实文件系统粘结在一起的框架,同样由超级块、i节点和目录项等对象组成,并分别为它们定义了一组抽象的操作接口。从而隔离了具体文件系统的特性,为上层应用提供了一致的编程接口。

Linux内核启动时将所需的文件系统通过VFS建立一颗目录树,根文件系统作为其主干,其他文件系统挂载至相应的分支。文件系统的结构

超级块是文件系统的组织者和管理者,负责对i节点表和数据区等对象的管理,i节点存储文件除名字外的所有信息,其中包括文件内容在数据区的分布,逻辑块是数据区的基本存储单位,目录是一种特殊文件,其内容存储文件的入口信息。文件系统引导块超级快数据块i-节点表数据区...01678910111213n-2n-1n14文件/目录大小创建日期修订日期访问日期归属数据分布i-节点247.520..610test611demo.c613demo.o620demostruct

dirent{

ino_t

d_ino;chard_name[NAME_MAX+1];}i-节点号文件名目录项的数据结构数据块11的内容分类API功能描述文件基本I/O操作open/close/unlink打开/创建/关闭/删除文read/write读/写文件readv/writev分散输入/集中输出pread/pwrite基于特定偏移量的读/写lseek定位读写操作的位置truncate文件截断dup/dup2复制文件描述符文件属性操作Stat/fstat/lstat获取文件的属性信息chmod设置文件的权限chown设置文件的属主/属组fcntl设置文件的操作目录操作mkdir/rmdir创建/删除目录chroot/chdir改变进程的根目录和工作目录opendir打开目录readdir读目录closedir关闭目录nftw遍历目录树文件系统操作mount/umount挂载/卸载文件系统statvfs获取文件系统的相关信息fsync/syncfs同步文件/文件系统标准I/O库fopen/fclose打开/关闭文件fread/fwrite读/写文件应用编程接口6.2文件的基本操作内容提要基本I/O操作分散输入和集中输出基于特定偏移量的I/O操作设置偏移量文件截断

I/O重定向基本I/O操作

读写文件时,需将数据在文件中的位置(偏移量)换算成数据在设备中的逻辑块号,该过程需借助i节点,因此,在读写文件前,应根据文件的路径名找到对应的i节点,这正是打开文件操作的任务。为了提高磁盘I/O性能,系统为每个打开的文件构建内核缓冲区,读操作首先搜索该缓冲区,在未命中时才真正向设备发起读请求,写操作时,只需将数据写入缓冲区,仅在必要时,才真正将数据写入设备。内核为每个打开的文件分配一个偏移量指针,指向当前读写位置,文建刚打开时,其值为0,随着读写操作的进行,指针向后作相应移动,必要时,可调整至所需位置。打开/关闭/删除操作头文件 #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h>函数原型 intopen(constchar*pathname,intflags); intopen(constchar*pathname,intflags,mode_tmode); intclose(intfd); intunlink(constchar*pathname);功能 打开/创建/关闭/删除文件。参数 pathname:文件的路径名。 flags:文件的操作模式。 mode:新建文件的权限分配。 fd:文件描述符。返回值 成功返回文件描述符,否则返回-1。打开文件inode

file…filesfs...

task_struct…filesfs...

task_struct进程1进程2file打开的文件描述i节点012012标准输入标准输出标准错误…f_dentryf_posf_op...…f_dentryf_posf_op...…i_sbi_op…d_named_inoded_named_inoded_named_inoded_named_inoded_named_inoded_named_inodedentry文件描述符打开的文件描述打开文件(续)

每个进程均有一个文件描述符表,用于记录打开的文件,内核为每个打开的文件创建一个文件描述,用于记录打开文件的状态,其地址记录在文件描述符表的某个单元中,单元的下标便是打开文件操作的返回值。一个文件描述可能会被多个进程或一个进程的多个文件描述符引用,例如,创建的子进程,子进程会继承父进程的文件描述符表,复制的文件描述符会共享文件描述。若进程源自登录shell,其文件描述符表的前三个单元通常处于打开状态,它们依次对应标准输入、标准输出和标准错误输出。关闭文件

当关闭文件时,对应文件描述的引用次数减1,当引用次数为0时,对应的文件描述被内核回收,若此时内核缓冲区中尚有未回写的数据,内核回将数据同步至设备。只有当打开文件上的所有引用全部关闭时,文件才能被删除。

读/写文件头文件

#include<unistd.h>函数原型

ssize_t

read(int

fd,void*buf,size_tcount);

ssize_t

write(int

fd,constvoid*buf,size_tcount);功能 读/写文件。参数

fd:文件描述符。

buf:缓冲区地址。

count:读/写字节数。返回值 成功,返回读/写的字节数,错误,返回-1。读/写文件(续)

读写文件时,根据文件描述符可定位关联的文件描述,由于文件描述存储了对应i节点的地址,可进一步找到对应的i节点,利用i节点中数据的分布信息,结合当前读写的偏移量,可计算出需要读写数据在设备上的位置,最终发起读写请求,真正完成数据的读写。实例分析

int

fds=open(argv[1],O_RDONLY);

int

fdt=open(argv[2],O_WRONLY|O_CREAT,0666);

ssize_t

len; while((len=read(fds,buf,BUFSIZ))>0)

write(fdt,buf,len);

close(fds);

close(fdt);分散输入和集中输出头文件

#include<sys/uio.h>函数原型

ssize_t

readv(int

fd,conststruct

iovec*iov,int

iovcnt);

ssize_t

writev(int

fd,conststruct

iovec*iov,int

iovcnt);功能 数据的分散读出/集中写入。参数

fd:文件描述符。

iovec:缓存向量。

iovcnt:缓存的数量。返回值 成功,返回读写的字节数,失败,返回-1。当保存读写数据的缓存地址不连续时,可使用分散输入和集中输出面向特定偏移量的读写操作头文件

#include<unistd.h>函数原型

ssize_t

pread(int

fd,void*buf,size_tcount,off_toffset);

ssize_t

pwrite(int

fd,constvoid*buf,size_tcount,off_toffset);功能 基于特定偏移量的读/写文件。参数

fd:文件描述符。

buf:缓冲区地址。

count:字节数。

offset:偏移量。返回值 成功,返回读写的字节数,失败,返回-1。 可避免对个进程同时竞争文件偏移量,适用于多个进程/线程同时存取文件的不同区域。设置当前偏移量头文件

#include<sys/types.h> #include<unistd.h>函数原型

off_t

lseek(int

fd,off_toffset,intwhence);功能 设置文件的当前偏移量。参数

fd:文件描述符。

offset:偏移量。

whence:参照坐标。返回值 成功,返回距文件头的字节数,失败,返回-1。

文件截断

文件写操作时,设备上存储数据的逻辑块,会依次映射至文件的线性空间,逻辑块时文件存储数据的最小单位,通常文件的最后一个逻辑块会有剩余,从而造成一定程度的浪费。若写入文件的字节不连续,则未写入部分会形成空隙,若空隙中存在未映射的逻辑块,则未映射部分形成空洞。文件截断和重置偏移量均有可能产生空隙。文件截断操作头文件

#include<unistd.h> #include<sys/types.h>函数原型

int

truncate(constchar*path,off_tlength);

int

ftruncate(int

fd,off_tlength);功能 文件截断。参数

path:文件路径。

fd:文件描述符。

length:文件长度。返回值 成功,返回0,失败,返回-1。

文件空袭...文件空洞(2个逻辑块)文件空隙(10.5k)扇区(512字节)文件大小(13.5k)映射映射逻辑块(4k)磁盘空间文件(字节流)/O重定向shell在加载可执行文件时,通过创建子进程,在子进程中加载可执行程序实现命令的运行。

I/O重定向可通过在子进程加载可执行文件前,改变子进程的运行环境,修改标准输入输出所指的文件描述。这可通过复制文件描述副和close-open来实现。复制文件描述符头文件

#include<unistd.h>函数原型

int

dup(int

oldfd);

intdup2(intoldfd,int

newfd);功能 复制文件描述符。参数

oldfd:原文件描述符。

newfd:新文件描述符。返回值 成功返回副本的文件描述符,失败返回-1。实例分析int

main(int

argc,char*argv[]){ if(argc!=2){

printf("Usage:%sfilename\n",argv[0]); exit(1); }

int

fd=open(argv[1],O_WRONLY|O_CREAT,0644);

intfd1=dup2(fd,1);

printf("hellodup2:%d\n",fd1);

write(fd,"endofprogram\n",15); return0;}6.3文件属性操作内容提要文件属性概述获得文件属性修改文件访问权限改变文件的归属设置文件行为属性文件属性概述structstat{

dev_t

st_dev; //文件的设备编号

ino_t

st_ino; //i节点号

mode_t

st_mode; //文件的类型和存取权限

nlink_t

st_nlink; //硬链接数量,即引用次数

uid_t

st_uid; //属主ID

gid_t

st_gid; //属组ID

dev_t

st_rdev; //设备类型

off_t

st_off; //文件字节数

unsignedlongst_blksize; //块大小

unsignedlongst_blocks; //块数,一块大小为512字节

time_t

st_atime; //最后一次访问时间

time_t

st_mtime; //最后一次修改时间

time_t

st_ctime; //最后一次改变时间(指属性)};0121415文件类型其他用户属组属主扩展权限i节点存储文件属性,其结构和内容与文件系统有关,为了隔离文件系统特性,Linux系统定义类型为stat的数据结构,并配合stat核心函数,降获取的文件属性存储于stat类型的实例。获取文件属性头文件

#include<sys/stat.h> #include<unistd.h>函数原型

int

stat(constchar*pathname,structstat*buf);

int

fstat(int

fd,structstat*buf);

int

lstat(constchar*pathname,structstat*buf);功能 获取文件的状态属性。参数

pathname:文件的路径名。

filedes:文件描述符。

buf:指向文件属性地址。返回值 成功,返回0,失败,返回-1。实例分析intret=stat(argv[1],&sb);if(ret==-1)err(1,"%s",argv[1]);printf("Filetype:");switch(sb.st_mode&S_IFMT){ caseS_IFBLK:printf("blockdevice\n");break; caseS_IFCHR:printf("characterdevice\n");break; caseS_IFDIR:printf("directory\n");break; caseS_IFIFO:printf("FIFO/pipe\n");break; caseS_IFLNK:printf("symlink\n");break; caseS_IFREG:printf("regularfile\n");break; caseS_IFSOCK:printf("socket\n");break;

default:printf("unknown?\n");break;}修改文件访问权限头文件

#include<sys/type.h> #include<sys/stat.h>函数原型

int

chmod(constchar*pathname,mode_tmode);

int

fchmod(int

fd,mode_tmode);功能 设置文件的权限。参数

pathname:文件的路径名。

fd:文件描述符。

mode:权限。返回值 成功,返回0,失败,返回-1。实例分析#include<stdlib.h>int

main(int

argc,char*argv[]){ if(argc!=3){

fprintf(stderr,"Usage:%sfilebane

mode(octal)\n",argv[0]); exit(1); }

mode_tmode=strtol(argv[2],NULL,8); chmod(argv[1],mode); exit(0);}改变文件的归属头文件

#include<unistd.h>函数原型

int

chown(constchar*pathname,uid_towner,gid_tgroup);

int

fchown(int

fd,uid_towner,gid_tgroup);

int

lchown(constchar*pathname,uid_towner,gid_tgroup);功能 设置文件的归属。参数

path:文件的路径名。

owner:新属主ID。

group:新属组ID。返回值 成功,返回0,失败,返回-1。设置文件行为属性头文件

#include<unistd.h> #include<fcntl.h>函数原型

int

fcntl(int

fd,int

cmd,longarg)功能 设置文件的行为属性。参数

fd:文件描述符。

cmd:操作命令。

arg:传递的参数。返回值 成功,返回值依赖于具体的操作,失败,返回-1。设置文件行为属性(续)fcntl函数中参数cmd的定义参数cmd

含义F_GETFL/F_SETFL获取/设置文件状态F_GETLK/F_SETLK/F_SETLKW获得/设置文件锁F_DUPFD复制尚未使用的最小文件描述符F_GETOWN_EX/,F_SETOWN_EX获取/设置I/O信号接收的目标F_GETSIG/F_SETSIG获取/设置异步I/O信号6.4目录操作目录概述

目录属于一种特殊的文件,目的是为了有效组织和管理文件系统,将文件系统构建成一棵基于层次关系的目录树。目录由若干目录项组成,目录项中记录文件的名称及其对应的i节点编号,建立起文件名和i节点的映射关系。由于目录文件内容的布局与文件系统有关,因此,无法象普通文件一样通过read函数读取,为此,Linux内核提供了getdents系统调用,为了简化操作,glibc提供了相应的库函数。创建/删除目录mkdir/rmdir函数头文件

#include<sys/types.h> #include<stat.h>函数原型

int

mkdir(constchar*pathname,mode_tmode);

int

rmdir(constchar*pathname);功能 创建/删除目录。参数

pathname:目录的路径名。

mode:新建目录权限。返回值 成功,返回0,失败,返回-1。根目录和工作目录1.chroot函数头文件

#include<unistd.h>函数原型

int

chroot(constchar*path);功能 改变进程的根目录。参数

path:路径名。返回值 成功,返回0,失败,返回-1。根目录和工作目录

2.chdir函数头文件

#include<unistd.h>函数原型

int

chdir(constchar*path);

int

fchdir(int

fd);功能 设置进程的工作目录。参数

path:路径名。

fd:文件描述符。返回值 成功,返回0,失败,返回-1。浏览目录1.opendir函数头文件

#include<sys/types.h> #include<dirent.h>函数原型

DIR*opendir(constchar*pathname); DIR*fdopendir(int

fd);功能 打开目录。参数

pathname:目录路径名。

fd:文件描述符。返回值 成功返回目录流,失败,返回NULL。浏览目录头文件

#include<sys/types.h> #include<dirent.h>函数原型

struct

dirent*readdir(DIR*dirp);功能 读目录。参数

dirp:打开的目录流。返回值 成功,返回下一个目录项,失败,返回NULL。struct

dirent

{longd_ino; //i节点号

chard_name[256]; //文件名

off_t

d_off; //在目录流中的偏移量

unsignedshortd_reclen; //文件名长度}浏览目录3.closedir函数头文件

#include<sys/types.h> #include<dirent.h>函数原型

int

closedir(DIR*dirp);功能 关闭打开的目录。参数

dirp:打开的目录流。返回值 成功,返回0,失败,返回-1。实例分析int

main(int

argc,char*argv[]){DIR*dirp;

struct

dirent*direntp;if((dirp=opendir(argv[1]))==NULL){

fprintf(stderr,"errormessage:%s\n",strerror(errno));exit(1);}while((direntp=readdir(dirp))!=NULL)

printf("%s\n",direntp->d_name);closedir(dirp);exit(0);}6.5文件系统操作文件系统概述

为了使用文件系统,Linux内核向用户层提供了相应的接口,在使用文件系统前,首先需通过mount函数将文件系统挂载至某个特定目录,当文件系统不再使用时,可通过umount函数将其从挂载点卸载,期间,可通过statvfs函数,获取文件系统的当前状态;必要时,可通过syncfs函数将整个文件系统同步至存储设备。挂载/卸载文件系统头文件

#include<sys/mount.h>函数原型

int

mount(constchar*source,constchar*target,char*type,unsignedlongflags,void*data);

int

umount(constchar*target);功能 挂载一个文件系统至目标目录。参数

source:源块设备文件。

target:挂载点目录。

type:文件系统类型。

flags:操作行为。

data:传递数据。返回值 陈宫,返回0,失败,返回-1。获取文件系统信息statvfs函数头文件

#include<sys/statvfs.h>函数原型

int

statvfs(constchar*path,struct

statvfs*buf);

int

fstatvfs(int

fd,struct

statvfs*buf);功能 获取文件系统的统计信息。参数

path:文件的路径名。

fd:文件描述符。

buf:指向存放文件系统统计信息的地址。返回值 成功,返回0,失败,返回-1。获取文件系统信息struct

statvfs{unsignedlongf_bsize;//逻辑块大小

unsignedlongf_frsize;//碎片大小

fsblkcnt_t

f_blocks;//碎片占用的逻辑块数

fsblkcnt_t

f_bfree;//空闲块数量

fsblkcnt_t

f_bavail;//用户可用的逻辑块数

fsfilcnt_t

f_files;//总i-节点数量

fsfilcnt_t

f_ffree;//空闲i-节点数

fsfilcnt_t

f_favail;//用户可用的i-节点数

unsignedlongf_fsid;//文件系统IDunsignedlongf_flag;//mount标识

unsignedlongf_namemax;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论