Comment init se familiarise-t-il avec les événements de pouvoir?

8

J'ai un Pi Model B Rev 2.0 (je pense) et j'ai l'intention de l'utiliser pour un système domotique. Comme j'ai un compteur à prépaiement sur mon alimentation électrique, je manque parfois d'électrons pour contourner l'alimentation secteur de ma maison!

Pour éviter les problèmes, j'ai obtenu un onduleur sous la forme d'un UPis Basic fabriqué par PiModules . Je l'ai configuré pour pouvoir interroger les tensions d'alimentation via le propre port série du Pi (pas la configuration par défaut mais une configuration prise en charge documentée dans le manuel ).

À l'heure actuelle, il utilise une broche GPIO dédiée (broche 13 sur l'en-tête, GPIO27 je crois) et le micro-contrôleur intégré utilise cela et un script python exécuté depuis rc.local pour indiquer au Pi shutdown -h nowquand la broche est prise basse - ce qui se produit lorsque le bouton "Arrêt" de l'onduleur est enfoncé ou si l'alimentation de la batterie est extrêmement faible en cas de panne de l'alimentation principale. Pour mémoire, le script est:

#!/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

Cela me semble un peu inélégant étant donné qu'il inita la capacité intégrée de gérer les événements d'alimentation. Je dois répéter que j'utilise sysVinit sur Raspbian Jessie PAS le systemd par défaut pour cette version (pour des raisons de préférence personnelle et de familiarité).

Je voudrais, dans un premier temps, remplacer le script ci-dessus par quelque chose qui dit à init de faire son powerfailnowquand la broche devient basse - et de faire un powerokwaits'il revient par la suite haut. Finalement , je veux aussi interroger le port série et garder un œil sur les réponses à @rpi, @batet @upsqui renvoient les tensions actuelles sur le rail de 5 V du Pi, la batterie LiPo et les Upis possèdent entrée microUSB respectivement - de sorte que Pi peut donner une alerte sur / gérer une coupure de courant (cela devrait entraîner une powerfailaction init et laisser le Pi me signaler l'état de la perte de puissance, l'utilisateur - en supposant que je n'ai pas encore remarqué!)

Cependant, j'ai du mal à savoir comment les périphériques Linux UPS signalent initque les commandes powerfail\ powerwait\ powerfailnow\ powerokwaitdéfinies dans \etc\inittabdoivent être exécutées.

Quelqu'un peut-il me dire, par exemple, comment un onduleur «adulte» peut dire à un noyau Linux sur un PC normal que des événements de «puissance» se produisent et comment je pourrais reproduire le même dans ce système sur un Pi?

SlySven
la source
Merci @ Jacobm001 d'avoir repéré l'absence de la balise pour la partie Python de cette question, au cours des dernières heures, j'ai suivi un cours intensif dans la langue (je fais des progrès) mais il y a peu de temps, je ne 'ai pas connu mon Asp de mon coude ...
SlySven
Je suis également curieux de savoir comment le Pi (ou init) connaît les événements de puissance. J'espère que quelqu'un répondra bientôt.
PNDA
Je regarderais dans acpid et peut-être que vous pouvez changer votre script pour réagir quand quelque chose change (pin haut -> bas) au lieu d'interroger la valeur chaque seconde?
Diederik de Haas
2
@ PandaLion98 Le matériel Pi n'a aucun événement d'alimentation, il n'y a donc rien à en savoir. Si certains sont implémentés, init ne les connaîtra que si cela est dit, soit par le noyau (en raison d'un événement de pilote, qui dans le cas du pi serait probablement un pilote pour du matériel supplémentaire) ou via une application terrestre utilisateur.
goldilocks

Réponses:

5

Ah, ha! Certains paragraphes des pages de manuel de se init(8)réfèrent à l' interface dépréciée de l'écriture d'une valeur d'une lettre /etc/powerstatus(maintenant remplacée par /var/run/powerstatus), puis de l'envoi d' initun SIGPWRsignal; la lettre doit être l'une des suivantes:

  • Puissance « F » en panne: [l'alimentation principale est en panne et l'onduleur] fournit l'alimentation, exécute les entrées powerwaitet powerfail.
  • Power ' O ' kay: l'alimentation [principale] a été rétablie, exécutez l' powerokwaitentrée.
  • « L puissance OW »: la puissance échoue et l'onduleur a une batterie faible [critique], exécutez l' powerfailnowentrée.
Si le fichier spécifié n'existe pas ou contient autre chose que les lettres F, Oou L, init se comportera comme s'il avait lu la lettre F.

En dessous, vous trouverez l'avis:

