O que se entende por "uma chamada do sistema", se não a implementação na linguagem de programação?


14

Gostaria de entender o termo "chamada do sistema". Eu sei que chamadas de sistema são usadas para obter serviços de kernel de um aplicativo de espaço de usuário.

A parte com a qual preciso de esclarecimentos é a diferença entre uma "chamada de sistema" e uma "implementação C da chamada de sistema".

Aqui está uma citação que me confunde:

Em sistemas do tipo Unix, essa API geralmente faz parte de uma implementação da biblioteca C (libc), como glibc, que fornece funções de wrapper para as chamadas do sistema, geralmente nomeadas como as chamadas do sistema que chamam

Quais são as "chamadas de sistema que eles chamam"? Onde está a fonte deles? Posso incluí-los diretamente no meu código?

A "chamada do sistema", em um sentido genérico, é apenas uma interface definida pelo POSIX, mas para realmente ver a implementação, pode-se examinar a fonte C e ver como o espaço do usuário real para a comunicação do kernel realmente funciona?

Nota de fundo: Estou tentando entender se, no final, cada função c acaba interagindo com os dispositivos da /dev.

Respostas:


21

Chamadas do sistema em si são um conceito. Eles representam ações que os processos podem solicitar ao kernel para executar.

Essas chamadas de sistema são implementadas no kernel do sistema semelhante ao UNIX. Essa implementação (escrita em C e em asm para peças pequenas) realmente executa a ação no sistema.

Em seguida, os processos usam uma interface para solicitar ao sistema a execução das chamadas do sistema. Essa interface é especificada pelo POSIX. Este é um conjunto de funções da biblioteca padrão C. Na verdade, eles são wrappers, eles podem executar algumas verificações e, em seguida, chamar uma função específica do sistema no kernel que diz para ele executar as ações exigidas pela chamada do sistema. E o truque é que as funções que são a interface são nomeadas da mesma forma que o sistema chama a si mesmas e são frequentemente chamadas diretamente de "chamadas pelo sistema".

Você pode chamar a função no kernel que executa a chamada do sistema diretamente através do mecanismo específico do sistema. O problema é que ele torna seu código absolutamente não portátil.

Portanto, uma chamada do sistema é:

  • um conceito, uma sequência de ações executadas pelo kernel para oferecer um serviço a um processo do usuário
  • a função da biblioteca padrão C que você deve usar no seu código para obter esse serviço do kernel.

1
Você tem um exemplo da "função wrapper" e uma chamada do sistema real? (caminhos de arquivos em Linux ou links para fontes)
TheMeaningfulEngineer

3
Por exemplo, esta é a implementação da getpidchamada do sistema no kernel do Linux: lxr.free-electrons.com/source/kernel/timer.c?v=2.6.35#L1337 . E esta é a função wrapper na biblioteca padrão GNU C glibc-2.19: fossies.org/dox/glibc-2.19/… .
precisa saber é o seguinte

@Igeorget: seus links não funcionam mais. Link atualizado para a implementação do kernel: github.com/torvalds/linux/blob/… . Não consegui encontrar o que a glibc faz atualmente, esse código é impossível de navegar.
rchard2scout

6

Uma chamada do sistema é uma maneira de solicitar ao seu sistema operacional (kernel) que faça alguma operação em nome do seu programa, que o programa não pode fazer por si só (ou é apenas inconveniente). O motivo para não ser capaz de executar alguma operação é normalmente que permitir que um programa aleatório os faça comprometer a integridade do sistema, como fazer E / S (diretamente na RAM, substituindo qualquer coisa).

O POSIX define uma interface para programas, certas funções que seu programa pode chamar. Alguns deles se traduzem mais ou menos diretamente em chamadas do sistema, outros requerem mais elaboração. É o tempo de execução do seu idioma, por exemplo, a biblioteca C, responsável por oferecer a interface POSIX, empacotar argumentos e receber resultados em mão ao chamador.

Os sistemas Unixy oferecem interfaces POSIX mais ou menos diretamente como chamadas do sistema. Normalmente, há uma maneira de chamar chamadas do sistema diretamente, procure syscall(2)os detalhes sobre como usar esse recurso no Linux.


1
Você toca em um ponto importante no qual as outras respostas apenas enfrentam. Qualquer função que um programador razoavelmente capazes poderia escrever para si próprio (como strlen, strcpy, sqrt, e qsort) pode ser e, provavelmente, é no espaço do usuário, carregado a partir de uma biblioteca. (Principalmente libc; matemática funções como sqrtfunções ea trigonométricas e hiperbólicas são provavelmente em libm, a biblioteca de matemática.) ... (continuação)
Scott

