Memória indestrutível, processos indestrutíveis


Tendo lido recentemente ( 1 , 2 , 3 ) com que dificuldade os processadores "espaciais" são dados, perguntei-me involuntariamente se o "preço" do ferro estável é tão alto que talvez valha a pena dar um passo e, por outro lado, tornar o "software" resistente a fatores especiais? Mas não o software aplicativo, mas o ambiente de execução: compilador, SO. É possível tornar a execução do programa a qualquer momento possível para interromper, reiniciar o sistema e continuar no mesmo local (ou quase no mesmo). No final, há hibernação .

Efeitos de radiação


Quase tudo o que voa do espaço é capaz de interromper a operação do microcircuito, é apenas uma questão de quantidade de energia que "ele" trouxe com ele. Mesmo um fóton, se tiver um comprimento de onda de raios gama, é capaz de superar vários centímetros de alumínio e ionizar o (s) átomo (s) ou até causar um efeito fotoelétrico nuclear . Um elétron não pode penetrar através de nenhum obstáculo denso, mas se for acelerado mais fortemente, emitirá um quantum gama ao frear com todas as conseqüências resultantes. Dado que a meia-vida de um nêutron livre é de cerca de 10 minutos, um nêutron raro (e muito rápido) chega do Sol. Mas os núcleos de qualquer coisa passam voando e também são capazes de fazer as coisas. Os neutrinos talvez não sejam vistos em nada disso.

Como não lembrar de Piglet com ele: "é difícil ser corajoso quando você é apenas um Ser Muito Pequeno".

As consequências da radiação cósmica que entra no semicondutor podem ser diferentes. É a ionização dos átomos e a violação da estrutura cristalina e das reações nucleares. É aqui que a dopagem de silício com nêutrons térmicos em um reator atômico é descrita , quando o Si (30) se transforma em P (31) e as propriedades desejadas do semicondutor são atingidas. Não vale a pena recontar os artigos maravilhosos mencionados, apenas observaremos o seguinte:

  1. Alguns efeitos têm um efeito a curto prazo e não têm efeitos a longo prazo. Eles podem levar a erros que podem ser corrigidos em hardware ou software. Na pior das hipóteses, uma reinicialização ajuda.
  2. , . - .
  3. .

Observe que os efeitos dos tipos 2 e 3, se puderam ser interrompidos, levam à degradação gradual do microcircuito. Por exemplo, se um dos (até 4) adicionadores "queimar" no processador superescalar , você pode (pelo menos especulativamente não ser difícil) desativar fisicamente a energia da vítima e usar os três restantes; exteriormente, apenas uma queda no desempenho será perceptível. Da mesma forma, se um dos registros do pool interno estiver danificado, ele poderá ser marcado como "sempre ocupado" e não poderá participar do planejamento das operações. A unidade de memória pode ficar indisponível. ... Mas se algo irreparável se deteriorar, você terá que aumentar a reserva de frio. Se ele é.

“Ficar em uma reserva fria, a propósito, não protege o microcircuito do acúmulo de dose e mesmo do acúmulo de carga no isolador do portão. Além disso, são conhecidos microcircuitos nos quais a degradação da dose sem fonte de alimentação é ainda pior do que com ela. Mas todos os efeitos únicos que causam falhas graves exigem a inclusão do chip. Com a energia desligada, pode haver efeitos de viés, mas eles não são importantes para a lógica digital. ” (amartology)

Portanto, existem dois fatores

  • a qualquer momento, pode ocorrer uma falha, tratada por uma reinicialização
  • Se o sistema se degradar gradualmente (sequência de falhas), a maior parte do trabalho ocorrerá em condições de degradação parcial

Como você mora com tudo isso? Devido à reserva / triplicação da votação em toda a hierarquia de blocos funcionais. Por si só, triplicar não é uma panacéia, é necessário entender qual dos resultados está correto quando um dos componentes falha. Em seguida, o componente com falha pode ser reiniciado e alinhado com dois trabalhadores. Porém, no caso de uma falha, quando o componente não puder ser colocado em condição de trabalho, apenas a reserva fria, se houver, ajudará.