L'utilisation de SIGPWRet /etc/powerstatusest déconseillée. Quelqu'un qui souhaite interagir avec initdoit utiliser le /run/initctlcanal de contrôle - voir le code source du sysvinitpaquet pour plus de documentation à ce sujet.

Donc, bien que cela puisse être une réponse, ce n'est pas la réponse - ensuite, je dois regarder le code source qui est conservé en tant que projet non GNU hébergé sur le site d'hébergement de GNU .

SlySven
la source
1

Je suppose que l'approche la plus propre serait d'avoir un pilote de périphérique noyau gérant GPIO27 et configuré pour recevoir une interruption lorsqu'elle devient faible. Le gestionnaire d'interruption avertirait init. La page http://elinux.org/RPi_Low-level_peripherals indique que Raspbian Wheezy prend en charge les interruptions GPIO.

Je m'excuse pour la réponse de mauvaise qualité, je n'ai pas regardé les pilotes gpio de Linux et comment les étendre / les améliorer. Je n'ai pas non plus recherché la méthode actuellement approuvée pour notifier init à partir d'un gestionnaire d'interruption. Espérons que ce message stimulera de meilleures réponses.

Tchad fermier
la source
Oui, une interruption semblerait mieux que de voter - Diederik de Haas l'a mentionné ci-dessus. Le centre de mon enquête à l'heure actuelle est cependant "Le gestionnaire d'interruption avertirait init ..." c'est ce mécanisme qui powerstatlaisse perplexe, le signal file / SIGPWR semble relativement simple et direct mais semble obsolète. J'essaie de découvrir maintenant l'utilisation réelle de la initctlpipe ...
SlySven
1

En fouillant dans le code source du SysV initdisponible sur le serveur Savannah de la Free Software Foundation, j'ai pu envoyer des demandes à mes RPi initen remplissant un struct init_requestcomme détaillé dans le initreq.hfichier d' en- tête. Plus précisément , cela a nécessité la magic, sleeptimeet, pour mes besoins les cmdchamps étant rempli, ce dernier étant mis à l' un des INIT_CMD_POWERFAIL, INIT_CMD_POWERFAILNOWou INIT_CMD_POWEROK.

Mon démon / programme qui doit être exécuté en tant qu'utilisateur avec la permission d'écrire dans le tube de contrôle d'init {à l'origine /dev/initctrlmais déplacé sur Debian et donc Raspbian vers /run/initctrl} a ensuite pu envoyer cette structure à initlaquelle a ensuite répondu de manière appropriée en répondant à la entrées suivantes dans /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

Remarque: cette interface - ou du moins la notification d'alimentation n'a PAS été adoptée par le nouveau fangled systemd- même si, ce qui pourrait être considéré comme un peu de programmation culte du fret, il essaie de s'assurer que le initctrltuyau existe. D'un autre côté, cela fait exactement ce que je veux qu'il fasse sur mon système RPi!

SlySven
la source
Bien que j'admire votre dévouement à ce problème, je ne peux m'empêcher de remarquer que vous avez passé beaucoup de temps à mettre en œuvre une solution qui est fonctionnellement équivalente à votre script initial et n'est même pas à l'épreuve du temps.
Dmitry Grigoryev
Eh bien, bien qu'il soit fonctionnellement équivalent au système initial, il utilise l'interface fournie recommandée plutôt que celle obsolète. En ce qui concerne l'épreuvage futur, n'est-ce pas aux personnes qui écrivent le futur système de mettre en œuvre l' interface connue du système qu'elles tentent de supplanter pour assurer la compatibilité descendante lorsque cela est possible.
SlySven
Après tout, obtenir une notification de panne de courant principale est assez important pour un système avec un onduleur, donc un gestionnaire de processus / système à moitié décent devrait être conscient de la façon dont son prédécesseur a fait les choses et rechercher d'autres processus utilisant cette API - une interface qui existe mais est ignoré semble un peu myope ... 8- / Selon le code sur: github.com/systemd/systemd/blob/master/src/initctl/initctl.c tout un onduleur indiquant systemdque l'alimentation principale est en panne de cette façon va enregistrer le message: "Requête UPS / alimentation initctl reçue. Ceci n'est pas implémenté dans systemd. Mettez à jour votre démon UPS!"
SlySven
"Ce n'est pas implémenté dans systemd. Mettez à niveau votre démon UPS" - c'est tout ce que vous devez savoir sur la compatibilité descendante sous Linux;)
Dmitry Grigoryev
L' initctlinterface de van Smoorenburg init a été déclarée privée et non pour des tiers par l'un des responsables du programme (à l'époque) en 2012. Miquel van Smoorenburg powerd, plus tard Tom Webster genpowerd, a utilisé à l'origine le /etc/powerstatusmécanisme.
JdeBP