No Linux, uma execução finalizada de um comando como cp
ou dd
não significa que os dados foram gravados no dispositivo. É necessário, por exemplo, chamar sync
ou chamar a função "Remover com segurança" ou "Ejetar" na unidade.
Qual é a filosofia por trás dessa abordagem? Por que os dados não são gravados de uma só vez? Não há perigo de que a gravação falhe devido a um erro de E / S?
kernel
drivers
io
unix-philosophy
marmistrz
fonte
fonte
Respostas:
Eficiência (melhor uso das características do disco) e desempenho (permite que o aplicativo continue imediatamente após uma gravação).
A principal vantagem é que o sistema operacional é livre para reordenar e mesclar operações de gravação contíguas para melhorar o uso da largura de banda (menos operações e menos buscas). Os discos rígidos têm melhor desempenho quando um pequeno número de operações grandes é solicitado, enquanto os aplicativos tendem a precisar de um grande número de operações pequenas. Outra otimização clara é que o sistema operacional também pode remover tudo, exceto a última gravação, quando o mesmo bloco é gravado várias vezes em um curto período de tempo, ou até mesmo remover algumas gravações todas juntas, se o arquivo afetado tiver sido removido nesse meio tempo.
Essas gravações assíncronas são feitas após o
write
retorno da chamada do sistema. Essa é a segunda e mais visível vantagem do usuário. Gravações assíncronas aceleram os aplicativos, pois eles são livres para continuar seu trabalho sem aguardar que os dados estejam realmente em disco. O mesmo tipo de buffer / cache também é implementado para operações de leitura em que blocos de leitura recentes ou frequentemente são retidos na memória em vez de serem lidos novamente a partir do disco.Não necessariamente. Isso depende do sistema de arquivos usado e da redundância em vigor. Um erro de E / S pode ser inofensivo se os dados puderem ser salvos em outro local. Sistemas de arquivos modernos como o ZFS recuperam automaticamente os blocos de disco defeituosos. Observe também que os erros de E / S não travam sistemas operacionais modernos. Se eles ocorrerem durante o acesso aos dados, eles são simplesmente relatados ao aplicativo afetado. Se eles ocorrerem durante o acesso aos metadados estruturais e colocarem o sistema de arquivos em risco, poderá ser remontado somente leitura ou tornado inacessível.
Também há um pequeno risco de perda de dados no caso de uma falha do sistema operacional, falta de energia ou falha de hardware. Esse é o motivo pelo qual aplicativos que precisam ter 100% de certeza de que os dados estão no disco (por exemplo, bancos de dados / aplicativos financeiros) estão fazendo gravações síncronas menos eficientes, mas mais seguras. Para reduzir o impacto no desempenho, muitos aplicativos ainda usam gravações assíncronas, mas eventualmente os sincronizam quando o usuário salva explicitamente um arquivo (por exemplo, vim, processadores de texto).
Por outro lado, uma grande maioria de usuários e aplicativos não precisa nem se importa com a segurança que as gravações síncronas fornecem. Se houver uma falha ou falta de energia, o único risco é perder na pior dos casos os últimos 30 segundos de dados. A menos que exista uma transação financeira envolvida ou algo semelhante que implique um custo muito superior a 30 segundos, o enorme ganho no desempenho (que não é uma ilusão, mas muito real) gravações assíncronas está permitindo superar em grande parte o risco.
Por fim, gravações síncronas não são suficientes para proteger os dados gravados. Se seu aplicativo realmente precisar garantir que seus dados não sejam perdidos, aconteça o que acontecer, a replicação de dados em vários discos e em várias localizações geográficas deve ser implementada para resistir a desastres como incêndio, inundação etc.
fonte
Ele simplesmente fornece uma ilusão de velocidade para programas que não precisam esperar até que a gravação seja concluída. Monte seus sistemas de arquivos no modo de sincronização (que fornece suas gravações instantâneas) e veja como tudo está lento.
Às vezes, os arquivos existem apenas temporariamente ... um programa faz um pouco de trabalho e exclui o arquivo logo após o término do trabalho. Se você atrasou essas gravações, talvez nunca as tenha escrito antes.
Ah, absolutamente. Nesse caso, geralmente todo o sistema de arquivos entra no modo somente leitura e tudo é horrível. Mas isso raramente acontece, não faz sentido perder as vantagens de desempenho em geral.
fonte
A E / S em buffer e assíncrona estava em uso antes do Linux e mesmo antes do Unix. O Unix tinha, e todos os seus rebentos também.
Aqui está o que Ritchie e Thompson escreveram em seu artigo do CACM The UNIX Time-Sharing System :
Na sua pergunta, você também escreveu:
Sim, a gravação pode falhar e o programa talvez nunca saiba disso. Embora nunca seja uma coisa boa, os efeitos disso podem ser minimizados nos casos em que um erro de E / S gera pânico no sistema (em alguns SOs isso é configurável - em vez de entrar em pânico, o sistema pode continuar em execução, mas o sistema de arquivos afetado é somente leitura desmontada ou montada). Os usuários podem ser notificados de que os dados nesse sistema de arquivos são suspeitos. E uma unidade de disco pode ser monitorada proativamente para ver se sua lista de defeitos crescentes está aumentando rapidamente, o que é uma indicação de que a unidade está falhando.
O BSD adicionou a
fsync
chamada do sistema para que um programa pudesse ter certeza de que seus dados de arquivo foram completamente gravados no disco antes de continuar, e os sistemas Unix subsequentes forneceram opções para realizar gravações síncronas. O GNU dd tem uma opçãoconv=fsync
para garantir que todos os dados foram gravados antes da saída do comando. É útil ao gravar em drives flash removíveis lentos, onde os dados armazenados em buffer podem levar alguns minutos para serem gravados.Outra fonte de corrupção de arquivos é o desligamento repentino do sistema, por exemplo, por perda de energia. Praticamente todos os sistemas atuais suportam uma flag limpa / suja em seus sistemas de arquivos. O sinalizador é definido como limpo quando não há mais dados a serem gravados e o sistema de arquivos está prestes a ser desmontado, normalmente durante o desligamento do sistema ou por chamada manual
umount
. Os sistemas geralmente serão executadosfsck
após a reinicialização se detectar que os sistemas de arquivos não foram desligados corretamente.fonte
Muitas boas respostas, mas deixe-me acrescentar mais uma coisa ... Lembre-se de que o Unix é um sistema com vários processos e multiusuários; portanto, muitos usuários potencialmente estariam tentando realizar operações de arquivo (especialmente gravações) no (quase) mesmo tempo. Com discos rígidos lentos antigos - talvez montados na rede - isso não apenas levaria tempo (pelo qual os programas basicamente travam e os usuários precisam esperar), mas causa muito movimento da cabeça de leitura / gravação do disco para frente e para trás.
Em vez disso, os arquivos que aguardavam gravação foram mantidos na memória por um tempo e classificados depois de onde deveriam terminar no disco ... e quando o buffer estava cheio - ou o daemon de sincronização de disco aguardou o número necessário de segundos (acho que geralmente eram cerca de 30 segundos) - todo o buffer foi gravado no disco "em ordem", com a cabeça de gravação apenas tendo que fazer um movimento contínuo de varredura, gravando os arquivos no disco como foi ... em vez de pular por todo o lugar.
De acordo com os discos rápidos de hoje - para não mencionar os dispositivos de estado sólido - o ganho é muito menor ... espeicamente em um sistema linux doméstico, onde há apenas um usuário trabalhando por vez e apenas com alguns programas.
De qualquer forma, a combinação de antecipar leituras lendo (no cache / buffer) mais do que foi solicitado - e classificando dados aguardando para serem gravados, para que pudessem ser gravados em "um movimento" - foi realmente uma boa ideia tempo, especialmente em sistemas com muita leitura e escrita por muitos usuários.
fonte
Não é específico para o Linux e é chamado de cache de página (que o Linux faz muito bem). Veja também http://linuxatemyram.com/ ; portanto, se um arquivo for gravado, leia novamente alguns segundos depois, muitas vezes nenhuma E / S de disco é necessária.
A principal vantagem é que, em muitos sistemas, há muita RAM e algumas podem ser usadas como cache pelo kernel. Portanto, algumas operações de arquivos podem tirar proveito desse cache. Além disso, o tempo de E / S do disco é muito mais lento (normalmente milhares de vezes para SDD e quase um milhão de vezes mais lento para discos rígidos mecânicos) que a RAM.
O código do aplicativo pode dar dicas sobre esse cache: veja, por exemplo, posix_fadvise (2) e madvise (2)
fonte
Os pratos giratórios são mais lentos que a RAM. Usamos o cache de leituras / gravações para 'ocultar' esse fato.
O aspecto útil da gravação de E / S é que ela não exige que a E / S de disco aconteça imediatamente - ao contrário de uma leitura, na qual você não pode retornar dados ao usuário até que a leitura seja concluída no disco.
Assim, as gravações operam com uma restrição de tempo flexível - desde que nossa taxa de transferência sustentada não exceda a do nosso disco, podemos ocultar muitas das penalidades de desempenho em um cache de gravação.
E precisamos escrever em cache - os discos giratórios são muito lentos comparativamente. Mas, para fazer isso, os tipos modernos de RAID têm uma penalidade significativa na operação.
Um RAID 6, por exemplo, para concluir uma E / S de gravação deve:
Assim, cada gravação é na verdade 6 operações de E / S - e, particularmente, quando você tem discos lentos como grandes unidades SATA, isso fica extremamente caro.
Mas há uma solução fácil e agradável - escreva coalescente. Se você pode criar uma gravação de 'faixa completa' em um buffer, não precisa ler a paridade do disco - você pode calculá-la com base no que tem na memória.
É muito desejável fazer isso, porque você não tem mais amplificação de gravação. Na verdade, você pode acabar com uma penalidade de gravação menor que o RAID 1 + 0.
Considerar:
Eixos RAID 6, 8 + 2 - 10.
8 blocos de dados consecutivos para gravação - calcule a paridade no cache e grave um bloco em cada disco. 10 gravações por 8, significa uma penalidade de gravação de 1,25. 10 discos de RAID 1 + 0 ainda têm uma penalidade de gravação de 2 (porque você precisa gravar em cada subespelho). Portanto, nesse cenário, você pode realmente fazer o RAID 6 ter um desempenho melhor que o RAID1 + 0. No uso no mundo real, você obtém um pouco mais de um perfil de IO misto.
Portanto, o cache de gravação faz uma enorme diferença no desempenho percebido dos conjuntos RAID - você pode gravar na velocidade da RAM e tem uma penalidade baixa de gravação - melhorando o rendimento sustentado, se o fizer.
Caso contrário, você sofre o desempenho lento do SATA, mas multiplique por 6 e adicione alguma contenção. Seu SATA RAID-6 de 10 vias sem cache de gravação seria um pouco mais rápido que uma única unidade sem RAID ... mas não muito.
Você se arrisca - como observa - a perda de energia significa perda de dados. Você pode atenuar isso realizando ciclos de liberação de cache, backup de bateria do cache ou usando SSD ou outros caches não voláteis.
fonte
Nenhuma das outras respostas mencionadas atrasou a alocação . Todos os XFS, ext4, BTRFS e ZFS o utilizam. O XFS está usando-o desde antes da ext4, então vou usá-lo como exemplo:
O XFS nem decide onde colocar os dados até a gravação. A alocação atrasada fornece ao alocador muito mais informações para basear suas decisões. Quando um arquivo está sendo gravado pela primeira vez, não há como saber se ele será um arquivo de 4k ou um arquivo de 1G e ainda em crescimento. Se houver 10 G de espaço livre contíguo em algum lugar, colocar o arquivo 4k no início não é bom. Colocar o arquivo grande no início de um grande espaço livre reduz a fragmentação.
fonte
Todas as outras respostas aqui estão no mínimo corretas para o caso normal, e eu recomendaria a leitura de qualquer uma delas antes da minha, mas você mencionou dd e dd tem um caso de uso típico que pode não envolver cache de gravação. O cache de gravação é implementado principalmente no nível do sistema de arquivos. Os dispositivos brutos normalmente não fazem cache de gravação (vários drivers de dispositivo, como raid ou lvm, são outra bola de cera). Como o dd é frequentemente usado com dispositivos de bloco bruto, ele fornece as opções bs e relacionadas para permitir gravações grandes para melhor desempenho em dispositivos brutos. Isso não é tão útil quando os dois pontos de extremidade são arquivos regulares (embora gravações grandes usem menos chamadas do sistema nesse caso). O outro local comum em que isso é particularmente visível é o pacote mtools, que é uma implementação do sistema de arquivos fatiados do espaço do usuário. o uso de mtools com uma unidade de disquete sempre parece incrivelmente lento, pois as ferramentas são completamente síncronas e as unidades de disquete são incrivelmente lentas. Montar o disquete e usar o sistema de arquivos com gordura do kernel é muito mais responsivo, exceto por umount que é síncrono (e muito importante para que seja assim, para evitar a perda de dados, especialmente para dispositivos removíveis como disquetes). Existem apenas alguns outros programas que eu sei que são usados regularmente com dispositivos brutos, como bancos de dados especialmente configurados (que implementam seu próprio cache de gravação), tar e dispositivos especiais e ferramentas de sistema de arquivos como chdsk, mkfs e mt. Montar o disquete e usar o sistema de arquivos com gordura do kernel é muito mais responsivo, exceto por umount que é síncrono (e muito importante para que seja assim, para evitar a perda de dados, especialmente para dispositivos removíveis como disquetes). Existem apenas alguns outros programas que eu sei que são usados regularmente com dispositivos brutos, como bancos de dados especialmente configurados (que implementam seu próprio cache de gravação), tar e dispositivos especiais e ferramentas de sistema de arquivos como chdsk, mkfs e mt. Montar o disquete e usar o sistema de arquivos com gordura do kernel é muito mais responsivo, exceto por umount que é síncrono (e muito importante para que seja assim, para evitar a perda de dados, especialmente para dispositivos removíveis como disquetes). Existem apenas alguns outros programas que eu sei que são usados regularmente com dispositivos brutos, como bancos de dados especialmente configurados (que implementam seu próprio cache de gravação), tar e dispositivos especiais e ferramentas de sistema de arquivos como chdsk, mkfs e mt.
fonte
O_DIRECT
se quiser ignorar o cache.dd oflag=direct
. IIRC, algumas unidades padronizam o direcionamento de E / S em dispositivos de bloco. (E exigem leitura / escrita de blocos alinhados, que o Linux não porque ele está apenas escrevendo o pagecache de qualquer maneira.)A filosofia é insegura por padrão.
Existem duas estratégias razoáveis e óbvias possíveis: liberar gravações no disco imediatamente ou atrasar a gravação. O UNIX escolheu historicamente o último. Portanto, obtenha segurança, você precisa ligar
fsync
depois.No entanto, você pode especificar a segurança antecipadamente montando um dispositivo com a opção
sync
ou por arquivo, abrindo-os comO_SYNC
.Lembre-se de que o UNIX foi projetado para especialistas em computadores. "Seguro por padrão" não foi considerado. Segurança significa E / S mais lenta, e esses sistemas antigos realmente tinham E / S lenta, tornando o preço alto. Infelizmente, nem o UNIX nem o Linux mudaram para o padrão de segurança, embora essa seja uma alteração sem interrupção.
fonte
Ele comercializa uma pequena quantidade de confiabilidade para um grande aumento na taxa de transferência.
Suponha, por exemplo, um programa de compactação de vídeo. Com gravação atrasada ("write back"):
Versus
A segunda versão aparece duas vezes mais rápido porque pode usar a CPU e o disco ao mesmo tempo, enquanto a primeira versão está sempre aguardando uma ou outra.
Geralmente, você deseja write-back para operações de streaming e operações de arquivos em massa e write-through para bancos de dados e aplicativos semelhantes a bancos de dados.
fonte
Em muitos aplicativos, os dispositivos de armazenamento estarão ocupados intermitentemente na leitura de dados. Se um sistema sempre puder adiar gravações até um momento em que o dispositivo de armazenamento não esteja ocupado lendo dados, do ponto de vista de um aplicativo, as gravações levarão tempo zero para serem concluídas. As únicas situações em que as gravações não seriam instantâneas seriam quando:
Os buffers de gravação são preenchidos até o ponto em que nenhuma solicitação de gravação adiada pode ser aceita até que as gravações sejam concluídas.
É necessário desligar ou remover o dispositivo para o qual as gravações estão pendentes.
Um aplicativo solicita especificamente a confirmação de que uma gravação foi realmente concluída.
De fato, é apenas por causa dos requisitos acima que as gravações precisam realmente ocorrer. Por outro lado, geralmente não há razão para não realizar gravações pendentes nos momentos em que um dispositivo estaria ocioso; portanto, muitos sistemas as executam nesse momento.
fonte
Há também o seguinte:
Escreva "Oi, Joe Moe"
é mais rápido que:
Escreva "Oi",
escreva "Joe"
Escreva "Moe"
E também:
Escreva "Oi, tudo bem?"
é mais rápido que:
Escreva "Oi, e aí?"
Exclua essa
gravação "Olá, tudo bem?"
Exclua essa
gravação "Olá, tudo bem?"
É melhor que as modificações e a agregação ocorram na RAM do que no disco. As gravações em disco em lote liberam os desenvolvedores de aplicativos de tais preocupações.
fonte