My Project
Chargement...
Recherche...
Aucune correspondance
tubes.c
Aller à la documentation de ce fichier.
1
12#include <manux/tubes.h>
13#include <manux/debug.h>
14#include <manux/tache.h> // tacheAjouterFichiers
15#include <manux/scheduler.h>// tacheEnCours
16#include <manux/fichier.h>
17#include <manux/errno.h> // ESUCCES
18#include <manux/memoire.h> // NULL
19#include <manux/kmalloc.h> // NULL
20#include <manux/string.h> // memcpy
22#include <manux/condition.h>
23
25
29#define MANUX_TUBE_NB_PAGES 1
30
31#define MANUX_TUBE_CAPACITE (MANUX_TAILLE_PAGE * MANUX_TUBE_NB_PAGES)
32
33#define MIN(a, b) (((a) < (b)) ? (a) : (b))
34
38typedef struct _tube {
39 uint8_t * donnees; //< Pointeur sur la zone de données
40 uint32_t taille; //< Nombre d'octets présents dans le tube
41 uint32_t indiceProchain ; //< Position de la prochaine insertion
42
45
49
53static
54int tubeOuvrir(INoeud * iNoeud, Fichier * f, uint16_t fanions, uint16_t mode)
55{
56 Tube * tube = (Tube *) f->iNoeud->prive;
57 (void)iNoeud;
58 (void)mode;
59
60 exclusionMutuelleEntrer(&(tube->exclusionMutuelle));
61
62 if (fanions & O_RDONLY) {
63 tube->nbLecteurs++;
64 }
65 if (fanions & O_WRONLY) {
66 tube->nbEcrivains++;
67 }
68
69 exclusionMutuelleSortir(&(tube->exclusionMutuelle));
70
71 f->prive = NULL;
72
73 return ESUCCES;
74}
75
79static
80int tubeFermer(Fichier * f)
81{
82
84 Tube * tube = (Tube *) f->iNoeud->prive;
85
86 exclusionMutuelleEntrer(&(tube->exclusionMutuelle));
87
88 printk_debug(DBG_KERNEL_TUBE, "mutex locked\n");
89
90 if (f->fanions & O_RDONLY) {
91 tube->nbLecteurs--;
92 }
93 if (f->fanions & O_WRONLY) {
94 tube->nbEcrivains--;
95 if (tube->nbEcrivains == 0) {
96 conditionDiffuser(&(tube->nouvellesDonnees));
97 }
98 }
99
100 exclusionMutuelleSortir(&(tube->exclusionMutuelle));
101
102 return ESUCCES;
103}
104
108static
109size_t tubeEcrire(Fichier * f, void * buffer, size_t nbOctets)
110{
111 Tube * tube;
112 uint32_t n = 0;
113 uint32_t nbOctetsEcrits = 0; // Le nombre d'octets déja écrits
114
116
117 // Peut-on décemment écrire dans le tube ?
118 if ((f == NULL) || (f->iNoeud == NULL) || (f->iNoeud->prive == NULL)) {
119 return -EINVAL;
120 }
121 tube = f->iNoeud->prive;
122
123 exclusionMutuelleEntrer(&(tube->exclusionMutuelle));
124
125 // On fait une boucle, car il est possible que l'on doive écrire en
126 // deux fois si on est proche de la fin du tableau qui contient les
127 // données.
128 do {
129 // On n'écrit ni plus que ce qui est demandé, ni plus que ce
130 // qu'on peut
131 n = MIN(nbOctets - nbOctetsEcrits, MANUX_TUBE_CAPACITE - tube->taille);
132
133 // On ne doit pas aller écrire au delà du buffer
134 n = MIN(n, (MANUX_TUBE_CAPACITE - tube->indiceProchain));
135
136 // On peut donc copier n octets dans le buffer à partir de la
137 // position courante, sans risque de déborder
138 memcpy(tube->donnees + tube->indiceProchain, buffer, n);
139
140 ordonnanceur(); // Pour forcer
141
142 tube->indiceProchain = (tube->indiceProchain + n) % MANUX_TUBE_CAPACITE;
143 tube->taille += n;
144
145 buffer += n;
146
147 nbOctetsEcrits += n;
148 } while (n > 0);
149
150 if (nbOctetsEcrits > 0) {
151 conditionSignaler(&(tube->nouvellesDonnees));
152 }
153
154 exclusionMutuelleSortir(&(tube->exclusionMutuelle));
155
157
158 return nbOctetsEcrits;
159}
160
161static
162size_t tubeLire(Fichier * f, void * buffer, size_t nbOctets)
163{
164 Tube * tube;
165 int n = 0;
166 int nbOctetsLus = 0;
167 int indicePremier;
168
170
171 // Peut-on décemment lire dans le tube ? (note : les deux premières
172 // conditions sont assurées par l'appelant (fichierLire) a priori
173 if ((f == NULL) || (f->iNoeud == NULL) || (f->iNoeud->prive == NULL)) {
174 return -EINVAL;
175 }
176 tube = f->iNoeud->prive;
177
178 exclusionMutuelleEntrer(&(tube->exclusionMutuelle));
179 printk_debug(DBG_KERNEL_TUBE, "mutex locked\n");
180
181 // En cas de lecture bloquante, j'attends la dispo des données ou
182 // la disparition du dernier écrivain
183 if ((f->fanions & O_NONBLOCK) == 0) {
184 while ((tube->taille == 0) && (tube->nbEcrivains > 0)) {
185 printk_debug(DBG_KERNEL_TUBE, "attente condition\n");
186 conditionAttendre(&(tube->nouvellesDonnees), &(tube->exclusionMutuelle));
187 }
188 }
189 // Je sais maintenant qu'il y a des données, ou alors qu'il n'y en
190 // aura plus jamais, ou alors je suis en non bloquant, bref, je
191 // peux y aller et faire comme si, ...
192
193 do {
194 // A partir de quel octet peut-on lire ?
195 indicePremier = (tube->indiceProchain + MANUX_TUBE_CAPACITE - tube->taille)
197
198 // On ne lit ni plus que ce qui est demandé, ni plus que ce
199 // qu'on a
200 n = MIN(nbOctets - nbOctetsLus, tube->taille);
201
202 // On ne doit pas aller lire au delà du buffer
203 n = MIN(n, (MANUX_TUBE_CAPACITE - indicePremier));
204
205 printk_debug(DBG_KERNEL_TUBE,"Je vais lire %d\n", n);
206
207 // On peut donc copier n octets dans le buffer à partir de la
208 // position courante, sans risque de déborder
209 memcpy(buffer, tube->donnees + indicePremier, n);
210
211 ordonnanceur(); // Pour forcer
212
213 indicePremier = (indicePremier + n) % MANUX_TUBE_CAPACITE;
214 tube->taille -= n;
215
216 buffer += n;
217
218 nbOctetsLus += n;
219 } while (n > 0);
220
221 exclusionMutuelleSortir(&(tube->exclusionMutuelle));
222
224
225 return nbOctetsLus;
226}
227
233 .ouvrir = tubeOuvrir,
234 .fermer = tubeFermer,
235 .ecrire = tubeEcrire,
236 .lire = tubeLire
237};
238
239#ifdef MANUX_APPELS_SYSTEME
247int sys_tube(ParametreAS as, int * fds)
248{
249 INoeud * iNoeud;
250 Fichier * fichiers[2];
251 Tube * tube;
252 (void) as;
253
254 printk_debug(DBG_KERNEL_TUBE, "Creation d'un tube (lire = 0x%x) ...\n", tubeLire);
255
256 // Création de la structure
257 tube = kmalloc(sizeof(Tube));
258 if (tube == NULL) {
259 return ENOMEM;
260 }
261
262 // Alocation de la mémoire tampon du tube
263 if ((tube->donnees = allouerPage()) == NULL) {
264 return ENOMEM;
265 }
266
267 // Initialisation des compteurs
268 tube->taille = 0;
269 tube->indiceProchain = 0;
270
271 // L'exclusion mutuelle qui le protègera
272 exclusionMutuelleInitialiser((&(tube->exclusionMutuelle)));
273 conditionInitialiser((&(tube->nouvellesDonnees)));
274
275 // Création de l'iNoeud qui décrit le tube dans le système
277
278 // Création du fichier de sortie du tube (celui où on va lire)
279 fichiers[0] = fichierCreer(iNoeud, O_RDONLY, 0);
280
281 // Création du fichier d'entrée du tube (celui où on va écrire)
282 fichiers[1] = fichierCreer(iNoeud, O_WRONLY, 0);
283
284 // On ajoute les fichiers à la tâche
285 if (tacheAjouterFichiers(tacheEnCours, 2, fichiers, fds) != 2 ) {
286 return ENOMEM;
287 }
288
289 printk_debug(DBG_KERNEL_TUBE, "Tube cree entre %d et %d\n", fds[0], fds[1]);
290
291 // Si on est encore là, c'est que tout s'est déroulé comme prévu !
292 return ESUCCES;
293}
294#endif
295
void conditionAttendre(Condition *cond, ExclusionMutuelle *em)
Attente de la prochaine occurence d'une condition.
Definition condition.c:134
void conditionInitialiser(Condition *cond)
Initialisation d'une condition.
Definition condition.c:110
void conditionSignaler(Condition *cond)
Signaler une occurence d'une condition à une tâche en attente.
Definition condition.c:168
void conditionDiffuser(Condition *cond)
Signaler une occurence d'une condition à toutes les tâches en attente.
Definition condition.c:193
Définition des exlusions mutuelles.
void exclusionMutuelleEntrer(ExclusionMutuelle *em)
Entrée en exclusion mutuelle.
void exclusionMutuelleInitialiser(ExclusionMutuelle *em)
Initialisation d'une exclusion mutuelle.
void exclusionMutuelleSortir(ExclusionMutuelle *em)
#define O_WRONLY
Definition fichier.h:28
#define O_NONBLOCK
Definition fichier.h:30
#define O_RDONLY
Les différents fanions.
Definition fichier.h:27
#define EINVAL
Definition errno.h:14
#define ENOMEM
Definition errno.h:13
#define ESUCCES
Definition errno.h:10
typedef void(Handler(void))
Définition de kmalloc.
void * allouerPage(void)
Definition memoire.c:234
#define NULL
Definition stddef.h:10
void * memcpy(void *dest, const void *src, size_t n)
Definition string.c:12
unsigned long uint32_t
Definition types.h:20
unsigned short uint16_t
Definition types.h:16
unsigned char uint8_t
Definition types.h:12
INoeud * iNoeudCreer(void *prive, MethodesFichier *methodesFichier)
: Création d'un INoeud
Definition inoeud.c:10
void * kmalloc(size_t n)
Allocation d'une zone de n octets.
Definition kmalloc-zs.c:139
#define DBG_KERNEL_TUBE
Definition debug.h:34
#define printk_debug(lvl, fmt, args...)
Definition debug.h:86
Tache * tacheEnCours
: L'identification de la tâche en cours
Definition scheduler.c:91
void ordonnanceur(void)
Basculer vers la prochaine tache à exécuter.
Definition scheduler.c:98
Définition des exclusions mutuelles.
: Qu'est-ce qu'un fichier ouvert du point de vue du noyau ?
Definition fichier.h:46
INoeud * iNoeud
Caractérisation de la structure.
Definition fichier.h:48
void * prive
Caractérisation du fichier ouvert.
Definition fichier.h:47
uint16_t fanions
O_RDONLY, O_NONBLOCK, O_SYNC.
Definition fichier.h:50
: Un INoeud représente un fichier, d'un point de vue statique Il s'agit donc de la description d'un f...
Definition inoeud.h:27
void * prive
Definition inoeud.h:29
: Définition des opérations réalisables sur un fichier
Definition fichier.h:36
int(* ouvrir)(INoeud *iNoeud, Fichier *f, uint16_t fanions, uint16_t mode)
Definition fichier.h:37
Définition des conditions.
Definition condition.h:18
: Définition d'un tube
Definition tubes.c:38
uint32_t taille
Definition tubes.c:40
int nbEcrivains
Definition tubes.c:43
ExclusionMutuelle exclusionMutuelle
Definition tubes.c:46
uint8_t * donnees
Definition tubes.c:39
Condition nouvellesDonnees
Definition tubes.c:47
uint32_t indiceProchain
Definition tubes.c:41
int nbLecteurs
Definition tubes.c:44
MethodesFichier tubeMethodesFichier
Déclaration des méthodes permettant de traiter un tube comme un fichier.
Definition tubes.c:24
#define MIN(a, b)
Definition tubes.c:33
#define MANUX_TUBE_CAPACITE
Definition tubes.c:31
struct _tube Tube
: Définition d'un tube
int tube(int *fd)
Création d'un tube de communication.