Mesmo que a falha não pareça crítica, pode causar sérios problemas. Suponha que tenhamos três computadores trabalhando de forma síncrona, em um deles (hipotético, mencionado acima), um dos adicionadores falhou. Isso não é um problema do ponto de vista de um computador que permaneceu operacional, mas é um problema para todo o sistema, pois o computador afetado começará a se atrasar sistematicamente e serão necessários esforços sérios para a sincronização geral.

Outro exemplo, uma falha de memória, como resultado de parte de seu alcance (até uma página) se tornar inutilizável, não é crítica do ponto de vista de um único computador. Após o diagnóstico, o sistema operacional é capaz de lidar com esse problema sem usar esse intervalo. Mas, do ponto de vista do sistema de trojan, isso é um desastre. Agora, se houver uma falha (que é tratada pela reinicialização), precisaremos levar o computador com falha a um estado idêntico a qualquer um dos restantes, mas isso é impossível porque em outros computadores, esse intervalo está funcionando e provavelmente é usado. Em princípio, é possível proibir esse intervalo nos três computadores; no entanto, não é óbvio que será possível fazer isso sem reiniciar todos os computadores.

É uma situação paradoxal quando um sistema que é trojan no nível superior é menos confiável em comparação com um único computador que pode se adaptar à degradação gradual.

Vale mencionar a abordagem chamada Lock-step , quando dois núcleos executam a mesma tarefa com um turno de um ou dois ciclos de clock e depois os resultados são comparados. Se não forem iguais, algum código será reexecutado. Isso não funciona se houver um erro na memória ou no cache geral, no entanto, ele possui sua própria proteção.

Há também uma abordagem em que o compilador repete a execução de parte dos comandos e compara os resultados. Uma versão tão suave do Lock-step.

Ambas as abordagens (obrigadoamartologypor dica) - uma tentativa de detectar uma falha e tentar corrigi-la com "pouco sangue", sem reiniciar. Provavelmente, consideraremos a situação quando ocorrer uma falha grave ou não crítica e uma reinicialização for inevitável. Como garantir que o programa sem nenhum esforço especial da sua parte possa ser interrompido a qualquer momento e continue sem perdas sérias.

Como ensinar hardware e sistema operacional a se adaptar à degradação gradual é um tópico para outra discussão.

E se


A idéia de uma memória estável / persistente não é nova em si mesma; portanto, o respeitado Dmitry Zavalishin (dzavalishin) propôs seu conceito de memória persistente . Em suas mãos, isso deu origem a todo um Phantom OS persistente , na verdade uma máquina virtual com sobrecarga correspondente.

Talvez, com o tempo, as tecnologias MRAM ou FRAM amadureçam ... enquanto estão cruas.

Há também uma lenda sobre o computador de bordo do foguete R-36M (15L579?), Que foi capaz de ser lançado através de uma nuvem radioativa imediatamente após uma explosão nuclear. A memória aplicada nos núcleos de ferrita é imune à radiação. O ciclo de gravação dessa memória é da ordem de unidades de microssegundos, portanto, durante o tempo em que o foguete voa alguns decímetros, houve uma oportunidade física de manter o contexto do processador - o conteúdo de registros e sinalizadores. Acordando em um ambiente seguro, o processador continuou a funcionar.
Parece crível.

Existem alguns buts:

  1. A hibernação em sua forma atual não é adequada. Demora algum esforço e tempo. Estamos tentando nos proteger de um fracasso repentino. Não é óbvio que após essa falha o processador esteja fisicamente apto a fazer pelo menos alguma coisa. Da mesma forma, em 15L579, o sistema recebe um aviso antes do início dos problemas e tem tempo para se proteger contra eles.
  2. “” — , , — . , () , .
  3. , , . — -.

Em geral, a recuperação de falhas é essencialmente uma contrapartida do tratamento de exceções. Na verdade, a falha em si na maioria dos casos começa como uma interrupção de hardware. A diferença é que, após a exceção, podemos continuar trabalhando e, neste caso, precisamos primeiro restaurar o contexto de trabalho - a memória e o estado do kernel do sistema operacional. Mas a parte final parece a mesma.

Primeiro, como deve aparecer do lado do programador de aplicativos.

Um olhar de fora do kernel do SO


Como a recuperação de falhas é semelhante à recuperação de lançar uma exceção, o trabalho com ela pode ser semelhante. Por exemplo, em C ++, herdamos a classe std :: tremendous_error de std :: exception, capturamos em um bloco try / catch regular e organizamos o processamento.

