第7、8章学习笔记
一、知识点归纳
- 1、文件操作级别从低到高分为硬件级别、操作系统内核中的文件系统函数、系统调用、I/O库函数、用户命令、sh脚本
- 2、文件I/O操作:
(1)用户模式下的程序执行操作
FILE Ep = fopen ("file","r"); or 室ILEEp = fopen ( "tile","w"')1可以打开一个读/写文件流。
( 2 ) fopen()在用户( heap)空间中创建一个FILE结构体,包含一个文件描述符fd、一个fbuf [BLKSIZE]和一些控制变量。
( 3 ) fread(ubuf, size, nitem, fp):将nitem个size字节读取到ubuf上,通过:·将数据从FILE结构体的fbuf上复制到ubuf上,若数据足够,则返回。·如果 fbuf没有更多数据,则执行(4a)。
(4a)发出read(fd,fbuf, BLKSIZE)系统调用,将文件数据块从内核读取到 fbuf上,然后将数据复制到ubuf上,直到数据足够或者文件无更多数据可复制。
( 4b) fwrite(ubuf, size, nitem, fp):将数据从ubuf复制到fbuf。·若(fbuf有空间):将数据复制到fbuf 上,并返回。
·若(fbuf已满):发出 write(fd,fbuf,BLKSIZE)系统调用,将数据块写入内核,然后再次写入fbuf。
这样,fread()/fwrite()会向内核发出read(/write)系统调用,但仅在必要时发出,而且它们会以块集大小来传输数据,提高效率。同样,其他库I/O函数,如 fgetc/fputc、fgetsllputs、fscanf/fprintf等也可以在用户空间内的FILE结构体中对fbuf进行操作。
(5)内核中的文件系统函数:
假设非特殊文件的 read(fd, fbuf[ ], BLKSIZE)系统调用。
(6)在read()系统调用中,fd是一个打开的文件描述符,它是运行进程的f数组中的一个索引,指向一个表示打开文件的OpenTable。
( 7 ) OpenTable包含文件的打开模式、一个指向内存中文件INODE的指针和读/写文件的当前字节偏移量。从 OpenTable的偏移量,
·计算逻辑块编号1bk。
·通过INODE.i_block[ ]数组将逻辑块编号转换为物理块编号blk。
( 8 ) Minode包含文件的内存 INODE。EMODE.i_block[ ]数组包含指向物理磁盘块的指针。文件系统可使用物理块编号从磁盘块直接读取数据或将数据直接写入磁盘块,但将会导致过多的物理磁盘I/O。
(9)为提高磁盘IO效率,操作系统内核通常会使用一组IO缓冲区作为高速缓存,以减少物理I/O的数量。磁盘I/O缓冲区管理将在第12章中讨论。
(9a)对于read(fd, buf, BLKSIZE)系统调用,要确定所需的(dev,blk)编号,然后查询I/O缓冲区高速缓存。
(9b)对于write(fd, fbuf, BLKSIZE)系统调用,要确定需要的(dev,blk)编号,然后查询I/O缓冲区高速缓存。
(10)设备I/O:Io缓冲区上的物理IO最终会仔细检查设备驱动程序,设备驱动程序由上半部分的start_io()和下半部分的磁盘中断处理程序组成。 - 3、低级别文件操作:分区、、格式化分区、挂载分区
- 4、 EXT2文件系统是Linux系统中广泛使用的文件系统,该文件系统是一种索引式文件系统,它将分区分为inode和block,它会给每个文件分配一个inode,inode中存储文件的一些属性信息,block中存储文件真正的内容,一个block的大小有1k、4k等大小,一个block中只能存储一个文件。
- 5、使用系统调用进行文件操作:
简单的系统调用:
access:检查对某个文件的权限
int access(char *pathname, int mode);chdir:更改目录
int chdir(const char *path);chmod:更改某个文件的权限
int chmod(char *path, mode_t mode) ;chown:更改文件所有人
int chown (char *name, int uid, int gid);chroot:将(逻辑)根目录更改为路径名int chroot (char *pathname) ;
getcwd:获取CWD的绝对路径名char *getcwd(char *buf, int size);
mkdir:创建目录
int mkdir (char *pathname, mode_t mode);
rmdir:移除目录(必须为空)
int rmdir(char *pathname );
link:将新文件名硬链接到旧文件名
int link (char *oldpath, char *newpath) ;
unlink:减少文件的链接数;如果链接数达到0,则删除文件int unlink (char *pathname);
symlink:为文件创建一个符号链接
int symlink(char *oldpath,char *newpath);rename:更改文件名称
int rename(char *oldpath, char *newpath);utime:更改文件的访问和修改时间
int utime(char *pathname, struct utimebuf *time)以下系统调用需要超级用户权限。
mount:将文件系统添加到挂载点目录上
intmount(char *specialfile, char *mountDir);
umount:分离挂载的文件系统
int umount (char *dir) ;
mknod:创建特殊文件 - 6、常用系统调用
- stat:获取文件状态信息
open:打开一个文件进行读、写、追加
int open(char *file, int flags, int mode)close:关闭打开的文件描述符
int close(int fd)
read:读取打开的文件描述符
int read(int fd,char buf[ 1, int count)write:写入打开的文件描述符
int write(int fa,char buf[ 1, int count)
lseek:重新定位文件描述符的读/写偏移量int lseek ( int fa, int offset, int whence)
dup:将文件描述符复制到可用的最小描述符编号中int dup(int oldfd) ;
dup2:将oldfd复制到newfd 中,如果newfd已打开,先将其关闭int dup2(int oldfa,int newfd)
link:将新文件硬链接到旧文件
int link(char *o1dPath, char *newPath)
unlink:取消某个文件的链接;如果文件链接数为0,则删除文件int unlink(char *pathname) ;
symlink:创建一个符号链接
int symlink(char *target,char *newpath)
readlink:读取符号链接文件的内容
int readlink(char *path,char *buf, int bufsize)
umask:设置文件创建掩码;文件权限为( mask & ~umask) - 7、stat文件状态
名称
stat, fstat, lstat - get file status
概要
include <sys/types.h>#include <sys/stat.h>#include <unistd.h>
int stat(const char *file_name,struct stat *buf) ;int fstat(int filedes,struct stat *buf);
int lstat(const char *file_name,struct stat *buf) ;描述
这些函数会返回指定文件的信息。不需要拥有文件的访问权限即可获取该信息,但是需要指向文件的路径中所有指定目录的搜索权限。
stat按文件名统计指向文件,并在缓冲区中填写stat信息。
lstat与stat相同,除非是符号链接,统计链接本身,而不是链接所引用文件。所以,stat 和 1stat的区别是:stat遵循链接,但 lstat不是。
fstat与 stat相同,也只在文件名处说明filedes(由open ( 2)返回)所指向的打开文件。
二、实践与操作
三、问题与解决
1、文件描述符是什么,有什么作用吗?
解决:文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号码,因此,在网络通信过程中稍不注意就有可能造成串话。标准文件描述符图如下:
作用: 1. 由于进程级文件描述符表的存在,不同的进程中会出现相同的文件描述符,它们可能指向同一个文件,也可能指向不同的文件 2. 两个不同的文件描述符,若指向同一个打开文件句柄,将共享同一文件偏移量。因此,如果通过其中一个文件描述符来修改文件偏移量(由调用read()、write()或lseek()所致),那么从另一个描述符中也会观察到变化,无论这两个文件描述符是否属于不同进程,还是同一个进程,情况都是如此。3. 要获取和修改打开的文件标志(例如:O_APPEND、O_NONBLOCK和O_ASYNC),可执行fcntl()的F_GETFL和F_SETFL操作,其对作用域的约束与上一条颇为类似。4. 文件描述符标志(即,close-on-exec)为进程和文件描述符所私有。对这一标志的修改将不会影响同一进程或不同进程中的其他文件描述符
2、LINUX根磁盘分区满了怎么办?
解决思路:删...
1.使用 df -h 命令查看磁盘使用情况
2.查看知道是磁盘使用满了之后从服务器根目录使用du -h --max-depth=1命令查找出占用空间最多的文件夹,输入命令:ls –lhS 将文件以从大到小顺序展现
3.rm –f 前确认下是否要下载下来让开发人员分析日志。
在Linux或者Unix系统中,通过rm或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink).然而如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用。
输入命令:/usr/sbin/lsof|grep deleted 确认删除文件是否被占用
然后就删删删