第七、八章学习笔记

第七章 文件操作

一、文件操作级别

(1)硬件级别

fdisk∶将硬盘、U盘或SDC盘分区。
mkfs∶格式化磁盘分区,为系统做好准备。
fsck∶检查和维修系统。
碎片整理∶压缩文件系统中的文件。

其中大多数是针对系统的实用程序。普通用户可能永远都不需要它们,但是它们是创建和维护系统不可缺少的工具。
(2)操作系统内核中的文件系统函数

每个操作系统内核均可为基本文件操作提供支持。
(3)系统调用

用户模式程序使用系统调用来访问内核函数。open)、ead)、sek和 I close()函数都是C语言库函数。每个库函数都会发出一个系统调用,使进程进入内核模式来执行相应的内核函数,例如pen可进入 kopen(),read可进入kead函数,等等。

(4)I/O库函数

系统调用可让用户读/写多个数据块,这些数据块只是一系列字节。用户通常需要读/写单独的字符、行或数据结构记录等。如果只有系统调用,用户模式程序则必须自己从缓冲区执行这些操作。大多数用户会认为这非常不方便。为此,C语言库提供了一系列标准的I0函数,同时也提高了运行效率。

I/O库函数包括:

   mode I/0: fopen(), fread(); fwrite(),fseek(), fclose(),fflush()fputs() printf(),fprintf(),sprintf()

除了读/写内存位置的 sscanf /sprintf(函数之外,所有其他I/0库函数都建立在系统调用之上,也就是说,它们最终会通过系统内核发出实际数据传输的系统调用

(5)用户命令

用户可以使用Unix/ /Linux命来执行文件操作,而不是编写程序。
每个用户命令实际上是一个可执行程序(cd除外),通常会调用库I/O函数,而库I/0函数再发出系统调用来调用相应的内核函数。

(6)sh脚本

虽然比系统调用方便多,但是必须手动输入命令,如果使用的是GUI,必须要拖放文件图标和点击指向设备来输入。sh语言包含所有的有效Unix/Linux命令,还支持变量和控制语句。

二、文件I/O操作

用户模式下的程序执行操作
FILE *fp = fopen(“file”, “r”);or FILE *fp = fopen(“file”,”w”);

原理:fopen()在用户(heap)空间中创建一个FILE结构体,包含一个文件描述符fd、一个fbuf[BLKSIZE]和一些控制变量。会向内核中的 kopen() 发出一个fd=open(“file”,flags=READ or WRITE)系统调用。

三、分区

1、分区

一个区块存储设备可以分为几个逻辑单元,成为分区。分区表位于第一个扇区的字节偏移446(ox1BE)处,改扇区称为设备的主引导记录。
如果某分区是扩展类型(类型编号=5),那么它可以划分为更多分区。假设分区P4是扩展类型,它被划分为扩展分区P5、P6、P7。扩展分区在扩展分区区域内形成一个链表,

每个扩展分区的第一个扇区是一个本地MBR。每个本地MBR在字节偏移量0xIBE处也有一个分区表,只包含两个条目。第一个条目定义了扩展分区的起始扇区和大小。第二个条目指向下一个本地MBR。所有本地MBR的扇区编号都与P4的起始扇区有关。照例,链表以最后一个本地MBR中的0结尾。在分区表中,CHS值仅对小于8GB的磁盘有效。对大于8GB但小于4G扇区的磁盘,只有最后两个条目start _sector 和nr sector有意义。

2、格式化分区

fdisk只是将一个存储设备划分为多个分区。每个分区都有特定的文件系统类型,但是分区还不能使用。为了存储文件,必须先为特定的文件系统准备好分区。该操作习惯上称为格式化磁盘或磁盘分区。
在Linux中,命令
mkfs -t TYPE [-b bsize] device nblocks
在一个nblocks设备上创建一个TYPE文件系统,每个块都是bsize字节。如果bsize未指定,则默认大小为1KB.
在Linux中,还不能访问新的文件系统。它必须挂在到跟文件系统中的现有目录。由于细腻文件系统不是真正的设备i,他们必须作为循环设备挂载,如:
sudo mount -o loop vdisk /mnt

3、挂载分区

man 8 losetup : 显示永固系统管理的losetup实用工具命令。

四、EXT2文件系统简介

1、EXT2文件系统数据结构

2、超级块

s_first_data_block:0表示4KB块大小,1表示1KB块大小。它用于确定块组描述符的起始块,s_first_data_block+ 1。
s_log_block_size确定文件块大小,为1KB*(2**s_log_block_size),例如О表示1KB块大小,1表示2KB块大小,2表示4KB块大小,等等。最常用的块大小是用于小文件系统的1KB和用于大文件系统的4KB。
s_mnt_count :已挂载文件系统的次数。当挂载计数达到max_mount_count时,fsck 会话将被迫检查文件系统的一致性。
s_magic是标识文件系统类型的幻数。EXT2/3/4文件系统的幻数是0xEF53。

3、块组描述符

EXT2将磁盘块分成几个组。每个组都有8192个块。每个组用一个块组描述符结构体描述。

4、位图

块位图是用来表示某种项的为序列。
索引节点位图一个索引节点就是用来代表一个文件的数据结构。

第八章

一、系统调用手册

在Unix以及大多数版本的Linux中,在线手册页保存在/usr/man/目录中。man2子目录中列出了所有系统调用手册页。sh命令man2 NAME显示了系统调用名称的手册页。

二、系统调用进行文件操作

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 *patiiname);
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 uniink(char *pathname);
symlink:为文件创建一个符号链接
int symliak(char *oldpath, char *newpath);
rename:更改文件名称
int rename(char *oldpath, char *newpath)/
utime:更改文件的访问和修改时间
int utime(char *pathname, struct utimebuf *time)
以下系统调用需要超级用户权限。
mount:将文件系统添加到挂载点目录上
int mount(char *specialfile, char *mountDir)/
umount:分离挂载的文件系统
int umount(char *dir);
mknod:创建特殊文件
int mknod(char *path, int mode, int device);