No entanto, o autor gosta mais da semântica de setjmp / longjmp (SJLJ) porque:

  • isso é conciso, basta chamar o setjmp analógico (& buf) e continuar o trabalho do mesmo local
  • mesmo nenhum "& buf" é necessário, basta chamar uma função do sistema que armazena o estado atual
  • além do C ++, existem outras ótimas linguagens, não em todo lugar há tratamento de exceções, mas em todo lugar existe uma chamada para funções do sistema
  • e não há necessidade de modificar o idioma, porque originalmente agiríamos da maneira mais invasiva possível

Ao mesmo tempo, o SJLJ perdeu a técnica DWARF (a rigor, anão é apenas um formato para registrar informações) no tratamento de exceções devido ao desempenho pior, o desempenho não é tão importante aqui. De qualquer forma, manter o estado não será barato, é preciso abordá-lo com responsabilidade.

Um olhar de dentro do kernel do SO


O que precisa ser salvo, em que consiste o contexto da execução do processo?

  1. Para cada segmento no modo de usuário - o "jmp_buf" atual com os registros necessários, isso significa que o sistema operacional deve parar todos os segmentos do processo de chamada antes de salvar os dados
  2. , — . (: ), (ex: ).
  3. . (ex: ), (ex: TCP ). .
  4. , . ,
  5. . , . , — . .. .

    , , . .
  6. , .

As informações não são necessárias para a transcodificação da memória virtual para a física e vice-versa; após a reinicialização, essas informações serão recriadas por si mesmas, possivelmente de uma maneira diferente.

Quanto ao trabalho com o sistema de arquivos. Entre os sistemas de arquivos, existem sistemas transacionais. Se o aplicativo exigir um comportamento transacional preciso, a preservação do contexto do processo deve ser sincronizada com a confirmação da transação do sistema de arquivos. Por outro lado, por exemplo, para gravar logs de texto, é lógico usar um sistema de arquivos regular; a transacionalidade aqui seria estranha.

De todas as alternativas acima, as maiores questões são causadas pela preservação do conteúdo da memória; o volume de tudo o mais é insignificante em comparação com isso.
Por exemplo, tempo de execuçãoa biblioteca armazena em buffer as alocações de memória, as solicita ao sistema em partes relativamente grandes e se distribui. Portanto, a criação / exclusão de segmentos é relativamente pequena.

Mas os programas trabalham continuamente com a memória; em essência, é o subsistema de memória que geralmente é o gargalo nos cálculos. E tudo o que pode simplificar nossas vidas é o suporte de hardware para sinalizadores de páginas modificadas. Espera-se que entre o estado seja salvo, não sejam exibidas muitas páginas modificadas.

Com base nisso, no futuro, lidaremos com o conteúdo da memória.

Salvando o conteúdo da memória


O comportamento desejado é próximo aos bancos de dados - o DBMS pode "cair" a qualquer momento, mas o trabalho realizado continuará até a última confirmação. Isso é conseguido mantendo um log de transações, informando quais registros de confirmação legalizarão todas as alterações feitas na transação.

Mas, como o termo " memória transacional " está ocupado, apresentaremos outro - "memória indestrutível".

De antemão você pode ver dois métodos pelos quais essa memória indestrutível pode ser implementada: a primeira

opção , vamos chamá-la de "despretensiosa".
A idéia principal é que todos os dados alterados em uma transação sejam colocados na RAM. Essa. durante a operação, o mecanismo de troca não salva nada no disco, mas durante a confirmação, todas as páginas alteradas são salvas no arquivo de troca.

As informações sobre os segmentos selecionados e sua conexão com o local no arquivo de troca são gravadas no log. Durante a operação, essas informações são acumuladas e registradas durante a confirmação. Ao reiniciar, o sistema tem a capacidade de criar novos segmentos. O mecanismo de troca poderá acessá-los e o programa interrompido receberá magicamente seus dados.

Contudo, nesse modo, é impossível, por exemplo, alocar um array de callocth maior que a memória disponível ( a propósito, é possível mallocth ). No entanto, isso não seria uma idéia muito boa.

Mesmo que esse regime se aplique apenas a processos que se declararam "indestrutíveis", a quantidade de memória ocupada pelas transações atuais de todos esses processos não pode exceder a disponível fisicamente. O mecanismo de swap realmente para de trocar e se transforma em um mecanismo para armazenar transações recentes.

