Como o init conhece os eventos de energia?

8

Eu tenho um Pi Modelo B Rev 2.0 (eu acho) e pretendo usá-lo para um sistema de automação residencial. Como tenho um medidor de pré-pagamento em meu suprimento de eletricidade, ocasionalmente fico sem elétrons para contornar o fornecimento de energia elétrica da minha casa!

Para evitar problemas, obtive um no-break na forma de um UPis Basic da PiModules . Eu o configurei para que eu possa pesquisar as tensões de alimentação através da porta serial do Pi (não a configuração padrão, mas uma instalação suportada documentada no manual ).

No momento, ele usa um pino GPIO dedicado (pino 13 no cabeçalho, GPIO27, eu acredito) e o microcontrolador embutido usa isso e um script python executado em rc.local para informar ao Pi shutdown -h nowquando o pino está baixo - o que acontece quando o botão "Desligar" do no-break é pressionado ou se a alimentação da bateria ficar muito baixa no caso de falha na alimentação principal. Para o registro, o script é:

#!/usr/bin/python

# import the  libraries to use time delays, send os commands and access GPIO pins
import PRi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM) # Set pin numbering to board numbering
GPIO.setup(27, GPIO.IN, pull_up_don=GPIO.PUD_UP) # Setup pin 27 as an input
while True: # Setup a whille loopto wait for a button press
    if(GPIO.input(27)==0): # Setup an if loop to run a shutdown command when button press sensed
        os.system("sudo shutdown -h now") # Send shutdown command to os
        break
    time.sleep(1) # Allow a sleep time of 1 second to reduce CPU usage

Isso me parece um pouco deselegante, pois initpossui a capacidade integrada de lidar com eventos de energia. Devo reiterar que estou usando o sysVinit no Raspbian Jessie, NÃO o sistema padrão para essa versão (por preferência pessoal e por motivos de familiaridade).

Gostaria, inicialmente, de substituir o script acima por algo que diga ao init para fazer isso powerfailnowquando o pino estiver baixo - e para fazer um powerokwaitse, posteriormente, retornar alto. Eventualmente, também quero pesquisar a porta serial e acompanhar as respostas @rpi, @bate @upsque retornam as tensões atuais no trilho de 5V do Pi, a bateria LiPo e a própria entrada microUsb da UPis, respectivamente - para que o Pi possa emitir um alerta em / lida com uma falha de energia (deve resultar em uma powerfailação init e deixar o Pi relatar o status de perda de energia para mim, o usuário - supondo que eu ainda não tenha notado!)

No entanto, estou tendo dificuldade em descobrir como dispositivos Linux UPS sinalizar para initque o powerfail\ powerwait\ powerfailnow\ powerokwaitcomandos definidos no \etc\inittabdeve ser realizada.

Alguém pode me aconselhar, por exemplo, como o UPS "adulto" diz a um kernel Linux em um PC normal que eventos de "energia" estão acontecendo e como eu posso reproduzir o mesmo neste sistema em um Pi?

SlySven
fonte
Obrigado @ Jacobm001 por detectar a ausência da tag para a parte Python-ish desta pergunta. Nas últimas horas, estive passando por um curso intensivo no idioma (estou fazendo algum progresso), mas há pouco tempo eu não 't ter conhecido meu Asp do meu cotovelo ...
SlySven
Também estou curioso para saber como o Pi (ou init) sabe sobre eventos de poder. Espero que alguém responda em breve.
PNDA
Gostaria de olhar para acpid e talvez você possa alterar seu script para reagir quando algo muda (pino alto -> baixo) em vez de pesquisar o valor a cada segundo?
Diederik de Haas
2
@ PandaLion98 O hardware Pi não possui eventos de energia, portanto não há nada a ser conhecido sobre eles. Se alguns forem implementados, o init só saberá sobre eles se for informado, seja pelo kernel (devido a um evento de driver, que no caso do pi provavelmente seria um driver para algum hardware adicional) ou por meio de um aplicativo local do usuário.
goldilocks

Respostas:

5

Ah ha! Alguns parágrafos nas páginas de manual init(8)referem-se à interface depreciada de escrever um valor de uma letra /etc/powerstatus(agora substituído por /var/run/powerstatus) e enviar initum SIGPWRsinal; a carta deve ser uma das seguintes:

  • Energia em ' F ': a energia principal falhou e o no-break está fornecendo energia, execute as entradas powerwaite powerfail.
  • Power ' O ' kay: a energia [principal] foi restaurada, execute a powerokwaitentrada.
  • ' L poder ow': a energia está a falhar e a UPS tem um [criticamente] bateria fraca, executar a powerfailnowentrada.
