User Tools

Site Tools


lab:2015:services

Servicii

Init

În procesul de boot, după ce kernel-ul s-a inițializat, trebuie pornit ansamblul de procese ce vor rula în user-space pe parcursul sesiunii curente. Pentru a realiza acest lucru, kernel-ul va porni daemon-ul init. În cazul în care kernel-ul nu reușeste sa pornească acest proces, se va produce ceea ce se cheamă “kernel panic”.

Init este primul proces pornit, rulează în user-space, are în mod normal PID-ul 1, va fi părintele tuturor celorlalte procese și va adopta orice proces orfan. Pentru a evita posibile accidente, init este implementat astfel încât sa ignore majoritatea semnalelor, chiar și pe cele trimise de procese rulate cu privilegii. Singurele semnale pe care acest proces le tratează sunt cele pentru care există handlere instalate explicit. Există totuși distribuții ce conțin astfel de handlere pentru a implementa comportamente asemănătoare cu halt sau shutdown atunci când init primește SIGTERM.

Odată ce a fost pornit procesul init, acesta are rolul ca mai departe să pornească restul proceselor din sesiune. De-a lungul timpului au existat diverse implementări ale acestei operații. Cea mai simplă abordare este cea folosită pe sistemele BSD. Acestea apelează un script ce se află în /etc/rc și conține lista programelor ce trebuiesc pornite. Init nu face altceva decât să ruleze acest script. Alte implementări se bazează pe evenimente asincrone (precum Upstart) sau daemoni specializați meniți să înglobeze și să înlocuiască init-ul clasic și script-urile necesare acestuia (systemd).

System V

RaspberryPi folosește modul de inițializare System V. Această implementare introduce conceptul de runlevel. Un runlevel descrie starea de execuție în care se află o mașină și este caracterizat de serviciile care sunt disponibile. În general, pentru fiecare sistem, există un runlevel default în care acesta pornește. Deși standardul Unix definește clar aceste runlevel-uri, cel default pentru multi-user session cu suport grafic diferă de la un sistem de operare la altul.

Pentru a vedea în ce runlevel este sistemul vostru, executați comanda who -r într-un terminal. Puteți verifica dacă RaspberryPi și desktop-ul rulează în același runlevel.

Implementarea System V presupune existența fișierului /etc/inittab. Aici, init caută informația legată de default runlevel: o intrare în fișier de forma :initdefault:. Dacă aceasta nu există, se va deschide o consolă din care utilizatorul își poate alege runlevel-ul. Procesele ce vor fi pornite depind de runlevel-ul ales.

Script-urile și programele ce se doresc a fi rulate de către init trebuie plasate în directorul /etc/init.d. Toate aceste script-uri folosesc un schelet standard care se găsește in fișierul /etc/init.d/skeleton:

schelet
#! /bin/sh
...
 
case "$1" in
 start)
   ...
 
 stop)
   ...
 
 status)
   ...
 
 *)
   ...
esac
 
exit 0

Observați că parametrul acestor script-uri corespunde cu parametrii pe care îi putem pasa comenzii Linux service.

Tot în /etc se găsesc o serie de directoare rcN.d, unde N este un număr corespunzător unui runlevel. Aceste directoare conțin fișiere cu numele de forma: [S|K][0-9][0-9]<nume_script>. Toate aceste fișiere sunt în realitate link-uri simbolice la script-urile din /etc/init.d. Aceasta este modalitatea de a specifica în System V ce program dorim să rulăm într-un anumit runlevel.

Instalarea unui serviciu din /etc/init.d în directoarele corespunzătoare runlevel-urilor în care va rula serviciul se face cu comanda update-rc.d <nume serviciu> defaults. Dezactivarea unui serviciu se face cu comanda update-rc.d <nume serviciu> remove.

  • S înseamnă că dorim rularea la intrarea în acel runlevel, iar K înseamna că dorim rularea atunci când părăsim acel runlevel.
  • numărul de două cifre ce urmează după S sau K reprezintă prioritatea script-ului. Deoarece link-urile din cadrul aceluiași runlevel sunt rulate alfabetic, cele cu un număr mai mic vor avea o prioritate mai mare.

Ca și init, toate aceste servicii vor rula în user-space, în modul neprivilegiat. În user-space, fiecare proces rulează în propriul spațiu de memorie și nu va putea accesa memoria altor procese. Singurul mod în care procesele vor putea comunica este prin mecanismele de IPC specifice sistemului de operare.

CGI

Serviciul pe care îl vom pune la dispoziţie pe RaspberryPi in acest laborator este un server web. Serverul web poate genera dinamic pagini. Aceasta se realizează prin execuţia de scripturi aflate în directorul cgi-bin din rădăcina serverului, folosindu-se o metodă standard numită Common Gateway Interface. CGI presupune execuţia unui script specificat în cererea HTTP (identificat ca orice alt fişier de pe server), care poate primi parametri dintr-un formular web pe stdin şi prin variabilele de mediu, respectiv poate genera pagini dinamice scriind pe stdout.

Exemplu:

