furos de arquivo (Perfuradas) e sua aplicação
http: // blog.jcix.top/2018-09-28/hole_punching/
O TOC [ dobrar ]
O comprimento de um arquivo e sua quantidade real de espaço em disco é provável que seja diferente, que envolve principalmente o conceito de arquivos esparsos (arquivo esparso), e os furos de arquivo (orifício de perfuração) são. Estas duas características necessárias para suportar o sistema de sistema operacional e arquivos, Linux é atualmente ext4, outros sistemas de arquivos XFS e suporte a esses recursos.
arquivos esparsos (arquivo esparso)
Saiba arquivo coeficiente mais intuitiva exemplo é a criação de um arquivo e, em seguida, usar lseek a um, a escrever algo real maior compensado neste offset, em seguida, a quantidade real de espaço em disco é pequeno, mas o tamanho do arquivo, mas relativamente grande. Por exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include <fcntl.h>
#include <assert.h>
int main()
{
// 打开两个文件file_normal和file_sparse
int fd = open("file_normal", O_RDWR|O_CREAT, 0755);
int fd_sparse = open("file_sparse", O_RDWR|O_CREAT, 0755);
assert(fd != -1);
// 一个从0写入3个字节,一个从1000偏移写入3个字节
lseek(fd, 0, SEEK_SET);
lseek(fd_sparse, 100000, SEEK_SET);
write(fd, "ABCDEFG", 3);
write(fd_sparse, "ABCDEFG", 3);
close(fd);
close(fd_sparse);
return 0;
}
|
ls
A -s
opção para imprimir o espaço em disco ocupado pelo arquivo na primeira coluna:
1
2
3
4
5
|
zjc@~$ ./sparse_file
zjc@~$ ls -lsh file*
4.0K -rwxr-xr-x. 1 zjc zjc 3 9月 28 11:45 file_normal
4.0K -rwxr-xr-x. 1 zjc zjc 98K 9月 28 11:45 file_sparse
|
Pode ser visto, o comprimento dos dois documentos são 3 bytes e 98K bytes, mas o espaço em disco é o mesmo, ou seja, a menor unidade de armazenamento do sistema de arquivos 4 KB. Isso ocorre porque não há uso file_sparse blocos de disco 100.000 antes de offset.
furos de arquivo (Perfuradas)
Exemplos superior ficheiro disperso é escrito por um deslocamento no arquivo vazio obtido de 3 bytes. E em alguns casos, iniciar um arquivo não é escassa, ele ocupou uma série de espaço em disco, em seguida, se algum do arquivo de dados no meio de nenhum uso, temos de reduzir o espaço em disco ocupado por arquivos, você só pode arquivo furos (perfuração) caminho de arquivo não-esparsos em um arquivo esparso.
O método específico é pelo fallocate
sistema de chamada. Através man 2 fallocate
, podemos ver o fallocate
protótipo chamada é a seguinte: [1]
1
2
3
4
5
|
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include
int fallocate(int fd, int mode, off_t offset, off_t len);
|
uso geral desta chamada pode ser chamado de "alocação": designado mode
como 0, em seguida, [vai apresentar offset
, offset+len
) para escrever a área de conteúdo é zero.
Vamos utilizá-lo para fazer tocas arquivo, essa utilização pode ser correspondentemente chamados "deallocation": Nós especificamos mode
a FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE
este tempo [ offset
, offset+len
) área do bloco será "buracos", a fim de reduzir o uso do disco de arquivo.
É por causa do fallocate
modo de "alocação", as chamadas do sistema para um arquivo cheio de zero, para que possamos usar apenas um presente para chamar primeiro "alocação", então a função arquivo de teste perfuração "deallocation".
Nota : Embora a página homem afirmou contém apenas fcntl.h
pode ser, mas nos meus CentOS 7 sistemas também precisa incluir linux/falloc.h
o contrário, o seguinte erro de compilação:
1
2
3
4
5
6
7
8
|
hole_punching.c: In function 'main':
hole_punching.c:33:25: error: 'FALLOC_FL_PUNCH_HOLE' undeclared (first use in this function)
ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, 409600, 1024000);
^
hole_punching.c:33:25: note: each undeclared identifier is reported only once for each function it appears in
hole_punching.c:33:46: error: 'FALLOC_FL_KEEP_SIZE' undeclared (first use in this function)
ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, 409600, 1024000);
|
Nossas rotinas de teste são as seguintes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
// 注意在CentOS 7中还需要包含linux/falloc.h:
#include <linux/falloc.h>
#include <sys/stat.h>
#include <assert.h>
int main()
{
off_t offset;
int ret;
struct stat st;
// do allocation
printf("===== Allocation =====\n");
int fd = open("./file_nohole", O_RDWR|O_CREAT, 0755);
assert(fd != -1);
ret = fallocate(fd, 0 , 0, 1024000);
assert(ret == 0);
offset = lseek(fd, 0, SEEK_END);
printf("SEEK_END offset:\t %d\n", offset);
fstat(fd, &st);
printf("fstat:\t\t\t file size %d, %d allocated (%d Bytes).\n",
st.st_size, st.st_blocks, st.st_blocks * 512);
close(fd);
// do dedallocation
printf("==== Deallocation ====\n");
fd = open("./file_withhole", O_RDWR|O_CREAT, 0755);
assert(fd != -1);
ret = fallocate(fd, 0 , 0, 1024000);
ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, 409600, 1024000);
assert(ret == 0);
offset = lseek(fd, 0, SEEK_END);
printf("SEEK_END offset:\t %d\n", offset);
fstat(fd, &st);
printf("fstat:\t\t\t file size %d, %d allocated (%d Bytes).\n",
st.st_size, st.st_blocks, st.st_blocks * 512);
close(fd);
return 0;
}
|
O resultado:
1
2
3
4
5
6
7
8
9
10
11
12
|
zjc@~$ ./hole_punching
===== Allocation =====
SEEK_END offset: 1024000
fstat: file size 1024000, 2000 allocated (1024000 Bytes).
==== Deallocation ====
SEEK_END offset: 1024000
fstat: file size 1024000, 800 allocated (409600 Bytes).
zjc@~$ ls -lsh file*
1000K -rwxr-xr-x. 1 zjc zjc 1000K Sep 28 11:59 file_nohole
400K -rwxr-xr-x. 1 zjc zjc 1000K Sep 28 11:59 file_withhole
|
Você pode ver se ele é usado struct stat
no st_blocks
campo ou ls
a -s
opção de nos dizer "file_withhole" Este arquivo foi atingido um buraco de 600 KB (1000 K -> 400 K) .
Buracos nas aplicações de compressão de páginas MySQL
página em meus artigos anteriores analisaram MySQL InnoDB compressão transparente [2] , este mecanismo de compressão é escavando baseado em arquivo. Ensaio blog pode olhar em detalhe, nas instruções simples abaixo:
InnoDB以InnoDB页为单元进行存储,对于一般的情况,InnoDB页默认为16KB,文件系统默认为4KB。当InnoDB要存储一个页时,会对16KB进行压缩,压缩后大小为12KB,那么12KB到16KB之间的内容会首先被填零,然后用fallocate
作“deallocation”打洞,这样额外的一个文件系统块就因压缩而被节约了;同样,若压缩后的页小于8 KB或小于4 KB,那么分别就可以节约8 KB 或 12 KB。
[1] fallocate – manipulate file space, http://man7.org/linux/man-pages/man2/fallocate.2.html
[2] MySQL InnoDB透明页压缩的简单分析, http://blog.jcix.top/2017-04-16/transparent_page_compression/