权限数字表示法

每个数字都是是由r=4;w=2;x=1相加的结果得出来的
-rw------- (600) – 只有属主有读写权限。
-rw-r–r-- (644) – 只有属主有读写权限;而属组用户和其他用户只有读权限。
-rwx------ (700) – 只有属主有读、写、执行权限。
-rwxr-xr-x (755) – 属主有读、写、执行权限;而属组用户和其他用户只有读、执行权限。
-rwx–x--x (711) – 属主有读、写、执行权限;而属组用户和其他用户只有执行权限。
-rw-rw-rw- (666) – 所有用户都有文件读、写权限。这种做法不可取。
-rwxrwxrwx (777) –所有用户都有读、写、执行权限。更不可取的做法。

三、链接文件

1、硬链接:命令

ln oldpath newpath
创建从newpath到oldpath的硬链接。对应的系统调用为:
link(char *oldpath,char *newpath)
硬链接文件会共享文件系统中相同的文件表示数据结构。文件链接会记录链接到同一索引结点的硬连接数量。相反,系统调用:
unlink(char *pathname)
会减少文件的链接数。如果链接变为0,文件就被完全删除。

2、软链接:命令

ln -s oldpath newpath #in command with the -s flag
创建从newpath到oldpath的软链接或符号链接。对应的系统调用是:
symlink(char *oldpath,chat *newpath)
newpath是LNK类型的普通文件,包含oldpath字符串。与硬链接不同,软链接适用于任何文件,包括目录。

四、stat系统调用

1、stat/lstat/fstat系统调用可将一个文件的信息返回。命令 man 2 stat 会显示stat系统调用的手册页。

概要

#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遵循链接,但1stat不是。
fstat 与 stat相同,也只在文件名处说明filedes(由open ( 2)返回)所指向的打开文件。

2、文件类型和权限

在stat结构体中,大多数字段都无须解释。只有st_mode字段需要进行说明:mode_t st_mode;
/ * copied from i_mode of INODE*/
st_mode的类型是一个u16 ( 16位),这16位的含义如下:

前4位是文件类型,可以(以八进制形式)解释为:

S_IFMT		0170000		bitmask for the file type bitfields
S_IFSOCK	0140000		socket
s_IFLNK	0120000		symbolic link
s_IFREG	0100000		regular file
s_IFBLK		0060000		block device
s_IFDIR		0040000		directory
s_IFCHR		0020000		character device
S_IFIFO		0010000		fifo

3、opendir-readdir函数

目录也是一个文件。我们应该能像其他任何普通文件一样,打开一个一个READ目录,然后读取他的内容。然而根据文件系统的不同,目录文件的内容可能会有不同。因此,用户可能无法正确读取和解释目录的内容。鉴于此,POSIX为目录文件指定了以下接口函数。

4、readlink函数

linux的open()系统调用遵循符号链接。因此,无法打开符号链接文件并读取其内容。要想读取符号链接文件的内容,我们必须使用readlink系统调用,即
int readlink(char *pathname,char buf[],int bufsize)
他将符号链接文件的内容复制到bufsize的buf[]中,并将实际复制的字节数返回。

问题与解决

1、文件描述符有什么作用吗?

  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 确认删除文件是否被占用 ,再删除。

原文地址:https://www.cnblogs.com/kevin-hw/p/15390126.html