文章目录
- 文件类型
- 普通文件(regular file:-)
- 目录文件(directory file:d)
- 字符特殊文件( character special file: c)
- 块设备文件(block special file: b):对应块设备(如磁盘等)。
- FIFO(fifo:p)
- 套接字文件( socket: s)
- 符号连接(symbolic link: l):
- 获取文件属性
- stat函数
- st_mode
- st_size
- 空洞文件的意义
- 制作空洞文件
- 文件权限掩码
- 如何修改文件权限掩码
文件类型
在Linux下一切皆是文件,从应用层(应用程序层)看待底层机制时,皆以文件的方式来看待这些机制.但是不同的底层机制,毕竟是不同的,比如底层驱动程序,就分为字符设备驱动和块设备驱动,根据底层机制的不同,文件被分为了7种类型,分布是 - d c s p c b
普通文件(regular file:-)
普通文件根据存放的内容的不同,又分为如下两种
- 文本文件
存放的都是文字编码,文本编辑器打开后,会将这些文字编码翻译为文字图形,以供人识别。 - 纯二进制文件(机器码)
比如经过编译后得到的可执行文件,里面放的是cpu执行的纯二进制机器码,由于文编编辑器只认识文字编码,所以用文本编辑器打开后,显示的内容无法是错乱的,无法辨识。
其实不管存放的是文字编码,还是机器码,在计算机中存储时,其实都是以二进制形式存放的,只不过我们这里可刻意的把机器码这类非文字编码的数据,特意强调为了二进制数据。
目录文件(directory file:d)
目录是一种特殊的文件,专门用于管理其他文件。
字符特殊文件( character special file: c)
字符设备文件,就是字符设备驱动程序,在上层的表现形式。
当应用程序调用底层字符设备驱动程序,实现对某个字符设备进行读写时,上层就需要对接底层的字符驱动程序,字符设备驱动在上层,会以"字符设备文件"的形式表现出来,我们通过open、read、write去读写字符设备文件,就实现了和底层字符设备驱动程序的交互。
块设备文件(block special file: b):对应块设备(如磁盘等)。
块设备文件,是块设备驱动程序在上层的表现形式。
字符设备与块设备有什么区别?
- 字符设备
以字节为单位来操作数据。
比如:键盘、鼠标、显示器都等是字符设备。
字符设备的驱动程序,就称为"字符设备驱动程序”。 - 块设备
块设备存储的数据量往往非常答,为了提高读写效率,都是以块(1024字节)为单位来操作数据。
比如:电脑硬盘、移动硬盘、u盘等,凡是涉及大量数据存储的,都是以块为单位来操作数据的,都是块设备。块设备的驱动程序,就成为"块设备驱动程序”。
FIFO(fifo:p)
管道文件,用于实现不同进程(程序)之间的通信,管道是os提供的一种纯代码层面的通信机制。
套接字文件( socket: s)
专门用于网络通信的文件。
讲到网络编程时,再来具体介绍。
符号连接(symbolic link: l):
其实就是一种快捷图标,背后指向了另外一个文件。
file 文件
查看文件属性
- 如果查看的是文本文件
会提醒你,它是文字编码格式的文件。 - 如果你查看的是纯二进制文件((机器码)
会提示你,这是一个可以运行的可执行文件。
a.out: ELF 64-bit LSB executable, x86-64,dynamically linked,/lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32,not strippe
- ELF: Linux下可执行文件的格式,windows下的可执行文件是PE格式对
应格式的可执行文件,只能在对应的os下运行。 - 64-bit:文件里面的机器码是64位.的
- LSB:小端序
- executable:明确告诉你,该文件是一个可执行文件·x86-64:运行的是x86架构64位的cpu
- dynamically linked,/ lib64/ ld-linux-x86-64.so.2
程序使用的库是动态链接库,库名叫/lib64/ld-linux-x86-64.so.2 - for GxU/Linux 2.6.32:运行的系统是Linux系统〈ubuntu) , Linux 2.6.32是ubuntu所用Linux内核的版本号
- not strippe:程序没有被瘦身,里面包含有各种用于调试用的信息,当这个程序最终发布时,会使用strip命令为程序瘦身,去除里面的无用信息,让程序变的更小。
获取文件属性
stat、lstat、fstat函数
ls命令其实就是调用了这三个函数中的lstat来实现的,我们可以调用lstat函数来自己实现一个ls命令。
stat函数
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *statbuf);
int lstat(const char *path, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
stat
与lstat
唯一的区别就是stat
获取链接文件属性时会直接获取链接指向的文件的属性,而lstat
会返回链接文件的属性,而fstat
与stat
唯一区别是fstat
使用文件描述符而非文件路径。
- 功能:获取文件的属性信息。
每个文件的属性信息,都是存在块设备上,该文件自己的inode节点(索引节点)空间中。
调用stat函数时,文件系统通过stat给的path,到块设备上索引到该文件的inode节点空间,然后将里面的文件属性信息,读到应用程序的缓存中,如此就得到了文件的属性信息。
文件属性数据中转的过程:
应用缓存<–stat函数提供的内核缓存<–驱动程序的缓存<–块设备上的inode结点 - 返回值
调用成功,返回0,失败返回-1,errno被设置。 - 参数
- path:文件路径名
- statbuf:应用缓存,用于存放读到的文件属性信息
struct stat{
dev_t st_dev;/*块设备号(ID)*/
ino_t st_ino;/*inode结点号,文件属性信息所存inode节点的编号*/
mode_t l st_mode;/*文件类型和文件权限 ls*/
nlink_t st_nlink;/*链接数 ls*/
uid_t st_uid;/*文件所属用户ID ls*/
gid_t st_gid;/*文件所属组ID ls*/
dev_t st_rdev;/*字符设备ID*/
off_t st_size;/*文件大小*/
blksize_t st_blksize;/*系统每次按块IO操作时,块的大小(一般是512或1024)*/
blkcnt_t st_blocks;/*块的索引号*/
/*windows下,文件的时间,同样也分为这三种*/
time_t st_atime;/*最后一次访问时间,read ls*/
time_t st_mtime;/*最后一次修改时间,write*/
time_t st_ctime;/*最后一次属性修改的时间,如权限被修改,文件所有者(属主)被修改*/
};
//其中有ls标记的是ls会显示的内容
st_mode
st_mode 本质就是一个16位二进制数
文件类型 设置位 文件权限****
****
*** *** ***
- 文件类型(定义在<sys/stat.h>)
二进制 | 含义 |
(1000 000000000000) | 代表普通文件 |
(0100 000000000000) | 代表目录文件 |
(0110 000000000000) | 代表块设备文件 |
(0011 000000000000) | 代表字符设备文件 |
(0001 000000000000) | 代表管道文件 |
(1100 000000000000) | 代表套接字文件 |
(1010 000000000000) | 代表符号链接文件 |
- 文件权限
user group other
r w x r w x r w x
0 1 - 0 1 - 0 1 -
st_size
文件长度,只对普通文件、目录及符号链接有意义因为只有普通文件、目录、以及符号链接文件才有实际的数据,有数据才有文件长度。其它的文件在块设备上只存储了文件属性,它们只是挂了一个文件名,以文件的形式进行管理而已,没有实际的数据,所以对于这些文件来说,文件大小是没有意义的。
符号链接文件就是一个快捷键,背后指向了某个文件。
符号链接文件的数据,就是所指向文件的文件名,所以它的文件大小指的就是这个文件名的字符个数。
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path,off_t length);
int ftruncate(int fd, off_t length) ;
函数功能:将文件长度截短为length所指定长度。truncate
利用文件路径名操作,ftruncate
利用文件描述符操作。
length
的大小可以大于文件实际大小,文件截断长度>文件长度时,多余的部分填放空洞。
ls查看到的只是文件的理论大小,但是空洞部分并不占用实际物理存储空间。du命令:查看文件在块设备上,实际占用的物理空间。
在一般文件的情况下,对于普通文件来说,文件数据的理论大小=在块设备上实际占用的空间大小。
但是空洞文件却不是这样的,对于空洞文件来说,文件数据的理论大小〉在块设备上实际占用的空间大小。
空洞文件的意义
打个比方,我承诺给你一亩地,但是你又不是马上就要用满这一亩地,是一点一点来占用的,如果我现在一下子就把一亩地全部给你,但是你要花费很久时间才会把地全用上,在你占满之前,一直有相当部分的空间被闲置不用,显然非常浪费空间资源。
解决办法是,我先承诺说给你一亩地,但是这一亩地先不全部给你,你搬一部分东西过来时,我给你一部分空间,按照这样的方式,直到把1亩地的空间全部给你,在你没有用满一亩地之前,其它的空间我就可以用作它用。
制作空洞文件
- truncate、ftrucate制作
文件截短长度>文件长度时,多余的部分就是空洞。 - 使用lseek制作
将文件读写位置调整到文件尾部之后,然后写点数据,中间空出的部分就是空洞。
文件权限掩码
111 111 111 (0777) 指定权限
&
~000 000 010 (0002)文件权限掩码
111 111 101 (0775) 实际文件权限
文件权限掩码是用来限制其他用户的权限,防止其他用户修改你的文件
每一个进程都有一个文件权限掩码,进程修改只是当前进程的文件权限掩码,对其它进程的文件权限掩码无影响。
如何修改文件权限掩码
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
- 功能:修改文件权限掩码
- 参数
mask:新的文件权限掩码 - 返回值
umask不会调用失败。返回值是旧的文件权限掩码。