Bagaimana init bisa mengetahui tentang peristiwa-peristiwa penting?

8

Saya memiliki Pi Model B Rev 2.0 (saya pikir) dan saya bermaksud menggunakannya untuk sistem Home Automation. Karena saya memiliki meteran prabayar pada pasokan listrik saya, saya kadang-kadang kehabisan elektron untuk berkeliling Pasokan Listrik rumah saya!

Untuk menghindari masalah, saya telah memperoleh UPS dalam bentuk UPis Basic yang dibuat oleh PiModules . Saya telah mengonfigurasinya sehingga saya dapat mensurvei tegangan suplai melalui port serial Pi sendiri (bukan konfigurasi default tetapi set-up yang didukung didokumentasikan dalam manual ).

Saat ini menggunakan pin GPIO khusus (pin 13 di header, GPIO27 saya percaya) dan micro-controller built-in menggunakan itu dan skrip python berjalan dari rc.local untuk memberitahu Pi shutdown -h nowketika pin diambil rendah - yang terjadi ketika tombol "Shutdown" UPS ditekan atau jika pasokan baterai hampir habis jika terjadi kegagalan pasokan utama. Sebagai catatan, skripnya adalah:

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

Hal ini mengejutkan saya karena saya sedikit canggung karena initmemiliki kemampuan bawaan untuk menangani peristiwa daya. Saya harus menegaskan kembali bahwa saya menggunakan sysVinit pada Raspbian Jessie BUKAN systemd default untuk rilis itu (untuk preferensi pribadi dan alasan keakraban).

Saya ingin, pada awalnya, mengganti skrip di atas dengan sesuatu yang memberitahu init untuk melakukannya powerfailnowketika pin menjadi rendah - dan untuk melakukan powerokwaitjika kemudian kembali tinggi. Akhirnya saya juga ingin polling port serial dan mengawasi tanggapan terhadap @rpi, @batdan @upsyang mengembalikan tegangan arus pada rel 5V Pi, baterai LiPo dan input microUsb UP UP masing-masing - sehingga Pi dapat memberi peringatan pada Saya menangani kegagalan daya (seharusnya menghasilkan powerfailtindakan init dan membiarkan Pi melaporkan status kehilangan daya kepada saya, pengguna - dengan asumsi saya belum siap memperhatikan!)

Namun saya mengalami kesulitan mencari tahu bagaimana perangkat UPS Linux memberi sinyal initbahwa powerfail\ powerwait\ powerfailnow\ powerokwaitperintah yang didefinisikan \etc\inittabharus dilakukan.

Adakah yang bisa memberi tahu saya, misalnya, bagaimana UPS "dewasa" memberi tahu kernel Linux pada PC normal bahwa peristiwa "kekuatan" terjadi dan bagaimana saya dapat mereproduksi hal yang sama dalam sistem ini pada Pi?

SlySven
sumber
Terima kasih @ Jacobm001 karena melihat tidak adanya tag untuk bagian Python-ish dari Pertanyaan ini, dalam beberapa jam terakhir saya telah menjalani kursus kilat dalam bahasa (saya sedang membuat kemajuan) tetapi beberapa saat yang lalu saya tidak mau telah mengetahui Asp saya dari Siku ...
SlySven
Saya juga ingin tahu bagaimana Pi (atau init) tahu tentang peristiwa kekuasaan. Semoga seseorang segera menjawab.
PNDA
Saya akan melihat acpid dan mungkin Anda dapat mengubah skrip Anda untuk bereaksi ketika sesuatu berubah (pin tinggi -> rendah) daripada menghitung nilai setiap detik?
Diederik de Haas
2
@ PandaLion98 Perangkat keras Pi tidak memiliki acara daya, jadi tidak ada yang diketahui tentang mereka. Jika beberapa diimplementasikan, init hanya akan tahu tentang mereka jika diberi tahu, baik oleh kernel (karena peristiwa driver, yang dalam kasus pi mungkin akan menjadi driver untuk beberapa perangkat keras tambahan) atau melalui aplikasi pengguna tanah.
goldilocks

Jawaban:

5

Ah, ha! Beberapa paragraf di halaman manual untuk init(8)mengacu pada terdepresiasi antarmuka penulisan nilai satu huruf ke /etc/powerstatus(sekarang diganti dengan /var/run/powerstatus) dan kemudian mengirimkan initsebuah SIGPWRsinyal; surat itu harus salah satu dari:

  • ' F ' sakit kekuasaan: [daya utama telah gagal dan] UPS menyediakan daya, jalankan powerwaitdan powerfailentri.
  • Daya ' O ' kay: daya [utama] telah dipulihkan, jalankan powerokwaitentri.
  • ' L ' ow power: listriknya mati dan UPS memiliki baterai lemah, jalankan powerfailnowentri.
Jika file yang ditentukan tidak ada atau mengandung apa pun selain huruf F, Oatau L, init akan berperilaku seolah-olah telah membaca surat itu F.

Di bawah ini adalah penasehat:

Penggunaan SIGPWRdan /etc/powerstatustidak disarankan. Seseorang yang ingin berinteraksi initharus menggunakan /run/initctlsaluran kontrol - lihat kode sumber sysvinitpaket untuk dokumentasi lebih lanjut tentang ini.

Jadi sementara ini mungkin jawaban itu bukan yang jawaban - berikutnya, saya perlu melihat kode sumber yang disimpan sebagai proyek non-GNU host di situs GNU hosting .

SlySven
sumber
1

Saya kira pendekatan yang paling bersih adalah memiliki driver perangkat kernel mengelola GPIO27 dan mengatur untuk menerima interupsi ketika semakin rendah. Penangan interrupt akan memberi tahu init. Halaman http://elinux.org/RPi_Low-level_peripherals mengatakan bahwa Raspbian Wheezy mendukung interupsi GPIO.

Saya minta maaf atas respons berkualitas rendah, saya belum melihat driver gpio Linux dan cara memperluas / meningkatkannya. Saya juga belum melihat metode yang disetujui saat ini untuk memberi tahu init dari dalam interrupt handler. Semoga postingan ini akan merangsang respons yang lebih baik.

Petani Chad
sumber
Ya, interupsi akan tampak lebih baik daripada polling - Diederik de Haas menyebutkan itu di atas. Fokus penyelidikan saya saat ini adalah " powerstatPenginterupsi interupsi akan memberi tahu init ..." itu adalah mekanisme yang membingungkan, sinyal file / SIGPWR terlihat relatif sederhana dan mudah tetapi tampaknya sudah usang. Saya mencoba mencari tahu sekarang tentang penggunaan initctlpipa di kehidupan nyata ...
SlySven
1

Dengan mempelajari kode sumber SysV yang inittersedia dari server Savannah Free Software Foundation, saya dapat mengirim permintaan ke RPi saya initdengan mengisi struct init_requestrincian initreq.hfile header. Secara khusus ini membutuhkan magic, sleeptimedan, untuk tujuan saya, cmdbidang yang diisi, dengan yang terakhir diatur ke salah satu INIT_CMD_POWERFAIL, INIT_CMD_POWERFAILNOWatau INIT_CMD_POWEROK.

Daemon / program saya yang perlu dijalankan sebagai pengguna dengan izin untuk menulis ke pipa kontrol init {awalnya di /dev/initctrltetapi pindah di Debian dan dengan demikian Raspbian ke /run/initctrl} kemudian dapat mengirim struktur inityang kemudian ditanggapi dengan tepat dengan menanggapi entri berikut dalam /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

Catatan: antarmuka ini - atau setidaknya pemberitahuan catu daya TIDAK diadopsi oleh yang baru ketinggalan jaman systemd- meskipun, oleh apa yang mungkin dianggap sebagai sedikit pemrograman pemujaan kargo, ia mencoba memastikan bahwa initctrlpipa itu ada. Di sisi lain, ini melakukan persis seperti yang saya inginkan pada sistem RPi saya!

SlySven
sumber
Meskipun saya mengagumi dedikasi Anda untuk masalah Anda ini, saya tidak bisa tidak menyadari bahwa Anda telah menghabiskan banyak waktu untuk mengimplementasikan solusi yang secara fungsional setara dengan skrip awal Anda dan bahkan bukan bukti di masa depan.
Dmitry Grigoryev
Yah, meskipun secara fungsional setara dengan sistem awal, ia menggunakan antarmuka yang disarankan daripada yang sudah usang. Mengenai pembuktian di masa depan, bukankah orang-orang yang menulis sistem di masa depan untuk mengimplementasikan antarmuka sistem yang diketahui mereka berusaha untuk menggantikan untuk memastikan kompatibilitas ke belakang jika memungkinkan.
SlySven
Lagi pula, mendapatkan pemberitahuan tentang kegagalan daya utama cukup penting untuk sistem dengan UPS sehingga manajer proses / sistem yang setengah layak harus mengetahui bagaimana pendahulunya melakukan hal-hal dan mencari proses lain menggunakan API - antarmuka yang ada tetapi diabaikan tampaknya agak picik ... 8- / Menurut kode di: github.com/systemd/systemd/blob/master/src/initctl/initctl.c semua UPS mengatakan systemdbahwa daya utama gagal cara ini akan mencatat pesan: "Menerima permintaan UPS / daya initctl. Ini tidak diterapkan dalam systemd. Tingkatkan daemon UPS Anda!"
SlySven
"Ini tidak diterapkan di systemd. Tingkatkan daemon UPS Anda" - hanya itu yang perlu Anda ketahui tentang kompatibilitas mundur di Linux;)
Dmitry Grigoryev
The initctlantarmuka untuk van Smoorenburg init dinyatakan pribadi dan tidak untuk pihak ketiga oleh salah satu (kemudian) pengelola program kembali pada tahun 2012. Miquel van Smoorenburg ini powerd, kemudian Tom Webster genpowerd, awalnya menggunakan /etc/powerstatusmekanisme.
JdeBP