O artigo reflete a experiĂŞncia pessoal de desenvolvimento de aplicativos CLI para Linux.
Ele discute como o processo de superusuário pode executar chamadas de sistema privilegiadas quando solicitado pelo programa de controle por meio de uma API bem definida.
O cĂłdigo-fonte Ă© escrito em Python para um aplicativo comercial real, mas abstraĂdo de tarefas especĂficas para publicação.
Introdução
“A comunicação entre processos (IPC) é a troca de dados entre threads de um ou diferentes processos. É implementado por meio de mecanismos fornecidos pelo kernel do sistema operacional ou por um processo que usa mecanismos do sistema operacional e implementa novos recursos IPC. " - Wikipedia
Os processos podem ter diferentes motivos para a troca de informações. Na minha opiniĂŁo, tudo isso Ă© consequĂŞncia da polĂtica de segurança do kernel Unix.
Como você sabe, o kernel Unix é um sistema autônomo que funciona sem intervenção humana. Na verdade, um usuário é um objeto do sistema operacional que parecia proteger o kernel de interferências não autorizadas.
A segurança do kernel consiste em dividir o espaço de endereço do sistema operacional em espaço do kernel e espaço do usuário . Daà os dois modos de operação do sistema: modo de usuário e modo kernel. Além disso, uma mudança de modos é uma troca entre dois espaços.
No modo de usuário, as áreas de memĂłria reservadas pelo kernel ficam inacessĂveis, assim como as chamadas do sistema que alteram o estado do sistema.
No entanto, o superusuário tem esse acesso.
Pré-requisitos de simultaneidade
Se o seu programa não usa chamadas de sistema privilegiadas, você não precisa de um superusuário, o que significa que você pode escrever um monólito sem simultaneidade.
Caso contrário, você terá que executar seu programa como root.
, .
, , .
, , , , . , . , , , — .
IPC.
|
|
|
|
|
|
, POSIX. |
|
, POSIX. |
(Message queue) |
. |
|
|
; , , Windows, , , IPC. |
|
. |
|
|
. |
|
, POSIX. |
(mmap) |
, POSIX. . Windows , API, API, POSIX. |
( ) |
MPI, Java RMI, CORBA . |
|
|
. |
|
|
, POSIX. |
|
|
, POSIX. |
API .
, , .
, , .
, , daemon. «d». : systemd.
, daemon , . : systemctl.
: ssh sshd.
.
.
├── core
│ ├── api.py
│ └── __init__.py
├── main.py
core
— , . api
.
API
from multiprocessing.connection import Client
from multiprocessing.connection import Listener
# ( )
#
daemon = ('localhost', 6000)
# ( )
#
cli = ('localhost', 6001)
def send(request: dict) -> bool or dict:
"""
.
,
.
"""
with Client(daemon) as conn:
conn.send(request)
with Listener(cli) as listener:
with listener.accept() as conn:
try:
return conn.recv()
except EOFError:
return False
def hello(name: str) -> send:
"""
send .
"""
return send({
"method": "hello",
"name": name
})
connection
multiprocessing
, API — socket.
Client
— , .
Listener
.
.
, Python, , . « » .
API
main.py
api
.
from core import api
response = api.hello("World!")
print(response)
. lick Framework LI , API.
API
, . .
def hello(request: dict) -> str:
"""
.
"""
return " ".join(["Hello", request["name"])
API
from core import api
from multiprocessing.connection import Listener
from multiprocessing.connection import Client
# ( )
daemon = ('localhost', 6000)
#
cli = ('localhost', 6001)
while True:
with Listener(daemon) as listener:
with listener.accept() as conn:
request = conn.recv()
if request["method"] == "hello":
response = api.hello(request)
with Client(cli) as conn:
conn.send(response)
, .
Portanto, ele sempre escuta na porta 6000 e analisa a solicitação quando um datagrama chega. Em seguida, ele chama o método especificado na solicitação e retorna o resultado da execução ao cliente.
Além disso
Aconselho você a equipar seu servidor com o pacote systemd , que permite que programas Python façam login no journald .
Para construir você pode usar o pyinstaller - ele irá empacotar seu código em um arquivo binário com todas as dependências. Não se esqueça da convenção de nomenclatura para arquivos executáveis ​​mencionada anteriormente.
Obrigado pela atenção!