Как init узнает о событиях power?

8

У меня есть Pi Model B Rev 2.0 (я думаю), и я собираюсь использовать его для системы домашней автоматизации. Поскольку у меня есть счетчик предоплаты по электроснабжению, у меня иногда заканчиваются электроны, чтобы обойти электроснабжение моего дома!

Чтобы избежать проблем, я приобрел ИБП в форме UPis Basic производства PiModules . Я настроил его так, чтобы я мог опрашивать напряжение питания через собственный последовательный порт Pi (не конфигурация по умолчанию, а поддерживаемая установка, описанная в руководстве ).

В настоящее время он использует выделенный вывод GPIO (вывод 13 на заголовке, я полагаю, GPIO27), и встроенный микроконтроллер использует его и скрипт python, запущенный из rc.local, чтобы сообщить Pi, shutdown -h nowкогда вывод выводится на низкий уровень - это происходит при нажатии кнопки «Выключение» ИБП или при критическом низком уровне заряда батареи в случае сбоя основного питания. Для записи скрипт:

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

Это кажется мне немного неутешительным, учитывая, что он initимеет встроенную возможность обрабатывать энергетические события. Я должен повторить, что я использую sysVinit на Raspbian Jessie, а не systemd по умолчанию для этого выпуска (по личным предпочтениям и из-за привычных причин).

Первоначально я хотел бы заменить вышеприведенный скрипт чем-то, что указывает init выполнить его, powerfailnowкогда пин становится низким, и делать, powerokwaitесли впоследствии он возвращает высокий. В конце концов , я также хочу , чтобы опрашивать последовательный порт и следить за ответами на @rpi, @batи @upsкоторые возвращают текущее напряжение на 5V поручень Пи, то LiPo батареи и UPis собственный вход MicroUSB соответственно - так что Pi может дать предупреждение о / обрабатывать сбой питания (это должно привести к powerfailдействию инициализации и позволить Pi сообщать мне о состоянии потери питания, пользователю - при условии, что я еще не заметил!)

Однако у меня возникают трудности с выяснением того, как устройства ИБП Linux сигнализируют о initтом, что powerfail\ powerwait\ powerfailnow\ powerokwaitкоманды, определенные в, \etc\inittabдолжны быть выполнены.

Кто-нибудь может мне посоветовать, например, как «взрослые» ИБП сообщают ядру Linux на обычном ПК, что происходят события «питания» и как я могу воспроизвести то же самое в этой системе на Pi?

SlySven
источник
Спасибо @ Jacobm001 за то, что я заметил отсутствие тега для Python-иш-части этого Вопроса, за последние несколько часов я проходил ускоренный курс по языку (у меня есть некоторые успехи), но недавно я бы не стал не знал моего Аспа с моего локтя ...
SlySven
Мне также любопытно, как Pi (или init) знает о событиях силы. Надеюсь, кто-то скоро ответит.
PNDA
Я бы посмотрел на acpid и, может быть, вы можете изменить свой сценарий, чтобы он реагировал на изменения (пин-код -> низкий) вместо опроса значения каждую секунду?
Дидерик де Хаас
2
@ PandaLion98 В оборудовании Pi нет событий питания, поэтому о них ничего не известно. Если некоторые из них реализованы, init узнает о них только в том случае, если об этом сообщит либо ядро ​​(из-за события драйвера, которое в случае с пи будет предположительно драйвером для некоторого дополнительного оборудования), либо через пользовательское наземное приложение.
Златовласка

Ответы:

5

Ах, ха! Некоторые пункты в справочных страницах init(8)относятся к изношенному интерфейсу записи значения один письма к /etc/powerstatus(теперь заменено /var/run/powerstatus) , а затем посылает initна SIGPWRсигнал; письмо должно быть одним из:

  • « F » больной мощностью: [главная сила оборвалась , и] ИБП обеспечивает питание, выполните powerwaitи powerfailзапись.
  • Power ' O ' kay: [основное] питание восстановлено, выполните powerokwaitзапись.
  • ' L ' ow power: происходит сбой питания, и у ИБП [критически] низкий уровень заряда батареи, выполните powerfailnowввод.
Если указанный файл не существует или содержит что-либо, кроме букв F, Oили Linit будет вести себя так, как будто он прочитал письмо F.

Ниже это рекомендация:

