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
.
fonte
getpid
chamada 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/… .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.fonte
strlen
,strcpy
,sqrt
, eqsort
) pode ser e, provavelmente, é no espaço do usuário, carregado a partir de uma biblioteca. (Principalmente libc; matemática funções comosqrt
funções ea trigonométricas e hiperbólicas são provavelmente em libm, a biblioteca de matemática.) ... (continuação)fork
,kill
ouopen
funçã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.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 exemplogit grep -i system\ call
. Puxe a fonte glibc e faça o mesmo.fonte
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).
fonte
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,
fonte