Sophie

Sophie

distrib > Mandriva > 9.1 > i586 > by-pkgid > f1098342ec4a2b28475e34123ce17201 > files > 524

howto-html-it-9.1-0.5mdk.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
 <TITLE>KernelAnalysis-HOWTO: Funzioni di comune utilizzo</TITLE>
 <LINK HREF="KernelAnalysis-HOWTO-14.html" REL=next>
 <LINK HREF="KernelAnalysis-HOWTO-12.html" REL=previous>
 <LINK HREF="KernelAnalysis-HOWTO.html#toc13" REL=contents>
</HEAD>
<BODY>
<A HREF="KernelAnalysis-HOWTO-14.html">Avanti</A>
<A HREF="KernelAnalysis-HOWTO-12.html">Indietro</A>
<A HREF="KernelAnalysis-HOWTO.html#toc13">Indice</A>
<HR>
<H2><A NAME="s13">13. Funzioni di comune utilizzo</A></H2>

<H2><A NAME="ss13.1">13.1 list_entry [include/linux/list.h]</A>
</H2>

<P>Definizione
<P>
<PRE>
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&amp;((type *)0)-&gt;member)))
</PRE>
<P>Significato:
<P>La macro "list_entry" viene usata per ricavare il puntatore ad una struttura
utilizzando soltanto un elemento interno alla struttura.
<P>Esempio
<P>
<PRE>
struct __wait_queue {
   unsigned int flags; 
   struct task_struct * task; 
   struct list_head task_list;
};
struct list_head { 
   struct list_head *next, *prev; 
};

// e con la definizione del tipo:
typedef struct __wait_queue wait_queue_t;

// avremo:
wait_queue_t *out list_entry(tmp, wait_queue_t, task_list);

// dove tmp punta a list_head
</PRE>
<P>Quindi, in questo caso, usando il puntatore *tmp [list_head]
troviamo il puntatore *out [wait_queue_t].
<P>
<PRE>

 ____________ &lt;---- *out [abbiamo calcolato questo]
|flags       |             /|\
|task *--&gt;   |              |
|task_list   |&lt;----    list_entry
|  prev * --&gt;|    |         |
|  next * --&gt;|    |         |
|____________|    ----- *tmp [partendo da questo]
 
</PRE>
<H2><A NAME="ss13.2">13.2 Sleep </A>
</H2>

<H3>Codice di Sleep</H3>

<P>Files:
<P>
<UL>
<LI>kernel/sched.c</LI>
<LI>include/linux/sched.h</LI>
<LI>include/linux/wait.h</LI>
<LI>include/linux/list.h</LI>
</UL>
<P>Funzioni:
<P>
<UL>
<LI>interruptible_sleep_on</LI>
<LI>interruptible_sleep_on_timeout</LI>
<LI>sleep_on</LI>
<LI>sleep_on_timeout</LI>
</UL>
<P>Funzioni chiamate:
<P>
<UL>
<LI>init_waitqueue_entry</LI>
<LI>__add_wait_queue</LI>
<LI>list_add</LI>
<LI>__list_add</LI>
<LI>__remove_wait_queue</LI>
</UL>
<P>InterCallings Analysis:
<P>
<PRE>
|sleep_on
   |init_waitqueue_entry  --
   |__add_wait_queue        |   Accodamento della richiesta sulla lista della risorsa
      |list_add              |
         |__list_add        -- 
   |schedule              ---     Attesa che la richiesta venga eseguita
      |__remove_wait_queue --   
      |list_del              |   Disaccodamento richiesta dalla lista della risorsa
         |__list_del        -- 
 
</PRE>
<P>Descrizione:
<P>Ogni risorsa (in teoria ogni oggetto condiviso tra piu' utenti e piu' processi),
ha una cosa per gestire TUTTI i Tasks che la richiedono.
<P>Questo metodo di accodamento viene chiamato "wait queue" e consiste di molti
elementi chiamati"wait queue element":
<P>
<PRE>
***   struttura wait queue [include/linux/wait.h]  ***


struct __wait_queue {
   unsigned int flags; 
   struct task_struct * task; 
   struct list_head task_list;
}
struct list_head { 
   struct list_head *next, *prev; 
};
</PRE>
<P>Rappresentazione grafica:
<P>
<PRE>
        ***  elemento wait queue  ***

                             /|\
                              |
       &lt;--[prev *, flags, task *, next *]--&gt;
 
                     


                 ***  Lista wait queue ***  
 
          /|\           /|\           /|\                /|\
           |             |             |                  |
--&gt; &lt;--[task1]--&gt; &lt;--[task2]--&gt; &lt;--[task3]--&gt; .... &lt;--[taskN]--&gt; &lt;--
|                                                                  |
|__________________________________________________________________|
          

           
              ***   Testa wait queue ***

       task1 &lt;--[prev *, lock, next *]--&gt; taskN
   
 
</PRE>
<P>La Testa "wait queue" punta al primo (con next *) e last (com prev *) all'ultimo
della lista "wait queue".
<P>Quando deve venire inserito un nuovo elemento viene chiamata la "__add_wait_queue"
[include/linux/wait.h], dopo di che verra' eseguita la generica routine
"list_add" [include/linux/wait.h]:
<P>
<PRE>
***   funzione list_add [include/linux/list.h]  ***

// classico inserimento doppio linkato
static __inline__ void __list_add (struct list_head * new,  \
                                   struct list_head * prev, \
                                   struct list_head * next) { 
   next-&gt;prev = new; 
   new-&gt;next = next; 
   new-&gt;prev = prev; 
   prev-&gt;next = new; 
}
</PRE>
<P>Per completare la descrizione vediamo anche la "__list_del" [include/linux/list.h]
chiamata da "list_del" [include/linux/list.h] all'interno di "remove_wait_queue"
[include/linux/wait.h]:
<P>
<PRE>
***   funzione list_del [include/linux/list.h]  ***


// classica cancellazione doppio linkato
static __inline__ void __list_del (struct list_head * prev, struct list_head * next) { 
   next-&gt;prev = prev; 
   prev-&gt;next = next; 
}
</PRE>
<H3>Considerazioni sullo Stack</H3>

<P>Una lista tipica (o coda) viene normalmente gestita allocandola nello Heap
(si veda il Cap.10 per definizioni e gestione delle variabili nello Heap e
nello Stack). 
<P>Qui invece, allochiamo ''Wait Queue'' in una variabile locale (quindi nello
Stack), dopo di che la funzione viene interrotta dalla schedulazione e, al
risveglio, la variabile locale verra' cancellata
<P>
<PRE>
  new task &lt;----|          task1 &lt;------|          task2 &lt;------|
                |                       |                       |
                |                       |                       | 
|..........|    |       |..........|    |       |..........|    | 
|wait.flags|    |       |wait.flags|    |       |wait.flags|    |
|wait.task_|____|       |wait.task_|____|       |wait.task_|____|   
|wait.prev |--&gt;         |wait.prev |--&gt;         |wait.prev |--&gt;
|wait.next |--&gt;         |wait.next |--&gt;         |wait.next |--&gt;   
|..        |            |..        |            |..        |    
|schedule()|            |schedule()|            |schedule()|     
|..........|            |..........|            |..........|    
|__________|            |__________|            |__________|     
 
   Stack                   Stack                   Stack
</PRE>
<HR>
<A HREF="KernelAnalysis-HOWTO-14.html">Avanti</A>
<A HREF="KernelAnalysis-HOWTO-12.html">Indietro</A>
<A HREF="KernelAnalysis-HOWTO.html#toc13">Indice</A>
</BODY>
</HTML>