(二)文件属性

我们通过ls查到就是文件属性,只不过ls只显示了部分文件属性

Table of Contents

1.涉及到的OS API

2.文件类型

2.1 文件的7种类型

2.2 如何判断文件的类型 

3、获取文件属性的函数,stat、lstat、fstat

3.1 stat

3.2 lstat

3.3.fstat

3.5 r w x的含义

4. umask函数

4.0 open函数创建新文件时的一个问题

4.1 函数原型

4.2每一个进程都有一个文件权限掩码

6. 文件长度st_size

7. 文件截断函数truncate、    ftruncate

7.1 函数原型

8. 空洞文件

9. 文件系统是如何管理文件的    

文件系统管理文件的逻辑结构——树形结构    

文件在块设备上是如何存储的

文件系统是如何通过“文件路径名”索引找到文件

10. link,unlink,remove,rename函数

10.1.1 硬链接

10.1.2 link函数

10.2 unlink函数

10.3、remove函数

10.4、rename函数

11.1 软链接文件 (快捷图标)

11.4 符号跟随函数 与 符号不跟随函数

12. getcwd、chdir、mkdir、rmdir

12.1 getcwd

12.2 chdir

12.3 mkdir函数

12.4 rmdir函数

13. opendir、readdir

13.1 opendir

13.2 readdir

14. chmode、fchmod


1.涉及到的OS API

stat、fstat、lstat

umask

chmod、fchmod

chown,fchown,lchown

link,unlink,remove,ren
symlink和readlink

chdir、和getcwd


看起来很多,不过每一行都是一组,只要理解其中一个,其它的都很好理解。

而且这些函数,都与我们常用的cd、ls、chmod、chown、pwd等命令息息相关

2.文件类型

2.1 文件的7种类型

Linux一切皆文件,文件一共分为7类分别是 - d c s p l b

(1)普通文件(regular file:-  

             文本文件           纯二进制文件(机器码)

(2)目录文件(director file:d)

             目录是一种特殊的文件,专门用于管理其它文件。

(3)字符设备文件(character special file:c)

             字符设备文件,就是字符设备驱动程序,在上层的表现形式。

(4)块设备文件(block special file:b):对应块设备(如磁盘等)。

             1)块设备文件,是块设备驱动程序在上层的表现形式。

             2)字符设备与块设备有什么区别?

                     

(5)FIFO(fifo:p)

          管道文件,用于实现不同进程(程序)之间的通信

(6)套接字文件(socket:s)

          专门用于网络通信的文件。

(7)符号连接(symbolic link:l):

          其实就是一种快捷图标,背后指向了另外一个文件。

2.2 如何判断文件的类型 

(1)ls查看- d c l b s p符号来区分

(2)可以使用file命令来查看

         (a)如果查看的是文本文件

         (b)如果你查看的是纯二进制文件(机器码)

           

3、获取文件属性的函数,stat、lstat、fstat

ls命令其实就是调用了这三个函数中的lstat来实现的,我们可以调用lstat函数来自己实现一个ls命令。

这三个是兄弟函数,实现的功能相同,只是略微有区别,我们只要先把stat函数搞清楚了,lstat、fstat非常容易理解。

3.1 stat

函数原型

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct stat *buf);

 

3.2 struct stat结构体

7类文件都有的属性

专门给块设备文件用的。

专门给字符设备用的

ls的信息

(1)st_uid 和 st_gid    用户id      组的组id

 

(2)st_mode

          (a)- :文件类型

          (b)rwxrwxr-x:文件权限   (读写执行)   

                       文件所属用户   所属组    其他人

 