Tudo isso impõe certa disciplina aos desenvolvedores de aplicativos, pode levar a uma carga desigual no disco, em geral, não é exatamente isso que queríamos, mas pode funcionar em sistemas embarcados.

Uma desvantagem significativa dessa opção é que um erro fatal durante a confirmação, quando apenas parte das páginas foi gravada, leva o processo correspondente a um estado instável, após o qual terá que ser interrompido.
Acontece algum tipo de inviolabilidade de 50%.

Opção dois , "Sombra"
Para atuar como um gerenciador de transações, você precisa ser um gerente de transações.

Vamos definir entidades:

  1. O arquivo da página contém páginas de dados; portanto, o tamanho é múltiplo do tamanho da página. Dizemos o arquivo, queremos dizer a seção, porque um tamanho fixo melhora a estabilidade do sistema.
  2. Alocador de página do arquivo de paginação . É necessário selecionar uma página não apenas para dados do usuário, mas também, por exemplo, para registrar o estado do próprio alocador. Bem como tudo o que foi mencionado acima.
  3. . , . , ,
    (= , ).
  4. . —
    • ID
    • ( )
    • ID .

    - TLB, .. .

    ( ) . . , ex: (Buddy Allocator) .

    , . .
  5. . COW (copy on write) . , . COW, - , . .

    — - , “dirty”. .
  6. (). .

    : , .

    . , . . , , . . , ? , .

    , .

    (= , , , ).


    (=, ). .

    . , . , , , .

    , . , . .

    — . , , , , .
    , , .

    .
  7. . , , — . , ?

    — . , . , . , .. .

    — , SSD ! , SSD ( “” ) .

    , .

    — . , . , . ( ).

    , , , . , , . , , , . , — . .
  8. Checkpoint.

    , , , , . — . , . checkpoint. .

    . . - checkpoint- . .

    , . - .

    checkpoint-. , / .

    -, - /, . , ( ...). .

    . . . , . — , checkpoint.


É uma pena que não haja dispositivos de armazenamento que sejam completamente resistentes à operação a longo prazo em condições de espaço. Os núcleos de ferrite eram resistentes à radiação, mas tinham seus próprios problemas específicos devido ao grande número de juntas soldadas. Além disso, baixa capacidade, baixa velocidade e alta complexidade de fabricação.

No entanto, você deve poder escrever e ler esses dados com confiabilidade.

Um candidato óbvio é a memória flash. O Flash não era inicialmente altamente confiável devido ao baixo número de ciclos de gravação válidos; portanto, métodos especiais foram desenvolvidos para trabalhar com ele .

Foi mencionado anteriormente que a triplicação é usada para trabalhar com elementos não confiáveis, o RAID1 é suficiente aquiPorque se a gravação falhar devido aos valores de controle, é conhecido qual das duas páginas foi gravada incorretamente e deve ser substituída.

Total


Bem, agora temos em nossas mãos todas as quatro letras da palavra ÁCIDO .

A - atomicidade,
C - consistência alcançada ,
I - isolamento é evidente , é alcançado naturalmente. Se você não considerar o caso da memória compartilhada. E no momento não estamos considerando isso.

D - persistência, o único momento em que tentamos trapacear quando lançamos o processo após uma confirmação sem esperar pela gravação física de todos os dados em sua memória no disco. Na pior das hipóteses, isso levará a uma reversão da transação anterior. Não está claro o quão crítico isso é para desempenho e durabilidade.

PS. Apenas uma nota rápida. Não temos um mecanismo para transações de reversão, a reversão pode ser apenas um erro fatal. Tecnicamente (ao que parece), é fácil implementar um programa de reversão de transações como um análogo do longjmp. Mas esta é uma versão muito mais avançada do longjmp, pois restaura completamente o estado interno do processo no momento do “setjmp”, evitando vazamentos de memória, permitindo a transição não apenas de baixo para cima na pilha ...

PPS . Talvez o servidor OpenLink Virtouso DBMS , disponível também como software livre , possa ser considerado o protótipo do gerenciador de transações .

PPPS . Graças a Valery Shunkov (amartology) e Anton Bondarev (abondarev) para uma discussão significativa e muito útil.

PPPPS . Ilustração de Anna Rusakova .

All Articles