Linux系統編程20 文件系統 - 空洞文件 分析 st_size,st_blksize,st_blocks

分析 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);
	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 是一個文件的唯一的標識,相當於身份證號

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