(3)将数字形式的st_mode,打印为-rwxrwxr-x形式

          文件类型
                   12~15 bit用于表示文件类型

                    如何表示文件类型

                                     

                  · 如何取出12~15位的值,然后用于判断文件的类型

                   

                   

       文件权限

                   

 

  (4)如何使用chmod命令修改文件权限(rwx)

          (a)方法1:直接使用数字   chmod 777 file.txt

          (a)方法2:直接使用rwx来设置

               · 例子1:修改所有权限 - chmod a=rw- file.txt 

               · 例子2:只修改某一组的权限- chmod u=rwx,g=rw-,o=r-- file.txt

               · 例子3:只修改组里面某一位的权限- chmod u+r,g+w,o+x file.txt

3.2 lstat

3.3.fstat

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int fstat(int fd, struct stat *buf);

3.5 r w x的含义

1)x对于普通文件来说

如果普通文件存放的只是文字编码,因为文字编码无法被cpu执行,所以普通文件的x没有太大意义,所以一般的普通文件的x权限一般都是-。

2)x对于目录的意义?

我们发现目录都有x,显然目录里面放的并不是机器指令,是不能被执行的,那么x对于目录的意义何在呢?

对于目录的x来说,也被称为通过权限,也就是说,如果你的目录没有x权限,你是无法通过这个目录的。

3)x对于其它文件来说,意义不大

4. umask函数

4.0 open函数创建新文件时的一个问题

 open函数创建新的文件时,如果指定的是0777满级权限的话,实际创建文件权限为0775(rwxrwxr-x) 

(1)为什么不是满级权限

      因为被文件权限掩码做了限制。

       

(2)怎么将文件权限掩码改为0

      使用umask即可。

4.1 函数原型

#include <sys/types.h>
#include <sys/stat.h>

mode_t umask(mode_t mask);

    

4.2每一个进程都有一个文件权限掩码

我的程序,修改只是当前进程的文件权限掩码,对其它进程的文件权限掩码无影响。

6. 文件长度st_size

struct stat中的st_size被用来存放文件长度,但只对普通文件目录、以及符号连接文件有意义。

因为只有普通文件、目录、以及符号链接文件才有实际的数据,有数据才有文件长度

其它的文件在块设备上只存储了文件属性,它们只是挂了一个文件名,以文件的形式进行管理而已,没有实际的数据,所以对于 这些文件来说,文件大小是没有意义的。

符号链接文件的文件大小 

符号链接文件就是一个快捷键,背后指向了某个文件。

符号链接文件的数据,就是所指向文件的文件名,所以它的文件大小指的就是这个名字的字符个数。

7. 文件截断函数truncate、    ftruncate

open可以指定了O_TRUNC后,文件里面有数据的话,会将打开的文件截短(清空)为0,

文件截短函数truncate,它不仅能够将文件截为0,还可以把文件截短为任意长度。

7.1 函数原型

#include <unistd.h>
#include <sys/types.h>
	
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

8. 空洞文件

我承诺给你一亩地,但是你又不是马上就要用满这一亩地,是一点一点来占用的,如果我现在一下子把一亩地全部你,

但是你要花费很久时间才会把地全用上,在你占满之前,一直有相当部分空间被闲置不用,显然非常浪费空间资源。

迅雷等下载文件

比如下载一个1M大小的文件,文件肯定是要花费相当长的时间才能下载完成,如果我直接就开辟一个实际占用1M空间
的普通文件来放数据的话,在实际下载完数据之前,未装满数据的空间都被闲置,会很浪费空间,怎么办呢?

 

解决办法就是开辟一个1M大小的空洞文件,空洞文件的理论大小是1M,但是并没有在块设备上实际给你分配1M的物理空间 而是在下载过程中,每下载一部分数据,再实际开辟一部分空间给你,直到整个文件下完位置。

如何制作空洞文件

truncate、ftrucate制作

        文件截短长度 > 文件长度时,多余的部分就是空洞。

        du命令:查看文件在块设备上,实际占用的物理空间。

        ls查看到的只是文件的理论大小,但是空洞部分并不占用实际物理存储空间。

