¿Cómo llega init a conocer los eventos de poder?

8

Tengo un Pi Model B Rev 2.0 (creo) y tengo la intención de usarlo para un sistema de automatización del hogar. Como tengo un medidor de prepago en mi suministro de electricidad, ocasionalmente me quedo sin electrones para recorrer el suministro de energía de mi casa.

Para evitar problemas, he obtenido un UPS en forma de UPis Basic hecho por PiModules . Lo configuré para que pueda sondear los voltajes de suministro a través del puerto serie del propio Pi (no la configuración predeterminada sino una configuración compatible documentada en el manual ).

En la actualidad, usa un pin GPIO dedicado (pin 13 en el encabezado, GPIO27, creo) y el microcontrolador incorporado lo usa y un script de Python que se ejecuta desde rc.local para indicarle al Pi shutdown -h nowcuándo se baja el pin. que ocurre cuando se presiona el botón "Apagar" del UPS o si el suministro de la batería se agota críticamente en caso de falla del suministro principal. Para el registro el guión es:

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

Esto me parece un poco poco elegante dado que inittiene la capacidad incorporada de manejar eventos de energía. Debo reiterar que estoy usando sysVinit en Raspbian Jessie NO el systemd predeterminado para esa versión (por razones de preferencia personal y familiaridad).

Inicialmente, me gustaría reemplazar el script anterior con algo que le indique a init que haga su función powerfailnowcuando el pin powerokwaitesté bajo, y que haga un si posteriormente regresa alto. Eventualmente también quiero sondear el puerto serie y mantener un ojo en las respuestas a @rpi, @baty @upsque devuelven las tensiones actuales en el carril 5V del Pi, la batería Li-Po y los Upis son dueños de entrada microUSB, respectivamente - de modo que el Pi puede dar una alerta de / manejar una falla de energía (debería resultar en una powerfailacción de inicio y dejar que el Pi me informe el estado de la pérdida de energía, el usuario, ¡suponiendo que no lo haya notado!)

Sin embargo estoy teniendo dificultades para encontrar la manera de dispositivos Linux UPS señal de initque el powerfail\ powerwait\ powerfailnow\ powerokwaitcomandos se define en \etc\inittabdebe ser realizada.

¿Alguien puede aconsejarme, por ejemplo, cómo UPS "adulto" le dice a un kernel de Linux en una PC normal que están ocurriendo eventos de "alimentación" y cómo puedo reproducir lo mismo en este sistema en un Pi?

SlySven
fuente
Gracias @ Jacobm001 por detectar la ausencia de la etiqueta para la parte Python-ish de esta pregunta, en las últimas horas he estado realizando un curso intensivo en el idioma (estoy avanzando un poco) pero hace poco tiempo no lo haría he conocido mi Asp desde mi codo ...
SlySven
También tengo curiosidad por saber cómo Pi (o init) sabe acerca de los eventos de poder. Esperemos que alguien responda pronto.
PNDA
Buscaría en acpid y tal vez puedas cambiar tu script para reaccionar cuando algo cambie (pin alto -> bajo) en lugar de sondear el valor cada segundo.
Diederik de Haas
2
@ PandaLion98 El hardware de Pi no tiene eventos de potencia, por lo que no se sabe nada sobre ellos. Si se implementan algunos, init solo los conocerá si se lo indica, ya sea por el núcleo (debido a un evento de controlador, que en el caso del pi presumiblemente sería un controlador para algún hardware adicional) o mediante una aplicación de tierra de usuario.
Ricitos de oro

Respuestas:

5

Ah, ja! Algunos párrafos en las páginas de manual se init(8)refieren a la interfaz depreciada de escribir un valor de una letra /etc/powerstatus(ahora reemplazado por /var/run/powerstatus) y luego enviar inituna SIGPWRseñal; la carta debe ser una de:

  • Energía en estado ' F ': [la alimentación principal ha fallado y] el UPS está proporcionando la energía, ejecuta las entradas powerwaity powerfail.
  • Potencia ' O ' kay: se restableció la alimentación [principal], ejecute la powerokwaitentrada.
  • ' L ' ow power: el poder está fallando y el UPS tiene una batería [críticamente] baja, ejecute la powerfailnowentrada.
Si el archivo especificado no existe o contiene algo más que las letras F, Oo Linit se comportará como si hubiera leído la letra F.

Debajo de esto está el aviso:

Uso SIGPWRy /etc/powerstatusse desaconseja. Alguien con quien desee interactuar initdebe usar el /run/initctlcanal de control; consulte el código fuente del sysvinitpaquete para obtener más documentación al respecto.

Entonces, si bien esta podría ser una respuesta, no es la respuesta; a continuación, tengo que mirar el código fuente que se mantiene como un proyecto no GNU alojado en el sitio de alojamiento de GNU .

SlySven
fuente
1

Supongo que el enfoque más limpio sería tener un controlador de dispositivo kernel que administre GPIO27 y que se configure para recibir una interrupción cuando baja. El manejador de interrupciones notificaría a init. La página http://elinux.org/RPi_Low-level_peripherals dice que Raspbian Wheezy admite interrupciones GPIO.

Pido disculpas por la respuesta de baja calidad, no he mirado los controladores gpio de Linux y cómo extenderlos / mejorarlos. Tampoco he buscado el método aprobado actual para notificar a init desde un controlador de interrupciones. Esperemos que esta publicación estimule mejores respuestas.

Chad Farmer
fuente
Sí, una interrupción parecería mejor que una encuesta: Diederik de Haas lo mencionó anteriormente. Sin embargo, el foco de mi investigación en el presente es "El controlador de interrupciones notificaría a init ..." es ese mecanismo el que es desconcertante, la powerstatseñal del archivo / SIGPWR parece relativamente simple y directa, pero parece estar en desuso. Estoy tratando de averiguar ahora sobre el uso real de la initctltubería ...
SlySven
1

Al profundizar en el código fuente del SysV initdisponible desde el servidor Savannah de la Free Software Foundation, pude enviar solicitudes a mis RPI initcompletando una struct init_requestcomo se detalla en el initreq.harchivo de encabezado. Específicamente esto requería el magic, sleeptimey, para mis propósitos los cmdcampos siendo llenada, siendo este último el conjunto a una de INIT_CMD_POWERFAIL, INIT_CMD_POWERFAILNOWo INIT_CMD_POWEROK.

Mi demonio / programa que debe ejecutarse como usuario con el permiso para escribir en la tubería de control de inicio {originalmente en /dev/initctrlpero movido en Debian y por lo tanto Raspbian a /run/initctrl} pudo enviar esa estructura a la initque luego respondió adecuadamente respondiendo al siguientes entradas en /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: esta interfaz, o al menos la notificación de la fuente de alimentación NO ha sido adoptada por el nuevo fracasado systemd, aunque, por lo que podría considerarse como un poco de programación de culto de carga , intenta asegurarse de que la initctrltubería exista. ¡Por otro lado, esto hace exactamente lo que quiero que haga en mi sistema RPi!

SlySven
fuente
Si bien admiro su dedicación a este problema suyo, no puedo evitar notar que ha dedicado una cantidad significativa de tiempo a implementar una solución que sea funcionalmente equivalente a su script inicial y que ni siquiera sea una prueba futura.
Dmitry Grigoryev
Bueno, si bien es funcionalmente equivalente al sistema inicial, utiliza la interfaz proporcionada recomendada en lugar de la obsoleta. En cuanto a las pruebas futuras, ¿no corresponde a las personas que escriben el sistema futuro implementar la interfaz conocida del sistema que intentan suplantar para garantizar la compatibilidad con versiones anteriores siempre que sea posible?
SlySven
Después de todo, recibir una notificación de falla de energía principal es bastante importante para un sistema con un UPS, por lo que un administrador de proceso / sistema medio decente debe ser consciente de cómo hizo su predecesor y buscar otros procesos utilizando esa API, una interfaz que existe pero se ignora parece un poco miope ... 8- / De acuerdo con el código en: github.com/systemd/systemd/blob/master/src/initctl/initctl.c todo un UPS dice systemdque la alimentación principal ha fallado de esta manera se registrará el mensaje: "Recibió UPS / solicitud de inicio de alimentación. Esto no está implementado en systemd. ¡Actualice su demonio UPS!"
SlySven
"Esto no está implementado en systemd. Actualice su demonio UPS" - eso es todo lo que necesita saber sobre la compatibilidad con versiones anteriores en Linux;)
Dmitry Grigoryev
La initctlinterfaz con van Smoorenburg init fue declarada privada y no para terceros por uno de los (entonces) mantenedores del programa en 2012. Miquel van Smoorenburg powerd, más tarde Tom Webster genpowerd, usó originalmente el /etc/powerstatusmecanismo.
JdeBP