Eu tenho um trabalho de faculdade onde eu tenho que criar um disco RAM.
Disseram-me para fazer um programa em C que escreve várias vezes em um arquivo colocado dentro do disco RAM e depois fazer o mesmo em um arquivo colocado no disco rígido para comparar as velocidades de gravação.
Recebi o seguinte script para criar o disco RAM:
#!/bin/bash
# RAM Disk
ROOTUSER_NAME=root
MOUNTPT=/tmp/ramdisk
SIZE=2024 # 2K blocs
BLOCKSIZE=1024 # block size: 1K (1024 bytes)
DEVICE=/dev/ram0 # First RAM Disk
username=`id -nu`
[ "$username" != "$ROOTUSER_NAME" ] && echo "not authorised" && exit 1
[ ! -d "$MOUNTPT" ] && mkdir $MOUNTPT
dd if=/dev/zero of=$DEVICE count=$SIZE bs=$BLOCKSIZE
/sbin/mkfs -t ext4 $DEVICE
mount $DEVICE $MOUNTPT # the mount
chmod 777 $MOUNTPT
echo $MOUNTPT " ready"
exit 0
O problema aqui é que minha máquina parece não ter /dev/ram0
no /dev
diretório; esta é a saída de ls /dev
:
ferran@amsa:~/Desktop$ ls /dev
autofs lightnvm sda tty22 tty5 ttyS18 vcs3
block log sda1 tty23 tty50 ttyS19 vcs4
bsg loop0 sda2 tty24 tty51 ttyS2 vcs5
btrfs-control loop1 sda3 tty25 tty52 ttyS20 vcs6
bus loop2 sda5 tty26 tty53 ttyS21 vcsa
cdrom loop3 sg0 tty27 tty54 ttyS22 vcsa1
cdrw loop4 sg1 tty28 tty55 ttyS23 vcsa2
char loop5 shm tty29 tty56 ttyS24 vcsa3
console loop6 snapshot tty3 tty57 ttyS25 vcsa4
core loop7 snd tty30 tty58 ttyS26 vcsa5
cpu loop8 sr0 tty31 tty59 ttyS27 vcsa6
cpu_dma_latency loop9 stderr tty32 tty6 ttyS28 vcsu
cuse loop-control stdin tty33 tty60 ttyS29 vcsu1
disk mapper stdout tty34 tty61 ttyS3 vcsu2
dma_heap mcelog tty tty35 tty62 ttyS30 vcsu3
dmmidi mem tty0 tty36 tty63 ttyS31 vcsu4
dri midi tty1 tty37 tty7 ttyS4 vcsu5
dvd mqueue tty10 tty38 tty8 ttyS5 vcsu6
ecryptfs net tty11 tty39 tty9 ttyS6 vfio
fb0 null tty12 tty4 ttyprintk ttyS7 vga_arbiter
fd nvram tty13 tty40 ttyS0 ttyS8 vhci
full port tty14 tty41 ttyS1 ttyS9 vhost-net
fuse ppp tty15 tty42 ttyS10 udmabuf vhost-vsock
hidraw0 psaux tty16 tty43 ttyS11 uhid vmci
hpet ptmx tty17 tty44 ttyS12 uinput zero
hugepages pts tty18 tty45 ttyS13 urandom zfs
hwrng random tty19 tty46 ttyS14 userio
initctl rfkill tty2 tty47 ttyS15 vcs
input rtc tty20 tty48 ttyS16 vcs1
kmsg rtc0 tty21 tty49 ttyS17 vcs2
E esta é a saída de fdisk -l
:
ferran@amsa:~/Desktop$ sudo fdisk -l
[sudo] password for ferran:
Disk /dev/loop0: 4 KiB, 4096 bytes, 8 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop1: 55,45 MiB, 58130432 bytes, 113536 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop2: 65,22 MiB, 68378624 bytes, 133552 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop3: 55,51 MiB, 58191872 bytes, 113656 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop4: 65,1 MiB, 68259840 bytes, 133320 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop5: 50,98 MiB, 53432320 bytes, 104360 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop6: 32,3 MiB, 33865728 bytes, 66144 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop7: 32,45 MiB, 34017280 bytes, 66440 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sda: 100 GiB, 107374182400 bytes, 209715200 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x70d3f840
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 117186559 117184512 55,9G 83 Linux
/dev/sda2 117188606 132810751 15622146 7,5G 5 Extended
/dev/sda3 132810752 132812799 2048 1M 82 Linux swap / Solaris
/dev/sda5 117188608 132810751 15622144 7,5G 82 Linux swap / Solaris
Partition table entries are not in disk order.
Disk /dev/loop8: 219 MiB, 229638144 bytes, 448512 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Para o teste de velocidade de gravação, uso o seguinte programa C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10000000
int main(int argc, char *argv[]){
char *c = /* This is compiled into one long string, with no newlines. */
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, "
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
"Ut enim ad minim veniam, quis nostrud exercitation "
"ullamco laboris nisi ut aliquip ex ea commodo consequat. "
"Duis aute irure dolor in reprehenderit in voluptate velit esse "
"cillum dolore eu fugiat nulla pariatur. Excepteur sint "
"occaecat cupidatat non proident, sunt in culpa qui "
"officia deserunt mollit anim id est laborum.";
FILE *fp;
fp = fopen(argv[1],"w");
for(int i=0; i < MAX; i++){
fputs(c,fp);
fseek(fp, 0, SEEK_SET);
}
fclose(fp);
}
Eu chamo duas vezes:
./writeTest ~/Desktop/test
./writeTest /tmp/ramdisk/test
E os resultados não são muito convincentes, porque o arquivo do disco RAM leva 8s e o arquivo do disco rígido leva 11s, o que não parece ser a melhoria que eu deveria obter, certo?
Quando executo o script bash, /dev/ram0
é criado, mas não sei se é isso que deveria acontecer e a melhoria na velocidade de gravação é a esperada ou se já deveria ter /dev/ram0
criado no meu /dev
diretório.
Qualquer ajuda seria apreciada.
Editar 1:
Fiz algumas alterações de acordo com o que @user1686 disse. Primeiro, carreguei o módulo necessário modprobe brd
e, em seguida, todos apareceram./dev/ram#
Então, tentei melhorar meu programa em C para reduzir as seek
chamadas, mesmo sabendo que ainda não é a melhor ideia testar a velocidade de gravação dessa maneira, me disseram para fazer isso usando um programa em C (talvez o objetivo fosse apenas que vimos uma melhoria ao escrever na RAM em vez de no disco rígido, e não que soubéssemos o incremento exato nas velocidades de gravação).
Para reduzir as seek
chamadas, aumentei o RAM Disk (passou de 2 MB para 32 MB) e, em vez de chamar seek
cada iteração do loop, aproximei quantos loops são necessários para gravar quase 32 MB e, em seguida, todas as MAX
iterações Eu chamo seek
, e finalmente repito os LOOPS
tempos de loop externo.
O programa fica assim:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOOPS 50
#define MAX 70000
int main(int argc, char *argv[]){
char *c = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor inci";
FILE *fp;
fp = fopen(argv[1],"w");
for(int i=0; i < LOOPS; i++){
for(int i=0; i < MAX; i++){
fputs(c,fp);
}
fseek(fp, 0, SEEK_SET);
}
fclose(fp);
}
Com esta nova versão e com o disco rígido principal e o disco RAM montados com a sync
opção consigo obter uma melhoria de 30x mais rápido, e parece aumentar à medida que aumento o valor de LOOPS
.
Sim e não, mas principalmente não.
O Linux realmente tem um driver "ramdisk" que pode fornecer
/dev/ram#
dispositivos e pode estar disponível em seu sistema, mas geralmente não é carregado por padrão e esses nós de dispositivo não existirão a menos que você carregue esse driver primeiro. Para fazer isso, insira obrd.ko
módulo do kernel e você deve obter 8 ou 16ram
dispositivos:Se o driver não foi carregado e seu script foi cegamente criado /dev/ram0 usando
dd
, então ele não criou um ramdisk dessa maneira – ele criou um arquivo. (Você deve remover isso antes de carregar o driver "brd".)No entanto, por sorte, seu script ainda acaba atingindo o objetivo de "melhores velocidades de gravação" mesmo sem /dev/ram0 estar disponível. Isso ocorre porque na maioria dos sistemas Linux, o /dev inteiro não é armazenado no disco físico, mas possui um sistema de
tmpfs
arquivos montado nele 1 .Um "tmpfs" já está na memória - é como usar um ramdisk, exceto que os ramdisks são de tamanho fixo e precisam ser combinados com outro sistema de arquivos, enquanto um tmpfs é dimensionado dinamicamente por conta própria.
Portanto, qualquer novo arquivo que você criar em /dev – e às vezes em /tmp, também 2 – será armazenado completamente na memória. Mesmo que seu script não tenha estabelecido um "ramdisk" de estilo antigo real, mas meramente criado um arquivo normal 3 chamado "/dev/ram0", o fato de estar armazenado em tmpfs significa que você ainda obtém o aumento de velocidade esperado. 4
(Mas você teria conseguido isso apontando seu programa ./writeTest diretamente para /dev/testfile também.)
Então, resumindo, enquanto o Linux tem ramdisks, o tmpfs é o substituto moderno dos ramdisks em quase todas as situações. Você não precisa decidir sobre seu tamanho, ou explicitamente "mkfs" um sistema de arquivos - apenas monte um tmpfs onde você precisar:
1 (Na maioria dos sistemas Linux hoje em dia, /dev usa "devtmpfs", uma variante tmpfs especial onde os nós de dispositivo automaticamente surgem assim que um driver reconhece um dispositivo; por exemplo, assim que você carrega o driver 'brd', /dev/ ram0 aparecerá inteiramente por conta própria. Mas fora isso, ele se comporta como um tmpfs regular.)
2 (Use
findmnt
oumount
para verificar se sua distribuição realmente monta um tmpfs em /tmp ou não.)3 (E mesmo sendo um arquivo, você ainda pode montá-lo como um disco porque o
mount
comando foi atualizado em 2011 para configurar automaticamente um "dispositivo de loop" sem precisar-o loop
ser especificado.)Uma razão pela qual você vê os dois testes sendo executados com a mesma rapidez é que as gravações são armazenadas em buffer na memória – seu programa não espera que cada gravação seja totalmente confirmada no disco antes de continuar com a próxima; em vez disso, tudo é gravado no disco em rajadas curtas.
(E porque seu programa busca de volta para 0 e sobrescreve os dados por completo, provavelmente não há muito que precise ser movido do buffer para o disco.)
A outra razão pela qual você vê os dois testes rodando rápido é porque os HDDs modernos são bastante rápidos e os SSDs ainda mais. Enquanto isso, se sua tarefa pede para você configurar um ramdisk, isso me faz pensar que foi escrito em 1999 com a expectativa de velocidades de disco em dezenas de MB/s.