"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Noções básicas sobre tempos de execução: de C às linguagens modernas

Noções básicas sobre tempos de execução: de C às linguagens modernas

Publicado em 2024-11-08
Navegar:833

Understanding Runtimes: From C to Modern Languages

Na era do desenvolvimento e programação de software moderno, o termo "tempo de execução" pode significar coisas diferentes dependendo do contexto e da linguagem em discussão. Estou aqui para esclarecer essas diferenças, focando em como os tempos de execução funcionam em C em comparação com linguagens mais modernas como Java ou Python. Pretendo manter este artigo voltado para programadores iniciantes, portanto evitarei me aprofundar em conceitos complexos.

O que é um tempo de execução?

Em sua essência, um tempo de execução é o próprio programa que lê e executa código escrito por um desenvolvedor. Mas fica confuso quando alguns desenvolvedores usam tempo de execução com linguagem C.

Tempos de execução de linguagem moderna

Em linguagens como Java ou Python, o runtime é um programa em si que lê seu arquivo myfile.js, é por isso que você executa programas nodejs como: node myfile.js e v8 engine( é o mecanismo JavaScript, ele analisa e executa JavaScript code.) gerencia tudo, quer você crie um novo arquivo, ative um processo filho e etc. e o mais importante, você não pode fazer nada que a v8 não permita. Mas quando você executa um programa c você não faz c myfile.c você só precisa compilá-lo uma vez e agora você não precisa mais do gcc, apenas execute-o diretamente.

O C "tempo de execução"

Em C, não há um programa separado rodando junto com seu código da mesma forma que em Java ou Python. Em vez disso, o que costuma ser chamado de "tempo de execução"

C é na verdade um conjunto de código inserido estaticamente e instruções adicionadas durante a compilação. É um conjunto mínimo de instruções incluídas no binário final para lidar com certas tarefas necessárias no nível da CPU/SO. Ele lida com a criação e desmontagem de stack frames para chamadas de função (usando instruções como PUSH, POP, CALL, RET em assembly). Mesmo isso pode ser substituído fornecendo sua própria função __start usando assembly embutido, dando aos desenvolvedores controle total sobre o ponto de entrada e inicialização do programa.

void__start(){ //Ponto de entrada personalizado, sem inicialização de biblioteca padrão // Você não tem acesso a argc e argv aqui, a menos que você os acesse manualmente a partir dos registros // você pode criar sua própria configuração de pilha personalizada, inicialização e etc aqui. // Sai diretamente usando um syscall asm("mov $60, %rax; mov $0, %rdi; syscall"); //exit(0)syscall }

void __start() {
// Custom entry point, no standard library initialization
// You have no access to argc and argv here unless you access them manually from registers
// you can create you own custom stack setup, initialization and etc here.

// Exit directly using a syscall
asm("mov $60, %rax; mov $0, %rdi; syscall"); // exit(0) syscall
}


Isso não se parece em nada com tempo de execução, é apenas um código em linguagem Assembly adicionado pelo compilador para que os desenvolvedores não precisem fazer isso.

O poder e a responsabilidade de C

Em C, você pode invocar chamadas de sistema diretamente usando assembly embutido para interagir com o kernel de maneiras normalmente não permitidas pelo sistema operacional, é assim que os malwares são criados. O assembly embutido permite que os desenvolvedores escrevam instruções em linguagem assembly dentro do código C. Isso geralmente é usado para código de desempenho crítico ou para acessar recursos de hardware específicos.

Montagem embutida em C

    O assembly inline permite que os desenvolvedores escrevam instruções em linguagem assembly dentro do código C. Isso geralmente é usado para código de desempenho crítico ou para acessar recursos de hardware específicos.
  • Ele fornece uma maneira de executar instruções da CPU diretamente.
Interação direta com o kernel

    usando assembly embutido, um programador pode invocar chamadas de sistema diretamente, sem passar por bibliotecas de nível superior.
  • Por exemplo, podemos usar assembly embutido para configurar registros com os parâmetros apropriados para uma chamada de sistema e então acioná-la.
  • Como o assembly embutido permite controle de baixo nível sobre os recursos do sistema, ele pode ser usado para contornar mecanismos de segurança ou manipular o kernel diretamente. É assim que o malware pode realizar ações não autorizadas, como acessar memória protegida, interceptar chamadas do sistema ou manipular processos e sua memória.
  • O malware pode explorar vulnerabilidades no sistema operacional ou usar essas interações de baixo nível para executar tarefas como keylogging, escalonamento de privilégios ou operações furtivas.
No linux C tem um FLAG que permite gravar dados de arquivo diretamente em um dispositivo de armazenamento, ignorando alguns dos mecanismos de cache do kernel, é chamado de flag O_DIRECT que é usado em combinação com as chamadas de sistema open e write. Este sinalizador garante que os dados não sejam armazenados em buffer na RAM ou gerenciados pelo kernel no espaço do kernel. Isso grava diretamente os dados no disco rígido, a JVM não permitirá isso e é apenas um exemplo simples. aqui está um exemplo simples:


asm volátil ( "syscall" : "=a" (escrito) : "0" (1), "D" (fd), "S" (amortecedor), "d" (BLOCK_SIZE) : "rcx", "r11", "memória" );


asm volatile (
"syscall"
: "=a" (written)
: "0" (1),
"D" (fd),
"S" (buffer),
"d" (BLOCK_SIZE)
: "rcx", "r11", "memory"
);


Nota: *

(escrito) é uma variável criada dentro de main(), (1) é o número syscall para gravação, (fd) é onde o arquivo será gravado, ou seja, int fs = open("caminho .log",O_WRONLY; (BLOCK_SIZE) é outro nome de variável. É mais complexo que isso. A evolução dos tempos de execução

É importante entender que o conceito de tempo de execução evoluiu ao longo dos anos. O "tempo de execução" C dos anos 70 é muito diferente dos ambientes de execução robustos que vemos nas linguagens dos anos 2000. Essa evolução pode causar confusão ao discutir tempos de execução, especialmente entre desenvolvedores familiarizados com diferentes épocas de programação.

Conclusão

Acho que as pessoas agora estão comparando o tempo de execução dos anos 1970 com os tempos de execução dos anos 2000, o que está confundindo novos desenvolvedores com desenvolvedores antigos.

Resolver um problema específico é a principal tarefa de qualquer linguagem de programação, você não quer escrever um framework inteiro para criar APIs em C, temos nodejs e é bom nisso e você não precisa escrever código bare metal em javascript porque nós já tenho C e é fabuloso nisso. Por que reinventar a roda, vamos usar as rodas e criar um carro fabuloso,

a menos que você não queira dirigi-lo em Marte.

Declaração de lançamento Este artigo está reproduzido em: https://dev.to/bossysmaxx/understanding-runtimes-from-c-to-modern-languages-3fkj?1 ​​​​Se houver alguma violação, entre em contato com [email protected] para excluir isto
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3