分析 off_t st_size 、blksize_t st_blksize, blkcnt_t st_blocks;
struct stat {
dev_t st_dev; /* ID of device containing file */文件所在设备的ID
ino_t st_ino; /* inode number */节点号
mode_t st_mode; /* protection */文件的类型和存取的权限
nlink_t st_nlink; /* number of hard links */链向此文件的连接数(硬连接)
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */设备ID号,针对设备文件
off_t st_size; /* total size, in bytes */文件大小,字节为单位
blksize_t st_blksize; /* blocksize for filesystem I/O */系统块的大小
blkcnt_t st_blocks; /* number of 512B blocks allocated */文件所占块数
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* time of last access */最近存取时间
struct timespec st_mtim; /* time of last modification */最近修改时间
struct timespec st_ctim; /* time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
off_t st_size; /* total size, in bytes /文件大小,字节为单位
blksize_t st_blksize; / blocksize for filesystem I/O /系统块的大小
blkcnt_t st_blocks; / number of 512B blocks allocated */文件所占块数
很多人 就会以为
st_size = st_blocks * st_blksize
但是,是不正确的,这是Windows 系统的思想,在Windows 中,一个文件的size 值,实际上就是一个文件在磁盘中所占用的大小。但是在UNIX系统中 不是这样的,这种差异和文件系统有关,在UNIX系统中,st_size 值 只是一个文件的属性,而 st_blksize*st_blocks 才真正决定了该文件所占磁盘空间的大小。
实验1 ,空洞文件 证明 UNIX系统中 文件的大小和 文件所占用磁盘空间 不是对等的。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
if(argc < 2)
{
fprintf(stderr,"Usage......\n");
exit(1);
}
fd = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0600);
if(fd < 0)
{
perror("open()");
exit(1);
}
//生成空洞文件 5G
lseek(fd, 5* 1024 *1024 *1024-1, SEEK_SET);
write(fd,"",1);//执行一次系统调用 尾部写0,不然当前文件不占空间
close(fd);
exit(0);
}
mhr@ubuntu:~/work/linux/wenjianxitong/20$ gcc big.c
big.c: In function ‘main’:
big.c:25:26: warning: integer overflow in expression [-Woverflow]
lseek(fd, 5* 1024 *1024 *1024-1, SEEK_SET);
^
mhr@ubuntu:~/work/linux/wenjianxitong/20$
mhr@ubuntu:~/work/linux/wenjianxitong/20$
mhr@ubuntu:~/work/linux/wenjianxitong/20$ ./a.out bigfile
mhr@ubuntu:~/work/linux/wenjianxitong/20$
mhr@ubuntu:~/work/linux/wenjianxitong/20$ stat bigfile
File: 'bigfile'
Size: 1073741824 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 12849444 Links: 1
Access: (0600/-rw-------) Uid: ( 1000/ mhr) Gid: ( 1000/ mhr)
Access: 2020-05-04 08:58:16.199732985 -0700
Modify: 2020-05-04 08:58:35.151295622 -0700
Change: 2020-05-04 08:58:35.151295622 -0700
Birth: -
mhr@ubuntu:~/work/linux/wenjianxitong/20$
发现 Size 大小不是5G,说明警告中的 溢出 “整数溢出” 确实发生了。发生整数溢出的原因在于,在程序中,和数学 物理 之类学科是一样的,没有单位的数值是没有意义的,所以 代码
lseek(fd, 5* 1024 *1024 *1024-1, SEEK_SET);
中的数值,由于没有标出单位,系统会默认认为是有符号整形,所以数据这里会溢出,所以我们需要在这里将数据类型放大,
改:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
if(argc < 2)
{
fprintf(stderr,"Usage......\n");
exit(1);
}
fd = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0600);
if(fd < 0)
{
perror("open()");
exit(1);
}
//生成空洞文件 5G
lseek(fd, 5LL* 1024LL *1024LL *1024LL-1LL, SEEK_SET);
write(fd,"",1);
close(fd);
exit(0);
}
mhr@ubuntu:~/work/linux/wenjianxitong/20$
mhr@ubuntu:~/work/linux/wenjianxitong/20$ gcc big.c
mhr@ubuntu:~/work/linux/wenjianxitong/20$ ./a.out bigfile
mhr@ubuntu:~/work/linux/wenjianxitong/20$ stat bigfile
File: 'bigfile'
Size: 5368709120 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 12849444 Links: 1
Access: (0600/-rw-------) Uid: ( 1000/ mhr) Gid: ( 1000/ mhr)
Access: 2020-05-04 08:58:16.199732985 -0700
Modify: 2020-05-04 09:04:27.883813275 -0700
Change: 2020-05-04 09:04:27.883813275 -0700
Birth: -
mhr@ubuntu:~/work/linux/wenjianxitong/20$
这里的 size 的大小是正确的,Size: 5368709120 ,而发现这个5G大小的文件,在当前环境下所占用的磁盘空间是 8*512 4k 的大小。这里就说明了 UNIX系统中 文件的大小和 文件所占用磁盘空间 不是对等的。
Inode: 12849443 是一个文件的唯一的标识,相当于身份证号