分析 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; / * tamaño total, en bytes /
tamaño de archivo , en bytes blksize_t st_blksize; / blocksize para E / S del sistema de archivos / tamaño de bloque del sistema
blkcnt_t st_blocks; / número de 512B bloques asignados * / número de bloques asignados por el archivo
Mucha gente piensa
st_size = st_blocks * st_blksize
Sin embargo, es incorrecto. Esta es la idea del sistema Windows. En Windows, el tamaño de un archivo es en realidad el tamaño de un archivo en el disco. Pero este no es el caso en el sistema UNIX. Esta diferencia está relacionada con el sistema de archivos. En el sistema UNIX, el valor st_size es solo un atributo de un archivo, y st_blksize * st_blocks realmente determina el tamaño del espacio en disco ocupado por el archivo.
Experimento 1. El archivo vacío demuestra que el tamaño del archivo en el sistema UNIX no es igual al espacio en disco ocupado por el archivo.
#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$
Se encuentra que el tamaño no es 5G, lo que indica que efectivamente se ha producido el desbordamiento "desbordamiento de enteros" en la advertencia. El motivo del desbordamiento de enteros es que en el programa es igual que en materias como matemáticas y física. Los valores numéricos sin unidades no tienen sentido, por lo que el código
lseek(fd, 5* 1024 *1024 *1024-1, SEEK_SET);
El valor en, debido a que no hay una unidad marcada, el sistema lo considerará como un entero con signo por defecto, por lo que los datos se desbordarán aquí, por lo que necesitamos ampliar el tipo de datos aquí,
cambio:
#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$
El tamaño del tamaño aquí es correcto, Tamaño: 5368709120, y se encuentra que el espacio en disco ocupado por este archivo de tamaño 5G en el entorno actual es 8 * 512 4k. Esto muestra que el tamaño del archivo en el sistema UNIX y el espacio en disco ocupado por el archivo no son iguales.
Inode: 12849443 es la identificación única de un archivo, equivalente al número de identificación