Se o arquivo especificado não existir ou contiver nada além das letras F, Oou L, init se comportará como se tivesse lido a letra F.

Abaixo deste é o aviso:

O uso SIGPWRe /etc/powerstatusdesanima. Alguém que queira interagir initdeve usar o /run/initctlcanal de controle - consulte o código-fonte do sysvinitpacote para obter mais documentação sobre isso.

Portanto, embora isso possa ser uma resposta , não é a resposta - a seguir, preciso examinar o código-fonte que é mantido como um projeto não-GNU hospedado no site de hospedagem do GNU .

SlySven
fonte
1

Eu acho que a abordagem mais limpa seria ter um driver de dispositivo do kernel gerenciando o GPIO27 e configurado para receber uma interrupção quando ficar baixo. O manipulador de interrupção notificaria o init. A página http://elinux.org/RPi_Low-level_peripherals diz que o Raspbian Wheezy suporta interrupções de GPIO.

Peço desculpas pela resposta de baixa qualidade, não olhei para os drivers gpio do Linux e como estendê-los / aprimorá-los. Também não procurei o método aprovado atual para notificar init de dentro de um manipulador de interrupções. Espero que este post estimule melhores respostas.

Chad Farmer
fonte
Sim, uma interrupção parece melhor do que a pesquisa - Diederik de Haas mencionou isso acima. O foco da minha investigação no momento é "O manipulador de interrupção notificaria o init ..." é esse mecanismo que é intrigante, o powerstatsinal do arquivo / SIGPWR parece relativamente simples e direto, mas parece estar obsoleto. Eu estou tentando descobrir agora sobre o uso da vida real da initctltubulação ...
SlySven
1

Ao pesquisar o código-fonte do SysV initdisponível no servidor Savannah da Free Software Foundation, fui capaz de enviar solicitações aos meus RPi initpreenchendo um struct init_requestconforme detalhado no initreq.harquivo de cabeçalho. Especificamente, esta requeria a magic, sleeptimee, para os meus propósitos os cmdcampos a ser preenchida, com o último conjunto de estar a um dos INIT_CMD_POWERFAIL, INIT_CMD_POWERFAILNOWou INIT_CMD_POWEROK.

Meu daemon / programa que precisa ser executado como usuário com permissão para gravar no canal de controle init {originalmente no /dev/initctrlDebian e, portanto, Raspbian para /run/initctrl} foi capaz de enviar a estrutura à initqual respondeu apropriadamente, respondendo ao seguintes entradas em /etc/inittab:

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

Nota: essa interface - ou pelo menos a notificação da fonte de alimentação NÃO foi adotada pelo novo fangled systemd-, embora pelo que possa ser considerado um pouco de programação de culto à carga, ele tente garantir a existência do initctrltubo. Por outro lado, isso faz exatamente o que eu quero que ele faça no meu sistema RPi!

SlySven
fonte
Embora eu admire sua dedicação a esse problema seu, não posso deixar de notar que você gastou um tempo significativo para implementar uma solução que é funcionalmente equivalente ao seu script inicial e nem sequer é uma prova futura.
Dmitry Grigoryev
Bem, embora seja funcionalmente equivalente ao sistema inicial, ele usa a interface fornecida recomendada e não a obsoleta. Quanto às provas futuras, não cabe às pessoas que escrevem o futuro sistema implementar a interface conhecida do sistema que estão tentando suplantar para garantir a compatibilidade com versões anteriores sempre que possível.
precisa saber é o seguinte
Afinal, receber uma notificação da principal falha de energia é muito importante para um sistema com um no-break, então um gerente de processo / sistema meio decente deve estar ciente de como seu antecessor fez as coisas e procurar outros processos usando essa API - uma interface que existe mas é ignorado parece um pouco míope ... 8- / De acordo com o código em: github.com/systemd/systemd/blob/master/src/initctl/initctl.c, todos os no-breaks informamsystemd que a energia principal falhou dessa maneira, será registrada a mensagem: "Solicitação de UPS / power initctl recebida. Isso não foi implementado no systemd. Atualize o daemon do UPS!"
precisa saber é o seguinte
"Isso não é implementado em systemd Atualize seu daemon UPS." - isso é tudo que você precisa saber sobre a compatibilidade com versões anteriores em Linux;)
Dmitry Grigoryev
A initctlinterface para o van van Smoorenburg init foi declarada privada e não para terceiros por um dos (então) mantenedores do programa em 2012. Miquel van Smoorenburg powerd, mais tarde Tom Webster genpowerd, originalmente usou o /etc/powerstatusmecanismo.
JdeBP 29/02