În directorul cgi­-bin din root-ul serverului web creăm un fişier executabil numit 1.sh. Conținutul acestui fișier este de forma:

1.sh
#!/bin/sh
echo "Content-­type: text/html"
echo ""
echo "<HTML><HEAD><TITLE>Sample CGI Output</TITLE></HEAD>"
echo "<BODY><p>"
echo ­-n "Generated "
date
echo "</p><pre>"
env
echo "</pre>"
echo "</BODY></HTML>"

Pentu executare, în browser se scrie http://<ip>/cgi­-bin/1.sh .

Metoda CGI permite execuţia oricărui script pe server, putându-se astfel efectua orice operaţie. În mod normal s-ar restricţiona accesul la sistem spre exemplu rulând serverul web sub un utilizator fără privilegii.

Exemplu de cod HTML:

<form method="post" action="/cgi-bin/on.sh">
<input type="submit" name="on" value="LED On" />
</form>

Chiar dacă scripturile nu generează ieşire, browserul le va interpreta ca downloaduri goale, pentru că a emis o cerere şi aşteaptă un fişier ca răspuns, mecanismul CGI se desfăşoară doar pe server, fără ştirea sau interesul browserului. Trebuie ca ele să trimită un răspuns de tip redirect la pagina iniţială pentru a obţine o interfaţă rezonabilă. Aceasta se face adăugând în scripturi următorul cod:

echo "HTTP/1.0 302 OK"
echo "Location: /"
echo

LED

Pentru a aprinde respectiv stinge un LED se poate folosi infrastructura sysfs, care presupune crearea de către kernel a unui arbore virtual de fișiere care oferă informații și control asupra unor dispozitive.

Astfel, pentru a controla singurul LED controlabil de pe placă (led-ul ACT - activity), se va folosi interfața din /sys/class/leds/led0/. Fiecare scriere sau citire într-un/dintr-un fișier din acest folder are o anumită semnificație. brightness controlează nivelul de luminozitate al LED-ului (în cazul acestui LED 0 înseamnă închis și orice număr între 1 și 255 înseamnă aprins), trigger desemnează o sursă de informație pe care LED-ul să o urmărească.

Spre exemplu:

cat /sys/class/leds/led0/trigger

afișează toate modurile de auto-trigger ale LED-ului, cu paranteze pătrate ('[' și ']') în jurul modului curent. Modul curent se selectează scriind în fișier textul unuia dintre moduri. În mod default este selectată sursa mmc0 pe LED, ceea ce înseamnă că LED-ul va pulsa la activități de scriere/citire pe cardul SD.

Pentru a aprinde LEDul ACT, se poate scrie în brightness, atâta vreme cât este selectat modul none de trigger, altfel valoarea scrisă va fi cu siguranță suprascrisă imediat.

Exerciții

1. (2p) LED - Creaţi un fişier on.sh, faceţi-l executabil şi aprindeţi din el un LED de pe placă. Creaţi un fişier similar off.sh pentru stingerea respectivului LED.

Nu uitați să dați disable la trigger. Dacă nu dați disable, script-urile care modifică starea ledului nu vor avea niciun efect. Pentru a da disable, trebuie sa scrieți comanda într-un fișier pe care îl executați cu drept de sudo

2. (2p) Creați un serviciu în runlevel-ul 2 care să aprindă ledul pentru parametrul start și să stingă ledul pentru parametrul stop.

Consultați secțiunea System V pentru a vedea cum se creează script-ul.

Fișierul skeleton conține următoarea linie: ”[ -x “$DAEMON” ] || exit 0”. Ștergeți-o.

3. (2p) HTTP - Instalați utilitarele necesare pentru a putea rula un server web pe portul 80.

  • Instalați lighttpd.
  • Navigați pe pagina default.
  • Urmăriți instrucțiunile pentru a crea o pagină nouă cu conținutul vostru și pentru a activa scripturile cgi.
  • Folosiți netstat ca să aflați cum se cheamă procesul cu server-ul web.
  • Folosiți ps ca să aflați cum se cheamă user-ul sub care rulează server-ul web.

4. (2p) CGI - Creaţi în index.html (în rădăcina ierarhiei web) două formulare web cu metoda POST, conţinând un singur buton submit fiecare. Un buton va aprinde LED-ul, iar celălalt buton îl va stinge.

5. (2p) PHP - Instalați php, varianta CGI (cu binar) (Hint: apt-cache search)

  • Activați php așa cum ați activat cgi, dar uitați-vă în folder-ul /etc/lighttpd/conf-available după numele modulului.
  • Testați instalarea de PHP cu
phpinfo.php
<?php
phpinfo();
?>
  • Pentru un Hello World cu scripting în PHP, rulați scriptul:
index.php
<html><body>
<?php
$cpuinfo = `cat /proc/cpuinfo`;
echo $cpuinfo;
?>
</body></html>
  • Adăugați informații despre parametrii pe care îi primește kernel-ul la pornire
  • Adăugați informații pe pagină despre device-ul pe care este montat '/'

Resurse

lab/2015/services.txt · Last modified: 2016/10/13 23:44 by Dan Dragomir