Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so2:laboratoare:lab06 [2017/03/26 11:47]
octavian.purdila [Workqueues] 4.9 updates
so2:laboratoare:lab06 [2018/04/29 21:37] (current)
silvia.pripoae [Workqueues]
Line 53: Line 53:
 ==== Softirq-uri ==== ==== Softirq-uri ====
  
-Softirq-urile nu pot fi folosite de către device drivere, ele sunt rezervate pentru diverse subsisteme ale kernelului. Din această cauză există un număr fix de softirq-uri definite la momentul compilării. Pentru kernelul [[http://lxr.free-electrons.com/​source/​include/​linux/​interrupt.h?v=4.9#L435|4.9]] avem următoarele softirq-uri:​+Softirq-urile nu pot fi folosite de către device drivere, ele sunt rezervate pentru diverse subsisteme ale kernelului. Din această cauză există un număr fix de softirq-uri definite la momentul compilării. Pentru kernelul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​interrupt.h#​L458|4.15]] avem următoarele softirq-uri:​
  
 <code c> <code c>
-enum +enum {
-{+
         HI_SOFTIRQ=0,​         HI_SOFTIRQ=0,​
         TIMER_SOFTIRQ,​         TIMER_SOFTIRQ,​
Line 79: Line 78:
   *''​BLOCK_IOPOLL_SOFTIRQ''​ - folosit de către subsistemul de IO pentru a crește performanța în momentul în care handler-ul iopoll este invocat;   *''​BLOCK_IOPOLL_SOFTIRQ''​ - folosit de către subsistemul de IO pentru a crește performanța în momentul în care handler-ul iopoll este invocat;
   *''​SCHED_SOFTIRQ''​ - load balancing;   *''​SCHED_SOFTIRQ''​ - load balancing;
-  *''​HRTIMER_SOFTIRQ''​ - implementarea timerelor de mare precizie ((jiffie -- începând cu 2.6.21, arhitectura tratării timerelor a fost complet rescrisă; se așteaptă ca in viitor și jiffie-ul să dispară. Pentru detalii consultați [[http://​lwn.net/​Articles/​223185/​|Clockevents and dyntick]] și  [[http://lxr.free-electrons.com/​source/​Documentation/​timers/​hrtimers.txt?v=3.13|Documentation/​timers/​hrtimers.txt]]));​ +  *''​HRTIMER_SOFTIRQ''​ - implementarea timerelor de mare precizie ((jiffie -- începând cu 2.6.21, arhitectura tratării timerelor a fost complet rescrisă; se așteaptă ca in viitor și jiffie-ul să dispară. Pentru detalii consultați [[http://​lwn.net/​Articles/​223185/​|Clockevents and dyntick]] și  [[https://elixir.bootlin.com/​linux/​v3.15/​source/​Documentation/​timers/​hrtimers.txt|Documentation/​timers/​hrtimers.txt]]));​ 
-  *''​RCU_SOFTIRQ''​ - implementarea mecanismelor de tip RCU ((read-copy update -- un mecanism prin care operațile distructive (ex: ștergerea unui element dintr-o listă înlănțuită) se fac în două etape: eliminarea referințelor către datele de șters și ștergerea propriu-zisă,​ care se face numai după ce este sigur că nimeni nu le mai folosește. Avantajul este că accesarea datelor se poate face fără sincronizare. Pentru mai multe informații citiți documentația [[http://lxr.free-electrons.com/​source/​Documentation/​RCU/​rcu.txt?v=4.9|RCU]] din kernelul Linux)).+  *''​RCU_SOFTIRQ''​ - implementarea mecanismelor de tip RCU ((read-copy update -- un mecanism prin care operațile distructive (ex: ștergerea unui element dintr-o listă înlănțuită) se fac în două etape: eliminarea referințelor către datele de șters și ștergerea propriu-zisă,​ care se face numai după ce este sigur că nimeni nu le mai folosește. Avantajul este că accesarea datelor se poate face fără sincronizare. Pentru mai multe informații citiți documentația [[https://elixir.bootlin.com/​linux/​v4.15/​source/​Documentation/​RCU/​rcu.txt|RCU]] din kernelul Linux)).
  
 Prioritare sunt softirq-urile de tip HI_SOFTIRQ, urmate în ordine de celelalte softirq-uri definite; cele de tip ''​RCU_SOFTIRQ''​ au cea mai mică prioritate. Prioritare sunt softirq-urile de tip HI_SOFTIRQ, urmate în ordine de celelalte softirq-uri definite; cele de tip ''​RCU_SOFTIRQ''​ au cea mai mică prioritate.
Line 87: Line 86:
 ==== Tasklets ==== ==== Tasklets ====
  
-Un tasklet este caracterizat prin structura [[http://lxr.free-electrons.com/​source/​include/​linux/​interrupt.h?v=4.9#L494|struct tasklet_struct]].+Un tasklet este caracterizat prin structura [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​interrupt.h#​L517|struct tasklet_struct]].
 Un tasklet preinițializat se definește astfel: Un tasklet preinițializat se definește astfel:
  
Line 154: Line 153:
 ==== Timere ==== ==== Timere ====
  
-Un caz particular de acțiuni amânabile, dar foarte des folosite, sunt timer-ele: [[http://lxr.free-electrons.com/​source/​include/​linux/​timer.h?v=4.9#L12|struct timer_list]].+Un caz particular de acțiuni amânabile, dar foarte des folosite, sunt timer-ele: [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​timer.h#​L13|struct timer_list]].
 În Linux, timer-ele rulează din context întrerupere,​ fiind implementate cu ajutorul softirq-urilor. În Linux, timer-ele rulează din context întrerupere,​ fiind implementate cu ajutorul softirq-urilor.
  
-Pentru a putea fi folosit, un timer trebuie mai întâi inițializat apelând [[http://lxr.free-electrons.com/​source/​include/​linux/​timer.h?v=4.9#L157|setup_timer]]:+Pentru a putea fi folosit, un timer trebuie mai întâi inițializat apelând [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​timer.h#​L121|timer_setup]]:
  
 <code c> <code c>
 #include <​linux/​sched.h>​ #include <​linux/​sched.h>​
  
-void setup_timer(struct timer_list *timer, +void timer_setup(struct timer_list *timer, 
-                 void (*function)(unsigned long), +                 void (*function)(struct timer_list *), 
-                 ​unsigned ​long data);+                 ​unsigned ​int flags);
 </​code>​ </​code>​
  
-Funcția de mai sus inițializează câmpurile interne ale structurii și asociază ''​function''​ ca rutina de tratare a timerului; parametrul ''​data'' ​va fi transmis funcției de tratare. Intrucât timer-ele sunt planificate peste softirq-uri,​ în codul asociat funcției de tratare nu pot fi folosite apeluri blocante.+Funcția de mai sus inițializează câmpurile interne ale structurii și asociază ''​function''​ ca rutina de tratare a timerului; ​folosind ​parametrul ''​flags'' ​se poate specifica comportamentul timer-ului ([[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​timer.h#​L41|lista flag-uri]]). Intrucât timer-ele sunt planificate peste softirq-uri,​ în codul asociat funcției de tratare nu pot fi folosite apeluri blocante.
  
-Planificarea unui timer se face cu [[http://lxr.free-electrons.com/​source/​kernel/​time/​timer.c?v=4.9#L1074|mod_timer]]:​+Planificarea unui timer se face cu [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​time/​timer.c#​L1072|mod_timer]]:​
  
 <code c> <code c>
Line 177: Line 176:
 unde ''​expires''​ este timpul (din viitor) la care să se ruleze funcția de tratare. Funcția poate fi folosită pentru a planifica sau pentru a replanifica un timer. unde ''​expires''​ este timpul (din viitor) la care să se ruleze funcția de tratare. Funcția poate fi folosită pentru a planifica sau pentru a replanifica un timer.
  
-Unitatea în care se măsoară timpul pentru aceste tipuri de timere este ''​jiffie''​ ((jiffie -- începând cu 2.6.21, arhitectura tratării timerelor a fost complet rescrisă; se așteaptă ca în viitor și jiffie-ul să dispară. Pentru detalii consultați [[http://​lwn.net/​Articles/​223185/​|Clockevents and dyntick]] și  [[http://lxr.free-electrons.com/​source/​Documentation/​timers/​hrtimers.txt?v=4.9|Documentation/​timers/​hrtimers.txt]])). Valoarea în timp absolut a unui jiffie este dependentă de platformă, și se poate afla cu ajutorul macroului ''​HZ''​ care definește numărul de jiffies pentru 1 secundă. Pentru a transforma între un interval de timp în jiffies (''​jiffies_value''​) și un interval în secunde (''​seconds_value''​) se folosesc următoarele formule:+Unitatea în care se măsoară timpul pentru aceste tipuri de timere este ''​jiffie''​ ((jiffie -- începând cu 2.6.21, arhitectura tratării timerelor a fost complet rescrisă; se așteaptă ca în viitor și jiffie-ul să dispară. Pentru detalii consultați [[http://​lwn.net/​Articles/​223185/​|Clockevents and dyntick]] și  [[https://elixir.bootlin.com/​linux/​v4.15/​source/​Documentation/​timers/​hrtimers.txt|Documentation/​timers/​hrtimers.txt]])). Valoarea în timp absolut a unui jiffie este dependentă de platformă, și se poate afla cu ajutorul macroului ''​HZ''​ care definește numărul de jiffies pentru 1 secundă. Pentru a transforma între un interval de timp în jiffies (''​jiffies_value''​) și un interval în secunde (''​seconds_value''​) se folosesc următoarele formule:
  
 <code c> <code c>
Line 196: Line 195:
 </​code>​ </​code>​
  
-Pentru a opri un timer se folosesc funcțiile [[http://lxr.free-electrons.com/​source/​kernel/​time/​timer.c?v=4.9#L1160|del_timer]] și [[http://lxr.free-electrons.com/​source/​kernel/​time/​timer.c?v=4.9#L1218|del_timer_sync]]:​+Pentru a opri un timer se folosesc funcțiile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​time/​timer.c#​L1173|del_timer]] și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​time/​timer.c#​L1202|del_timer_sync]]:​
  
 <code c> <code c>
Line 203: Line 202:
 </​code>​ </​code>​
  
-Funcțiile se pot apela atât pentru un timer planificat cât și pentru un timer neplanificat. Funcția [[http://lxr.free-electrons.com/​source/​kernel/​time/​timer.c?v=4.9#L1218|del_timer_sync]] este folosită pentru a elimina race-urile ce pot apărea pe sisteme multiprocesor,​ întrucât la terminarea apelului se garantează că funcția de tratare a timer-ului nu rulează pe niciun procesor.+Funcțiile se pot apela atât pentru un timer planificat cât și pentru un timer neplanificat. Funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​time/​timer.c#​L1202|del_timer_sync]] este folosită pentru a elimina race-urile ce pot apărea pe sisteme multiprocesor,​ întrucât la terminarea apelului se garantează că funcția de tratare a timer-ului nu rulează pe niciun procesor.
  
 O greșeală frecventă a folosirii timer-elor este aceea că se uită oprirea timerelor pornite. De exemplu, **înainte de descărcarea unui modul trebuie să oprim timerele**, pentru că dacă un timer expiră după descărcarea modului, funcția de tratare nu va mai fi încărcată în kernel și se va genera un kernel oops. O greșeală frecventă a folosirii timer-elor este aceea că se uită oprirea timerelor pornite. De exemplu, **înainte de descărcarea unui modul trebuie să oprim timerele**, pentru că dacă un timer expiră după descărcarea modului, funcția de tratare nu va mai fi încărcată în kernel și se va genera un kernel oops.
Line 212: Line 211:
 #include <​linux/​sched.h>​ #include <​linux/​sched.h>​
  
-void timer_function(unsigned long arg);+void timer_function(struct timer_list *timer);
  
 struct timer_list timer; struct timer_list timer;
 unsigned long seconds = 1; unsigned long seconds = 1;
  
-setup_timer(&​timer,​ timer_function,​ 0);+timer_setup(&​timer,​ timer_function,​ 0);
 mod_timer(&​timer,​ jiffies + seconds * HZ); mod_timer(&​timer,​ jiffies + seconds * HZ);
 </​code>​ </​code>​
Line 228: Line 227:
 ==== Locking softirq-uri ==== ==== Locking softirq-uri ====
  
-Pentru a masca softirq-urile (inclusiv timerele sau taskleții) puteți folosi funcțiile [[http://lxr.free-electrons.com/​source/​include/​linux/​bottom_half.h?v=4.9#L16|local_bh_disable]] / [[http://lxr.free-electrons.com/​source/​include/​linux/​bottom_half.h?v=4.9#L29|local_bh_enable]]:​+Pentru a masca softirq-urile (inclusiv timerele sau taskleții) puteți folosi funcțiile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​bottom_half.h#​L17|local_bh_disable]] / [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​bottom_half.h#​L30|local_bh_enable]]:​
  
 <code c> <code c>
Line 249: Line 248:
 </​code>​ </​code>​
  
-Pentru situațiile în care trebuie să mascați softirq-urile dar și să folosiți lock-uri puteți folosi funcțiile de mai jos, definite în [[http://lxr.free-electrons.com/​source/​include/​linux/​spinlock.h?v=4.9#L305|linux/​spinlock.h]] ((spinlock -- pentru mai multe detalii despre folosirea spinlock-urilor,​ revedeți [[so2:​laboratoare:​lab03#​Spinlock-uri|Laboratorul 3]])). Funcțiile ''​*_lock_bh()''​ vor dezactiva softirq-urile,​ iar apoi vor efectua operația de //lock//. Funcțiile ''​*_unlock_bh()''​ vor efectua operația de //unlock// și apoi vor reactiva softirq-urile.+Pentru situațiile în care trebuie să mascați softirq-urile dar și să folosiți lock-uri puteți folosi funcțiile de mai jos, definite în [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​spinlock.h#​L313|linux/​spinlock.h]] ((spinlock -- pentru mai multe detalii despre folosirea spinlock-urilor,​ revedeți [[so2:​laboratoare:​lab03#​Spinlock-uri|Laboratorul 3]])). Funcțiile ''​*_lock_bh()''​ vor dezactiva softirq-urile,​ iar apoi vor efectua operația de //lock//. Funcțiile ''​*_unlock_bh()''​ vor efectua operația de //unlock// și apoi vor reactiva softirq-urile.
  
 <code c> <code c>
Line 263: Line 262:
 ==== Workqueues ==== ==== Workqueues ====
  
-Puteți folosi workqueue-uri pentru a planifica acțiuni care să ruleze în context proces. Unitatea de bază cu care se lucrează poartă denumirea de **work**. Există două structuri care definesc o sarcină: ​ [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L100|struct work_struct]] (pentru a planifica o sarcină să ruleze la un moment ulterior de timp) și [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L113|struct delayed_work]] (pentru a putea planifica o sarcină să ruleze după cel puțin un interval de timp dat). O sarcină de tipul ''​struct delayed_work''​ folosește un ''​timer''​ pentru a rula după intervalul de timp specificat; funcțiile pentru lucrul cu acest tip de sarcini sunt similare cu cele pentru ''​struct work_struct'',​ dar conțin ''​delayed''​ în numele funcției. O sarcină se poate inițializa cu ajutorul următoarelor macrodefiniții:​+Puteți folosi workqueue-uri pentru a planifica acțiuni care să ruleze în context proces. Unitatea de bază cu care se lucrează poartă denumirea de **work**. Există două structuri care definesc o sarcină: ​ [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L101|struct work_struct]] (pentru a planifica o sarcină să ruleze la un moment ulterior de timp) și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L114|struct delayed_work]] (pentru a putea planifica o sarcină să ruleze după cel puțin un interval de timp dat). O sarcină de tipul ''​struct delayed_work''​ folosește un ''​timer''​ pentru a rula după intervalul de timp specificat; funcțiile pentru lucrul cu acest tip de sarcini sunt similare cu cele pentru ''​struct work_struct'',​ dar conțin ''​delayed''​ în numele funcției. O sarcină se poate inițializa cu ajutorul următoarelor macrodefiniții:​
  
 <code c> <code c>
Line 296: Line 295:
 </​code>​ </​code>​
  
-Odată declarată și inițializată,​ putem planifica sarcina folosind funcțiile [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L519|schedule_work]] și [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L579|schedule_delayed_work]]:​+Odată declarată și inițializată,​ putem planifica sarcina folosind funcțiile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L533|schedule_work]] și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L593|schedule_delayed_work]]:​
  
 <code c> <code c>
Line 303: Line 302:
 </​code>​ </​code>​
  
-Funcția [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L579|schedule_delayed_work]] poate fi folosită pentru a planifica un work pentru execuție cu o întârziere de minim ''​delay'';​ întârzierea este dată în [[#​Timere|jiffies]].+Funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L593|schedule_delayed_work]] poate fi folosită pentru a planifica un work pentru execuție cu o întârziere de minim ''​delay'';​ întârzierea este dată în [[#​Timere|jiffies]].
  
 Sarcinile nu pot fi mascate. Sarcinile nu pot fi mascate.
  
-O sarcină planificată ​cu întârziere,​ dar care nu a rulat încă, ​poate fi anulată apelând [[http://lxr.free-electrons.com/​source/​kernel/​workqueue.c?v=4.9#L3024|cancel_delayed_work_sync]]:​+O sarcină planificată poate fi anulată apelând [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​workqueue.c#​L3051|cancel_delayed_work_sync]] sau [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​workqueue.c#​L2958|cancel_work_sync]]:
  
 <code c> <code c>
 +int cancel_work_sync(struct delayed_work *work);
 int cancel_delayed_work_sync(struct delayed_work *work); int cancel_delayed_work_sync(struct delayed_work *work);
 </​code>​ </​code>​
  
-Apelul nu face decât să oprească execuția ulterioară a sarcinii; dacă funcția asociată sarcinii este deja în execuție la momentul apelului, aceasta va rula în continuare.+Apelul nu face decât să oprească execuția ulterioară a sarcinii; dacă funcția asociată sarcinii este deja în execuție la momentul apelului, aceasta va rula în continuare. În orice caz, la terminarea acestor apeluri se garantează faptul că sarcina nu va mai rula.
  
-Putem să așteptăm terminarea rulării sarcinilor din coada folosind [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L535|flush_scheduled_work]]:​+Putem să așteptăm terminarea rulării sarcinilor din coada folosind [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L549|flush_scheduled_work]]:​
  
 <code c> <code c>
Line 323: Line 323:
 Această funcție este blocantă și, din această cauză, nu poate fi folosită din context întrerupere. La execuția acestei funcții se va aștepta terminarea tuturor sarcinilor din coadă existente la momentul apelului; pentru sarcinile planificate cu întârziere trebuie apelată funcția ''​cancel_delayed_work''​ înainte de apelul ''​flush_scheduled_work''​. Această funcție este blocantă și, din această cauză, nu poate fi folosită din context întrerupere. La execuția acestei funcții se va aștepta terminarea tuturor sarcinilor din coadă existente la momentul apelului; pentru sarcinile planificate cu întârziere trebuie apelată funcția ''​cancel_delayed_work''​ înainte de apelul ''​flush_scheduled_work''​.
  
-În fine, următoarele funcții pot fi folosite pentru a planifica sarcini pe un anumit procesor ([[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L564|schedule_delayed_work_on]]),​ respectiv pe toate procesoarele ([[http://lxr.free-electrons.com/​source/​kernel/​workqueue.c?v=4.9#L3039|schedule_on_each_cpu]]):​+În fine, următoarele funcții pot fi folosite pentru a planifica sarcini pe un anumit procesor ([[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L578|schedule_delayed_work_on]]),​ respectiv pe toate procesoarele ([[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​workqueue.c#​L3066|schedule_on_each_cpu]]):​
  
 <code c> <code c>
Line 348: Line 348:
 </​code>​ </​code>​
  
-După cum se poate observa, funcția ''​my_work_handler''​ primește drept parametru sarcina care se execută. Pentru a putea accesa date private ale modulului, se poate folosi macrodefiniția [[http://lxr.free-electrons.com/​source/​include/​linux/​kernel.h?v=4.9#L828|container_of]] ((container_of -- un exemplu de utilizare pentru macrodefiniția ''​container_of''​ este la parcurgerea [[so2:​laboratoare:​lab03#​Liste|listelor]] din kernel)):+După cum se poate observa, funcția ''​my_work_handler''​ primește drept parametru sarcina care se execută. Pentru a putea accesa date private ale modulului, se poate folosi macrodefiniția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​kernel.h#​L921|container_of]] ((container_of -- un exemplu de utilizare pentru macrodefiniția ''​container_of''​ este la parcurgerea [[so2:​laboratoare:​lab03#​Liste|listelor]] din kernel)):
  
 <code c> <code c>
Line 379: Line 379:
 Funcțiile declarate mai sus folosesc o coadă de sarcini predefinită (numită **events**),​ iar acestea rulează in contextul thread-ului ​ **events/​x**,​ după cum s-a precizat mai sus. Deși aceasta este suficientă in majoritatea cazurilor, este o resursă partajată și întârzieri mari în funcțiile asociate sarcinilor pot cauza întârzieri celorlalți utilizatori ai cozii. Din acest motiv, există funcții pentru crearea de cozi de sarcini suplimentare. Funcțiile declarate mai sus folosesc o coadă de sarcini predefinită (numită **events**),​ iar acestea rulează in contextul thread-ului ​ **events/​x**,​ după cum s-a precizat mai sus. Deși aceasta este suficientă in majoritatea cazurilor, este o resursă partajată și întârzieri mari în funcțiile asociate sarcinilor pot cauza întârzieri celorlalți utilizatori ai cozii. Din acest motiv, există funcții pentru crearea de cozi de sarcini suplimentare.
  
-O coada de sarcini este reprezentată de [[http://lxr.free-electrons.com/​source/​kernel/​workqueue.c?v=4.9#L235|struct workqueue_struct]]. Poate fi creată cu ajutorul funcțiilor:​+O coada de sarcini este reprezentată de [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​workqueue.c#​L236|struct workqueue_struct]]. Poate fi creată cu ajutorul funcțiilor:​
  
 <code c> <code c>
Line 386: Line 386:
 </​code>​ </​code>​
  
-Funcția [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L414|create_workqueue]] folosește câte un thread pentru fiecare procesor din sistem, iar [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L419|create_singlethread_workqueue]] folosește un singur thread.+Funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L428|create_workqueue]] folosește câte un thread pentru fiecare procesor din sistem, iar [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L433|create_singlethread_workqueue]] folosește un singur thread.
  
-Pentru a adăuga o sarcina in coada suplimentară se vor folosi funcțiile [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L461|queue_work]] și [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L477|queue_delayed_work]]:​+Pentru a adăuga o sarcina in coada suplimentară se vor folosi funcțiile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L475|queue_work]] și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L491|queue_delayed_work]]:​
  
 <code c> <code c>
Line 396: Line 396:
 </​code>​ </​code>​
  
-Funcția [[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L477|queue_delayed_work]] poate fi folosită pentru a planifica un work pentru execuție cu o întârziere de minim ''​delay'';​ întârzierea este dată în [[#​Timere|jiffies]].+Funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L491|queue_delayed_work]] poate fi folosită pentru a planifica un work pentru execuție cu o întârziere de minim ''​delay'';​ întârzierea este dată în [[#​Timere|jiffies]].
  
-Pentru a aștepta terminarea sarcinilor din coadă se apelează [[http://lxr.free-electrons.com/​source/​kernel/​workqueue.c?v=4.9#L2577|flush_workqueue]]:​+Pentru a aștepta terminarea sarcinilor din coadă se apelează [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​workqueue.c#​L2589|flush_workqueue]]:​
  
 <code c> <code c>
Line 404: Line 404:
 </​code>​ </​code>​
  
-iar pentru a distruge coada [[http://lxr.free-electrons.com/​source/​kernel/​workqueue.c?v=4.9#L4014|destroy_workqueue]]:​+iar pentru a distruge coada [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​workqueue.c#​L4060|destroy_workqueue]]:​
  
 <code c> <code c>
Line 430: Line 430:
 </​code>​ </​code>​
  
-Sarcinile planificate cu aceste funcții vor rula în contextul unei nou kernel thread denumit **my_workqueue**,​ numele dat la crearea cozii de sarcini cu apelul [[[http://lxr.free-electrons.com/​source/​include/​linux/​workqueue.h?v=4.9#L419|create_singlethread_workqueue]].+Sarcinile planificate cu aceste funcții vor rula în contextul unei nou kernel thread denumit **my_workqueue**,​ numele dat la crearea cozii de sarcini cu apelul [[[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​workqueue.h#​L433|create_singlethread_workqueue]].
 ==== Kernel threads ==== ==== Kernel threads ====
  
 Kernel thread-urile au apărut din necesitatea de a rula cod în context proces din kernel. Kernel thread-urile stau la baza mecanismului de workqueue. În esență, un kernel thread este un thread ce rulează în contextul procesului init și nu rulează decât în kernel-mode. Din acest motiv, un kernel thread nu are asociat informații precum un spațiu de adresă user. Kernel thread-urile au apărut din necesitatea de a rula cod în context proces din kernel. Kernel thread-urile stau la baza mecanismului de workqueue. În esență, un kernel thread este un thread ce rulează în contextul procesului init și nu rulează decât în kernel-mode. Din acest motiv, un kernel thread nu are asociat informații precum un spațiu de adresă user.
  
-Pentru a crea un kernel thread, se apelează funcția [[http://lxr.free-electrons.com/​source/​kernel/​kthread.c?v=3.13#L245|kthread_create_on_node]] sau [[http://lxr.free-electrons.com/​source/​kernel/​kthread.c?v=3.13#L355|kthread_create_on_cpu]]:​+Pentru a crea un kernel thread, se apelează funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​kthread.c#​L333|kthread_create_on_node]] sau [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​kthread.c#​L413|kthread_create_on_cpu]]:​
  
 <code c> <code c>
Line 463: Line 463:
 va crea un kernel thread cu numele **mykthread0**. va crea un kernel thread cu numele **mykthread0**.
  
-Kernel thread-ul creat cu această funcție va fi oprit, în starea ''​TASK_INTERRUPTIBLE''​. Pentru a porni kernel thread-ul se va apela funcția [[http://lxr.free-electrons.com/​source/​kernel/​sched/​core.c?v=3.13#L1674|wake_up_process]]:​+Kernel thread-ul creat cu această funcție va fi oprit, în starea ''​TASK_INTERRUPTIBLE''​. Pentru a porni kernel thread-ul se va apela funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​kernel/​sched/​core.c#​L2137|wake_up_process]]:​
  
 <code c> <code c>
Line 471: Line 471:
 </​code>​ </​code>​
  
-Alternativ, se poate folosi macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​kthread.h?v=3.13#L22|kthread_run]]:​+Alternativ, se poate folosi macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​kthread.h#​L35|kthread_run]]:​
  
 <code c> <code c>
so2/laboratoare/lab06.1490518052.txt.gz · Last modified: 2017/03/26 11:47 by octavian.purdila
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0