Guillaume Chanel
Remerciements à Jean-Luc Falcone
Cours système d'exploitation by Guillaume Chanel, Jean-Luc Falcone and University of Geneva is licensed under CC BY-NC-SA 4.0
Merci à Jacques Menu
0 | Entrée standard |
---|---|
1 | Sortie standard |
2 | Erreur standard |
A l'ouverture d'un canal d'entrée/sortie:
Un élément de la tables des canaux ouverts contient (entre autre):
O_RDONLY, O_WRONLY, O_RDWR
)O_NONBLOCK, O_ASYNC, O_APPEND
)Les mêmes fonctions sont utilisés quelque soit le type de fichier (fichier de données, socket, pipe, périphériques, etc.):
Opération | Appel système |
---|---|
Ouverture | open |
Lecture de données | read |
Ecriture de données | write |
Contrôle du fonctionement | fcntl |
Fermeture | close |
open
)L'appel système suivant ouvre un canal:
int open(const char *pathname, int flags, mode_t mode);
pathname
est le nom du fichierflags
est un champ de bit indiquant le mode d'accès au fichiermode
indique les permissions si le fichier est créé par open
(cf. O_CREAT
).Les flags suivants peuvent être passés à la fonction open
:
O_RDONLY | Lecture seule |
O_WRONLY | Ecriture seule |
O_RDWR | Lecture et écriture |
O_NONBLOCK | Canal non-bloqué par une lecture/écriture |
O_APPEND | Ecrit à la fin |
O_CREAT | Crée le fichier s'il n'existe pas |
O_TRUNC | Efface le fichier s'il existe |
O_EXCL | Erreur si O_CREATE est spécifié et que le fichier existe |
Lorsque que le flag O_CREAT
est passé, il faut spécifier les permissions:
int fd = open("/tmp/foo.txt", O_RDWR | O_CREAT | O_OEXCL, 0640);
Si O_CREAT
est absent, le mode est ignoré.
Si un fichier est ouvert plusieurs fois par un ou plusieurs processus:
close
)fd
:int close(int fd);
unlink
, le fichier est effectivement effacé.exit
ou abort
, le noyau ferme tous les descripteurs (équivalent à close
).execv()
si le bit close-on-exec est égal à 1.fcntl
)On peut manipuler finement un descripteur avec:
int fcntl(int fd, int cmd, ... /* arg */ );
fd
est un descripteur et cmd
la commande.read
)Pour lire les données d'un descripteur, on peut utiliser:
ssize_t read(int fd, void *buf, size_t count);
count
bytes depuis le descripteur fd
buf
errno
)write
)Pour écrire des données sur un descripteur, on peut utiliser:
ssize_t write(int fd, void *buf, size_t count);
count
bytes sur le descripteur fd
buf
contient les bytes à écrireerrno
)Include example there (see script)
lseek
)off_t lseek(int fd, off_t offset, int whence);
fd
whence
permet d'interpréter l'offseterrno
)La nouvelle position, dépend de whence
et d'offset
whence | Nouvelle position |
---|---|
SEEK_SET | offset |
SEEK_CUR | position courant + offset |
SEEK_END | fin du fichier + offset |
Include example there (see script)
withdraw( accounts, 10, 200 )
withdraw( accounts, 10, 150 )
Les processus peuvent poser des verrous sur des fichiers pour se coordoner.
Il y a deux types de stratégie:
Un verrou obligatoire bloque les opérations de lecture/écriture
Les verrous peuvent être:
partagés | plusieurs verrous peuvent être posés en même temps (shared) |
---|---|
exclusifs | un seul verrou peut être posé à la fois. |
Ces deux types permettent de résoudre le Readers-Writers-Problem.
struct flock
)F_RDLCK | plusieurs verrous peuvent être posés en même temps (verrou partagé, shared) |
F_WRLCK | un seul verrou peut être posé à la fois (verrou exclusif, exclusive) |
F_UNLCK | pas de verrou (débloque un verrou existant). |
l_whence | fonctionne comme pour lseek |
l_start | donne le début du verrou (dépend de l_whence ) |
l_len | Nombre de "bytes" verouillés |
fcntl
)L'appel système suivant permet de poser/enlever les verrous:
int fcntl(int fd, int cmd, struct flock *lock);
fd
spécifie le descripteur du fichier.cmd
) utiliséelock
permet de passer ou de recevoir les paramètres du verrou.F_SETLK
F_SETLK
permet de poser/enlever un verrou.lock->l_type
:
F_RDLCK | essaie de poser un verrou partagé |
F_WRLCK | essaie de poser un verrou exclusif |
F_UNLCK | enlève un verrou précédent |
EACCES
ou EAGAIN
.F_SETLK
: LOCK
int LOCK( int fd, int account ) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = account;
fl.l_len = 1;
if (fcntl(fd, F_SETLK, &fl) == -1) {
if (errno == EACCES || errno == EAGAIN) {
//Attendre ou faire autre chose
return LOCK( fd, account );
} else return -1;
} else return 0;
}
F_SETLK
: UNLOCK
int UNLOCK( int fd, int account ) {
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = account;
fl.l_len = 1;
return fcntl(fd, F_SETLK, &fl);
}
F_SETLKW
F_SETLKW
permet de poser/enlever un verrou.lock->l_type
:
F_RDLCK | essaie de poser un verrou partagé |
F_WRLCK | essaie de poser un verrou exclusif |
F_UNLCK | enlève un verrou précédent |
EINTR
.F_SETLKW
: LOCK
int LOCK( int fd, int account ) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = account;
fl.l_len = 1;
return fcntl(fd, F_SETLKW, &fl);
}
F_GETLK
F_GETLK
permet d'obtenir des informations sur un verrou.*lock
doit être remplie avec les informations concernant un verrou que l'on souhaite poser.lock->l_type
vaut F_UNLCK
*lock
contient des informations sur un des verrous déjà en place.open
avec les flags O_CREAT|O_EXCL
.
#define LOCK_FILE ".lock"
int LOCK() {
int fd = open( LOCK_FILE, (O_CREAT|O_EXCL), 0600 );
if( fd < 0 && errno == EEXIST ) {
//ATTENDRE
return LOCK();
}
return fd;
}
int UNLOCK( int fd ) {
close(fd);
return unlink(LOCK_FILE);
}
mkstemp
)La fonction mkstemp
permet de créer et d'ouvrir un fichier temporaire:
int mkstemp(char *template);
*template
), terminé par 6 "X".*template
est modifiée avec le vrai nom du fichier.0600
mkstemp
char name[15] = "";
int fd = -1;
strncpy( name, "/tmp/ed.XXXXXX", sizeof name );
fd = mkstemp( name );
if( fd < 0 ) {
//Gerer l'erreur
}
else {
printf( "The temporaray filename is %s\n", name );
}
unlink
n'efface pas un fichier, seulement son nomunlink
sur un fichier temporaire créé.mkstemp/unlink/link
(pseudocode)
int fd = mkstemp( name );
unlink( fd ); // Enleve le nom
DOWNLOAD_INTO( fd );
PLAY_WITH( fd );
close( downloadFD ); // Efface les donnees
mkdtemp
)On peut aussi créer des répertoires temporaires:
char *mkdtemp(char *template);
mkstemp
.0700
.NULL
.