1
(continuação) ... Mas não há nenhuma maneira que um usuário pode escrever o seu próprio fork, killou openfunção, porque estes requerem acesso ao espaço de kernel do sistema operacional de memória (por exemplo, a tabela de processo) ou instruções privilegiadas (por exemplo, I / O). Portanto, o código que executa essas funções deve estar no kernel do sistema operacional; portanto, funções do sistema ou chamadas do sistema.
Scott Scott

5

Claro, vamos fazer de quantas direções podemos olhar para este elefante? coisa.

A chamada real do sistema é, no seu programa construído, a instrução da máquina que aciona a escalação de privilégios no modo kernel, e no próprio kernel é o código que a instrução chama. O código libc (e todo tempo de execução de idioma) configura os registros da máquina e os parâmetros de armazenamento em que o código do kernel espera encontrá-los, o que pode ser um local decididamente estranho devido a restrições nas instruções da máquina.

Uma vez no código do sistema operacional, há um pouco de desenrolamento da imagem espelhada das coisas específicas da máquina que o tempo de execução do usuário fez e, em seguida, uma chamada de sub-rotina perfeitamente comum.
Se você quiser ver exatamente como isso funciona em um sistema operacional em grande escala, puxe a fonte do kernel ( git clone https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/) e faça por exemplo git grep -i system\ call. Puxe a fonte glibc e faça o mesmo.


É verdade, mas remexendo em Linux ou glibc é um pouco sobre o lado pesado ...
vonbrand

3

No Linux, pelo menos, o mecanismo de chamada do sistema funciona na maioria das arquiteturas, colocando alguns dados especificamente formatados (geralmente algum tipo de estrutura) em alguns registradores ou endereços de memória predefinidos.

No entanto, o problema ocorre ao forçar a CPU a alternar para o espaço do kernel para que ele possa executar o código privilegiado do kernel para atender à chamada. Isso é feito forçando uma falha de algum tipo (uma falha sendo dividida por 0, um estouro indefinido ou uma segfault etc.), isso força o kernel a assumir a execução para lidar com a falha.

Normalmente, o kernel lida com falhas, matando o processo causador ou executando um manipulador fornecido pelo usuário. No entanto, no caso de um syscall, ele verificará os registros e os locais de memória predefinidos e, se eles contiverem uma solicitação de syscall, executará isso usando os dados fornecidos pelo processo do usuário na estrutura da memória. Isso geralmente tem que ser feito com alguma montagem especialmente criada para facilitar o uso do syscall para o usuário que a biblioteca C do sistema precisa envolvê-lo como uma função. Para uma interface de nível inferior, consulte http://man7.org/linux/man-pages/man2/syscall.2.html para obter mais informações sobre como os syscalls funcionam e como você pode ligar sem um wrapper C.

Isso é simplificado demais, não é verdade em todas as arquiteturas (o mips possui uma instrução syscall especial) e não necessariamente funciona da mesma forma em todos os sistemas operacionais. Ainda assim, se você tiver quaisquer comentários ou perguntas, por favor, pergunte.

Alterado: Observe que, com relação ao seu comentário sobre as coisas em / dev /, essa é realmente uma interface de nível superior ao kernel, e não uma interface inferior. Esses dispositivos realmente usam (aproximadamente) quatro syscalls abaixo. Gravar neles é o mesmo que um syscall de gravação, ler um syscall de leitura, abrir / fechar equivalentes aos syscalls de abertura e fechamento e executar um ioctl causa um syscall especial do ioctl, que por si só é uma interface para acessar um dos muitos ioctl do sistema chamadas (chamadas especiais, geralmente específicas de dispositivos com uso muito restrito para gravar uma chamada de sistema inteira para elas).


1

Toda chamada de sistema possui um número inteiro associado. Esse número inteiro é uma função do valor de retorno da chamada do sistema, número de argumentos para a chamada do sistema e tipo dos argumentos. Esse número de chamada do sistema nada mais é do que um deslocamento no vetor de chamada global do sistema; esse vetor, acessível apenas no modo privilegiado, contém ponteiro para os manipuladores apropriados. O processo ao invocar uma chamada de sistema, uma interrupção de software (interrupção de interceptação) seria gerada; portanto, um manipulador de interceptação seria executado, determinando qual chamada de sistema deveria ser invocada. Em seguida, o kernel copiava os argumentos da chamada de sistema passada pelo usuário que está na pilha nos registros do processador e, após a conclusão do serviço solicitado, os dados eram copiados de volta para a pilha a partir dos registros do processador. Essa é uma das razões pelas quais há argumentos limitados para chamadas do sistema,


Cada chamada (operação) é identificada internamente por um número, verdadeiro. Mas o número depende da operação , não do valor de retorno nem do número de argumentos. Uma explicação de como costumava funcionar a partir da userland no x86 está aqui
vonbrand
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.