Использование SIGPWRи /etc/powerstatusне рекомендуется. Кто-то, кто хочет взаимодействовать, initдолжен использовать /run/initctlканал управления - см. Исходный код sysvinitпакета для получения дополнительной документации об этом.

Таким образом , в то время как это могло бы быть ответом не ответ - рядом, мне нужно посмотреть на исходный код , который хранится в проекте , не GNU размещенного на хостинг сайта ГНУ .

SlySven
источник
1

Я полагаю, что самым чистым подходом было бы иметь драйвер устройства ядра, управляющий GPIO27 и настроенный на получение прерывания, когда оно падает. Обработчик прерываний уведомит init. На странице http://elinux.org/RPi_Low-level_peripherals говорится, что Распбиан Уизи поддерживает прерывания GPIO.

Я извиняюсь за некачественный ответ, я не смотрел на драйверы gpio для Linux и как их расширять / улучшать. Я также не посмотрел текущий одобренный метод уведомления init из обработчика прерываний. Надеюсь, этот пост будет стимулировать лучшие ответы.

Чад Фармер
источник
Да, прерывание показалось бы лучше, чем опрос - Дидерик де Хаас упомянул об этом выше. В настоящее время мое исследование сосредоточено на том, что «обработчик прерываний будет уведомлять init ...», это тот механизм, который озадачивает, powerstatсигнал file / SIGPWR выглядит относительно простым и понятным, но кажется устаревшим. Я пытаюсь выяснить сейчас о реальном использовании initctlтрубы ...
SlySven
1

Изучив исходный код SysV, initдоступный на сервере Savannah Фонда Свободного Программного Обеспечения, я смог отправить запросы на мои RPi, initзаполнив, struct init_requestкак описано в initreq.hзаголовочном файле. В частности , это требуется magic, sleeptimeи для моих целей cmdполя заполняются из, с последним набором бытия к одному из INIT_CMD_POWERFAIL, INIT_CMD_POWERFAILNOWили INIT_CMD_POWEROK.

Мой демон / программа, которую нужно запустить как пользователь с правами на запись в канал управления init (первоначально он был /dev/initctrlперенесен в Debian и, следовательно, в Raspbian в /run/initctrl), смог затем отправить эту структуру, на initкоторую затем соответствующим образом отреагировал, ответив на запрос. следующие записи в /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

Примечание: этот интерфейс - или, по крайней мере, уведомление источника питания НЕ было принято новым fangled systemd- даже при том, что, что может быть расценено как немного культового программирования, он действительно пытается гарантировать, что initctrlканал существует. С другой стороны, это именно то, что я хочу сделать в моей системе RPi!

SlySven
источник
Хотя я восхищаюсь вашей приверженностью этой вашей проблеме, я не могу не заметить, что вы потратили значительное количество времени на реализацию решения, которое функционально эквивалентно вашему первоначальному сценарию и даже не является доказательством на будущее.
Дмитрий Григорьев
Ну, хотя он функционально эквивалентен исходной системе, он использует рекомендованный интерфейс, а не устаревший. Что касается проверки на будущее, не должны ли люди, пишущие будущую систему, реализовать известный интерфейс системы, которую они пытаются заменить, чтобы обеспечить обратную совместимость, где это возможно.
SlySven
В конце концов, получение уведомления о сбое основного питания очень важно для системы с ИБП, поэтому полуадекватный менеджер процессов / систем должен знать о том, как его предшественник работает, и следить за другими процессами, используя этот API - интерфейс, который существует , но игнорируется , кажется , немного близорук ... 8- / в соответствии с кодом по адресу: github.com/systemd/systemd/blob/master/src/initctl/initctl.c все ИБП , рассказывающие о systemdтом , что главная сила не смогла таким образом будет регистрироваться сообщение: «Получен запрос UPS / power initctl. Это не реализовано в systemd. Обновите ваш демон UPS!»
SlySven
«Это не реализовано в systemd. Обновите ваш демон UPS» - это все, что вам нужно знать о обратной совместимости в Linux;)
Дмитрий Григорьев,
initctlИнтерфейс ван Smoorenburg INIT был объявлен приватным и не для третьих лиц одного из (тогда) Сопровождающих программ обратно в 2012 году Микель вана Smoorenburg - х powerd, а позже Том Вебстер genpowerd, первоначально использовал /etc/powerstatusмеханизм.
JdeBP