使用lseek制作

        将文件读写位置调整到文件尾部之后,然后写点数据,中间空出的部分就是空洞。

9. 文件系统是如何管理文件的    

文件系统管理文件的逻辑结构——树形结构    

对于文件系统来说,目录是非常重要的文件组织节点。

文件在块设备上是如何存储的

(1)超级区

               负责“块设备”空间的分配和回收。

(2)inode节点区

               1)被划分为了一个个相连的,空间大小相同的inode节点空间。

               2)每个节点空间被用于存放某个文件的属性信息,每个节点空间大小是固定的

               3)每个节点都有一个节点编号,通过节点编号就可以索引找到inode节点空间。

(3)数据区

           存储数据时,实际上并不是数据有多少个字节,就分配对应多少的字节空间给你,为了便于物理空间高效管理,往往都是按块 分配空间的,一块往往为4k字节(4*1024)

       1)普通文件

       2)目录文件

             

       3)链接文件 :  存放的数据很简单,就是所指向文件的文件名。

文件系统是如何通过“文件路径名”索引找到文件

1)索引找到普通文件 

fd = open("/new/xxx.txt", O_RDWR); 

找到数据存放空间的起始地址后,read、write调用驱动读写数据时, 块设备驱动程序”通过这个地址,就能够实现读写。

 

stat("/new/xxx.txt", ...); 

       这个函数获取文件属性时,也是按照相同的原理来索引的,找到文件的inode节点空间后,就可以将inode节点中的文件属性读取出来。

10. link,unlink,remove,rename函数

这几个函数与ln、rm、mv命令息息相关,因为这几个命令就是调用这几个函数来实现的

10.1.1 硬链接

(1)ln命令创建硬链接:          ln xxx.txt xxx1.txt

(2)创建硬链接,创建的是什么      创建硬链接,就是再为文件创建一个名字。

           1)每创建一个硬链接,文件就多一个文件名,硬件链接数+1

                

                从图中看出,创建硬链接后所得到的多个文件名,指向的同一个inode节点,

                只有inode节点代表了文件的真实存在,

                inode节点只有一个,因此多个文件名指向的是同一个文件,不管使用的是哪一个文件名,都能操作这个文件。

          2)硬链接数

               记录了有多少个文件名指向了inode节点,通过创建硬链接,每增加一个文件名,就多一个硬链接数。

          3)删除文件后,文件数据还在吗?

                还在,因为删除文件时,只是将文件的inode节点空间释放了,如果这个文件有数据的话,

                那么这个文件的数据仍然还在,只要将文件的inode节点空间恢复,即可还原该文件。

          4)有关目录的硬链接数

             (a)为什么新建的目录一开始的文件链接数就是2

                      因为新创建的目录,一开始就有两个名字指向了目录的inode节点,分别是目录的本名new和.

                      

            (b)为什么在该目录下,每多创建一个目录,当前目录就会多一个硬链数

                      新创建目录的..名字,也指向了当前目录new。

                      

            (c)能不能使用ln命令,自己给目录创建硬链接

                      答:不能,Linux不允许用户自己给目录创建硬链接,只能由Linux系统自己给目录创建硬链接。

                             用户只能给目录以外的,其它类型的文件创建硬链接。

10.1.2 link函数

#include <unistd.h>

int link(const char *oldpath, const char *newpath);

  

10.2 unlink函数

#include <unistd.h>

int unlink(const char *pathname);

  

 

  使用unlink创建临时文件

          所谓临时文件就是,只在程序运行过程中有效,程序运行结束后就自动删除,这就是临时文件,

  如何使用unlink创建临时文件?

  1.   open创建一个文件后(新文件的硬链接数都是1),然后立即调用unlink将文件硬链接数减为0,将其删除。
  2.   虽然文件的硬链接数变成了0,但是在进程没有结束之前,这个文件仍然可以被使用,直到进程结束后,文件被删

10.3、remove函数

10.3.1函数原型

