Vous êtes sur la page 1sur 8

Annexes ED3

ANNEXE 1 Ordonnancement Linux

A titre d'information, voici la syntaxe des primitives système auxquelles


on a fait référence dans l’exercice 1.

 #include <sched.h>
int sched_setscheduler(pid_t pid, int politique,
const struct sched_param *param);

pid: est l’identifiant du processus pour lequel on veut changer de


politique d’ordonnancement
politique = {SCHED_FIFO, SCHED_RR, SCHED_OTHER}
param : paramètres d’ordonnancement, contient la priorité du
processus.
La structure sched_param définie dans <sched.h> contient un seul
champ : int sched_priority.

 #include <sched.h>
int sched_yield(void);
permet au processus courant de libérer volontairement le processeur et
d’être placé en fin de file. Le processeur exécute un autre processus s’il
y en a.

 #include <sys/resource.h>
int setpriority(int p, int q, int prio);
modifie la priorité d’un processus, d’un groupe de processus ou de tous
les processus de l’utilisateur.

P Q
PRIO_PROCESS getpid()
PRIO_PGRP getgpid()
PRIO_USER getuid()

prio est la nouvelle priorité.

Exemple de programme :

#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/resource.h>

void proc_fils (int pid) {

1
int i;

sleep(rand()%3); // retarder l'execution de chaque processus fils


// le temps de changer sa priorite
printf("\nle processus %d commence a s'executer \n",pid);
for (i=0 ; i<10000000 ; i++) {
if (i==500000) {
printf("\nle processus %d vient de liberer le
processeur\n ", pid) ;
sched_yield() ;
printf("\nle processus %d reprend son execution apres un
sched_yield()\n ", pid) ;
}
}
exit(0);
}

void afficher_ordo_priorite(int pid) {


int ordo;
struct sched_param p1;

printf ("\n Processus %d : (ordo =", pid);


ordo= sched_getscheduler(pid); // retourne la file d'ordo du processus
switch (ordo) {
case SCHED_FIFO : printf(" SCHED_FIFO, ") ; break ;
case SCHED_RR : printf(" SCHED_RR, ") ; break ;
case SCHED_OTHER : printf("SCHED_OTHER, ") ;
}
sched_getparam(pid,&p1);
printf ("priorite = %d )\n", p1.sched_priority);
}

void changer_ordo_priorite(int pid, int file, int prio) {


struct sched_param p1;
int res;

/* changer la file d'ordo et la priorite d'un processus */


p1.sched_priority=prio;
if ((res=sched_setscheduler(pid, file, &p1))!=-1) {
afficher_ordo_priorite(pid);
}
}

// M A I N
int main (void){
int pidf1, pidf2;

struct timespec intervalle;

printf("Les priorites minimale et maximale de la politique SCHED_FIFO sont


: %d et %d\n", sched_get_priority_min(SCHED_FIFO),
sched_get_priority_max(SCHED_FIFO));
printf("Les priorites minimale et maximale de la politique SCHED_RR sont :
%d et %d\n", sched_get_priority_min(SCHED_RR),
sched_get_priority_max(SCHED_RR));
printf("Les priorites minimale et maximale de la politique SCHED_OTHER sont
: %d et %d\n",
sched_get_priority_min(SCHED_OTHER),sched_get_priority_max(SCHED_OTHER));

srand(getpid()); // initialisation du generateur de nombres aleatoires

2
if ((pidf1=fork())==0) { // processus fils 1
proc_fils(getpid());
}

if ((pidf2=fork())==0) { // processus fils 2


proc_fils(getpid());
}

if (pidf1==-1 || pidf2==-1) { printf("erreur\n"); exit(1); }

/* processus pere*/

printf("\n ==>Parametres initiaux du processus pere et ses fils: \n");


afficher_ordo_priorite(getpid()) ;
afficher_ordo_priorite(pidf1);
afficher_ordo_priorite(pidf2);

printf("\n\n ==>Nouveaux parametres des processus fils: \n");


changer_ordo_priorite(pidf2, SCHED_FIFO,3);
changer_ordo_priorite(pidf1, SCHED_RR,5);

sched_rr_get_interval(pidf1,&intervalle);
printf("\nquantum de temps de la file SCHED_RR : %d milli-sec\n",
intervalle.tv_nsec/1000000);

while ( waitpid(-1,NULL, 0) > 0); /* le pere attend la fin de tous ses fils
*/
printf("\nTerminaison de tous les processus\n");
return 0;
}

Exécution
$cc scheduling.c -o sched
$./sched
Les priorites minimale et maximale de la politique SCHED_FIFO sont : 1 et
99
Les priorites minimale et maximale de la politique SCHED_RR sont : 1 et 99
Les priorites minimale et maximale de la politique SCHED_OTHER sont : 0 et
0

==>Parametres initiaux du processus pere et ses fils:

Processus 1711 : (ordo =SCHED_OTHER, priorite = 0 )

Processus 1712 : (ordo =SCHED_OTHER, priorite = 0 )

Processus 1713 : (ordo =SCHED_OTHER, priorite = 0 )

==>Nouveaux parametres des processus fils:

Processus 1713 : (ordo = SCHED_FIFO, priorite = 3 )

Processus 1712 : (ordo = SCHED_RR, priorite = 5 )

quantum de temps de la file SCHED_RR : 150 milli-sec

le processus 1713 commence a s'executer

le processus 1713 vient de liberer le processeur

3
le processus 1713 reprend son execution apres un sched_yield()

le processus 1712 commence a s'executer

le processus 1712 vient de liberer le processeur

le processus 1712 reprend son execution apres un sched_yield()

Terminaison de tous les processus


$

4
Anne xe2 Processus et Threads Windows
1. Les processus
Dans l’API Win32, une application peut créer un nouveau processus en faisant appel
à la fonction CreateProcess.

Syntaxe :

BOOL CreateProcess (
LPCTSTR lpszImageName,
LPCTSTR lpszCommandLine,
LPSECURITY_ATTRIBUTES lpsaProcess,
LPSECURITY_ATTRIBUTES lpsaThread,
BOOL fInheritHandles,
DWORD fdwCreate,
LPVOID lpvEnvironment,
LPTSTR lpszCurDir,
LPSTARTUPINFO lpsiStartInfo,
LPPROCESS_INFORMATION lppiProcInfo);

La création d’un processus implique :


- la création d’un objet kernel auquel est associé un compteur d’utilisation
initialisé à 1. L’objet kernel est une structure de données utilisée par le système
pour référencer le processus.
- La création d’un espace d’adressage virtuel de 4Go dans lequel le système
charge le code du processus, ses données ainsi que les bibliothèques
dynamiques requises.
- La création de l’objet kernel du thread principal qui sera associé au processus
créé (un compteur d’utilisation associé à l’objet kernel du thread est initialisé à
1).

Le thread principal sert à exécuter le code du processus créé, car les entités
d’exécution (d’ordonnancement) sous Windows sont les threads. En plus du thread
principal créé automatiquement à la création d’un processus, il est possible de créer
explicitement des threads à l’aide de la fonction CreateThread. Tous les threads
appartenant au même processus partagent les ressources du processus.

1.1 Premier paramètre de la fonction CreateProcess : lpszImageName


Ce paramètre désigne le nom du fichier exécutable (avec l’extension .exe) qui
contient le code à exécuter à l’exécution du processus créé.

1.2 Deuxième paramètre de la fonction CreateProcess : lpszCommandLine


Ce paramètre contient la ligne de commande. Si le premier paramètre est à NULL,
alors le premier mot du deuxième paramètre correspond au nom du fichier
exécutable (avec l’extension .exe).
Exemple :
CreateProcess ("C:\\WINNT\\SYSTEM32\\NOTEPAD.EXE", "WRITE README.TXT”,
…);
Appelle l’application NOTEPAD (Bloc-notes) mais la ligne de commande Bloc-notes
est “WRITE README.TXT”.

5
1.3 3ème et 4ème paramètres de la fonction CreateProcess : LPSECURITY_ATTRIBUTES
Ces paramètres correspondent à des structures de données qui définissent des
attributs de sécurité pour le thread ou processus créé. Quand ils ne sont pas vides
(NULL), ces paramètres permettent principalement de fixer l’héritage des objets
créés.

Exemple

LPSECURITY_ATTRIBUTES saProcess, saThread ;



saProcess.bInheritHandle=TRUE;
// le processus qui sera créé autorise l’héritage du handle de
// l’objet kernel du processus

saThread.bInheritHandle=FALSE;
// le processus qui sera créé refuse l’héritage du handle de
// l’objet kernel du thread principal qui sera associé au processus

1.4 5ème paramètre de la fonction CreateProcess : fInheritHandles


Si ce paramètre = TRUE, cela signifie que le processus créé désire hériter des handles
existants qui sont associés à l’application. Le handle est la référence retournée lors de
la création d’un objet kernel pour un processus ou un Thread.

Exemple :

LPSECURITY_ATTRIBUTES saProcess, saThread ;
STARTUPINFO si;
PROCESS_INFORMATION piProcessB;

saProcess.nLength = sizeof(saProcess);
saProcess.lpSecurityDescriptor = NULL;
saProcess.bInheritHandle=TRUE;

saThread.nLength = sizeof(saThread);
saThread.lpSecurityDescriptor = NULL;
saThread.bInheritHandle=FALSE;

CreateProcess(NULL, “ProcessB”, &saProcess, &saThread, FALSE, 0,


NULL, NULL, &si, &piProcessB);

1.5 5ème paramètre de la fonction CreateProcess : fdwCreate


Ce paramètre peut positionner plusieurs drapeaux avec l’opérateur OU. Exemples de
drapeaux :
- DEBUG_PROCESS : si le processus père souhaite déboguer le processus fils.
- CREATE_SUSPENDED : une fois le processus fils créé, son thread est
suspendu.
- CREATE_NEW_CONSOLE : crée une nouvelle fenêtre console au processus
fils.

6
- Fixer la priorité du processus créé : IDLE_PRIORIY_CLASS ,
NORMAL_PRIORIY_CLASS, HIGH_PRIORIY_CLASS, REALTIME_PRIORIY_CLASS,
- …

1.6 6ème paramètre de la fonction CreateProcess : lpvEnvironment


Ce paramètre pointe sur un espace mémoire qui contient les variables
d’environnement que le processus créé utilisera.

1.7 7ème paramètre de la fonction CreateProcess : lpszCurDir


Ce paramètre contient le répertoire de travail du processus créé.

1.8 8ème paramètre de la fonction CreateProcess : lpsiStartInfo


Ce paramètre contient les paramètres d’une fenêtre graphique ou d’une console si
une fenêtre graphique ou une console doit être associée au processus créé.

1.9 9ème paramètre de la fonction CreateProcess : lppiProcInfo


Ce paramètre a la structure suivante. Il contient le handle du processus créé, le
handle du Thread créé, le PID du processus et le TID du Thread créé.

typedef struct _PROCESS_INFORMATION {


HANDLE hProcess,
HANDLE hThread,
DWORD dwProcessId,
DWORD dwThreadId,
} PROCESS_INFORMATION ;

Tout processus créé a son propre espace d’adressage et ses propres données, si un
processus fils et un processus père désirent partager des données, ils doivent le faire
à l’aide de mécanismes de communication tels que les canaux (pipe), les fichiers
mappés en mémoire, etc.

2. Les threads
En plus du thread principal qui est créé à la création d’un processus, et permettant
l’exécution du code du processus créé, il est possible de créer explicitement de
nouveaux threads à l’aide de la fonction système CreateThread.

Syntaxe :

HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParm,
DWORD fdwCreate,
LPDWORD lpIDThread);

A la création du thread, le système effectue les étapes suivantes :

7
1. alloue un objet kernel pour le nouveau Thread. La fonction CreateThread
retourne un handle sur cet objet.
2. initialise à 1 le compteur du Thread, qui se trouve dans l’objet kernel du
Thread.
3. alloue une structure CONTEXT au nouveau Thread. Cette structure contient
l’état des registres du processeur ainsi que le pointeur de la pile d’exécution.
4. prépare la pile d’exécution en lui affectant deux pages mémoire.
5. initialise la structure CONTEXT pour pointer sur le sommet de la pile.

Si le 1er paramètre lpsa = TRUE, cela signifie que le handle de l’objet Thread créé
peut être hérité par les processus fils.
Le 2ème paramètre cbStack contient la taille de la pile d’exécution. Le 3ème
paramètre lpStartAddr contient l’adresse de la fonction Thread à exécuter. Le 4ème
paramètre est une valeur sur 32 bits qui peut être passée à la fonction Thread. Le
5ème paramètre lpvThreadParm contient des drapeaux. Le 6ème paramètre
lpIDThread est le TID attribué par le système au Thread créé.

Vous aimerez peut-être aussi