#include <stdio.h>

int remove(const char *pathname);

10.3.2 为什么这个函数既能用于删除一般文件,也能用于删除目录

(1)remove是一个库函数  它封装了unlink和rmdir这两个系统函数。

          

(3)rm命令

         这个命令既能用于删除目录,也能用于删除其它所有的文件,可以认为就是调用remove实现。

10.4、rename函数

修改文件的路径名,mv命令就是调用这个函数实现的。

函数原型

#include <stdio.h>

int rename(const char *oldpath, const char *newpath);

1)修改路径名情况1:当只改路径,不改文件名字 :      这种情况其实就是移动。

       如果文件移动起始位置和目标位置,在同一个分区里面的话

  •                移动文件时,不会移动文件的数据,只是把文件的基本信息(名字、inode编号),
  •                从这个目录记录到另一个目录下

       如果移动的起始位置和目标位置,不在同一个分区

  •               既要移动数据,也要移动文件基本信息

       在Linux下,分区是以目录的形式存在的,而在windows分区是以c:等盘符形式存在

 

2)修改路径名情况2:不改路径,只改文件名       这种情况就是一般意义上的改名。

3)修改路径名情况3:既改路径,也改文件名

11. symlink、readlink

这两个函数与符号链接文件有关,(软链接文件)

11.1 软链接文件 (快捷图标

11.1.1 使用ln -s就可以创建符号链接文件

11.1.2 什么是符号链接文件  

           符号链接文件就是一个快捷图标,它指向了另一个文件

11.1.3 符号链接 与 硬链接的对比

       

     (1)创建硬连接

                同一个文件有多个不同的名字,它们指向是同一个inode节点。

     (2)创建符号链接文件

               符号链接文件与它所指向的文件,是两个完全不同的独立的文件,拥有自己独立的inode节点。

               符号链接文件的数据就是指向文件的文件名,文件大小就是名字的字符个数。

     (3)不能给目录创建硬链接,但是可以给目录创建符号链接文

     (4)可以给符号链接文件,创建硬链接吗  可以

#include <unistd.h>

int symlink(const char *oldpath, const char *newpath);

#include <unistd.h>

ssize_t readlink(const char *path, char *buf, size_t bufsiz);
	

  

11.4 符号跟随函数 与 符号不跟随函数

(1) 符号跟随函数

(2)符号不跟随函数

12. getcwd、chdir、mkdir、rmdir

12.1 getcwd

这是一个库函数,执行pwd命令就是调用这个函数实现的。

#include <unistd.h>

char *getcwd(char *buf, size_t size);

  

   pwd这个命令获取的是,当前终端这个进程的工作路径。

   我自己的进程调用getcwd函数,获取的是我自己进程的当前工作路径,默认是你运行这个程序时所在的路径。

12.2 chdir

#include <unistd.h>
				
int chdir(const char *path);

  

12.3 mkdir函数

mkdir命令调用的就是这个函数。

#include <sys/stat.h>
#include <sys/types.h>

int mkdir(const char *pathname, mode_t mode);

12.4 rmdir函数

rmdir和rm命令删除目录时,调用的都是rmdir这个函数。

  •        rmdir命令:只能删除空目录,rmdir命令用的很少
  •        rm:不管目录空不空,都能删除,rm用的最多

函数原型

#include <unistd.h>

int rmdir(const char *pathname);

如果目录不为空,必须递归调用rmdir函数,实现递归删除。 

什么是递归删除?

13. opendir、readdir

opendir:打开目录,以便调用readdir读取目录项

readdir:读取目录里面的目录项


什么是目录项?

13.1 opendir

#include <sys/types.h>
#include <dirent.h>

DIR *opendir(const char *name);

  

13.2 readdir

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

  

14. chmode、fchmod

 #include <sys/stat.h>

 int chmod(const char *pathname, mode_t mode);
 int fchmod(int fd, mode_t mode);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章