-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path01_open_1_intro.c
More file actions
122 lines (102 loc) · 5.63 KB
/
01_open_1_intro.c
File metadata and controls
122 lines (102 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
/* Atomicity (atomicita'): il kernel garantisce che ciascun step delle system
call e' eseguito in una singola operazione e senza interruzioni da parte di un
processo o thread. Tutte le system call sono eseguite atomicamente.
Il termine Unbuffered I/O (definito anche I/O di basso livello) indica che le
varie routine (open, read, write, lseek, close, etc...) sono chiamate dirette
al sistema operativo e pertanto gestite dal Kernel stesso, inoltre l'accesso
in lettura e in scrittura sul disco comporta un "semplice" trasferimento di
byte, naturalmente senza formattazione.
L'I/O Unbuffered non e' standard ISO C, bensi' standard POSIX 1., nonche'
Single Unix Specification, per cui se lo scopo del programma dovesse essere
la portabilita' sarebbe opportuno utilizzare gli stream - IO bufferizzato -.
HEADER : <fcntl.h>
PROTOTYPE: int open(const char *pathname, int oflag, ... mode_t mode);
La funzione open() apre o crea il file definito in 'pathname', secondo la
modalita' indicata da 'oflag' ed eventualmente con i permessi definiti mediante
una bit mask in 'mode'. Ritorna 0 in caso di successo, -1 altrimenti.
Allorquando si apre un file, il kernel rilascia un file descriptor al processo,
ossia un intero non negativo che identifica un file aperto; nei sistemi UNIX ad
ogni processo sono associati 3 file descriptor: standard input 0, standard
output 1, standard error 2.
POISX peraltro ne specifica anche le costanti simboliche in:
- standard input = 0 = STDIN_FILENO;
- stanbdar output = 1 = STDOUT_FILENO;
- standard error = 2 = STDERR_FILENO;
Nota: per cio' che concerne la shell, lo standard input corrisponde ai dati
ricevuti mediante tastiera, lo standard output e lo standard error
corrispondono ai dati inviati al terminale.
Per poter iniziare a lavorare con un file e' necessario per prima cosa aprirlo,
la open() ha questo compito, ed e' peraltro anche il momento in cui sono
associati ad esso i 3 file descriptor di default; volendo essere ancor piu'
precisi la open() alloca il file, lo inserisce nella file table e crea il
riferimento nella struttura files_struct del processo.
Nota: Il valore di 'oflag' e' ottenuto mediante un OR aritmetico tra le
varie costanti simboliche, quando i bit costituiscono un file status
flag.
Il comportamento della funzione open() e le diverse modalita' con cui un file
puo' essere aperto sono definite dal valore di 'oflag', il cui contenuto e'
ottenuto come maschera binaria in cui ciascun bit ha un significato ben
preciso.
I bit che caratterizzano le costanti simboliche sono suddivisi in tre categorie:
1 - Flag delle modalita' di accesso sui file (solo uno)
-------------------------------------------------------
- O_RDONLY - Apre il file in lettura;
- O_WRONLY - Apre il file in scrittura;
- O_RDWR - Apre il file il lettura e scrittura;
2 - Flag delle modalita' di apertura sui file (in combinazione)
---------------------------------------------------------------
- O_CREAT - Se il file non esiste sara' creato;
- O_DIRECTORY - Se 'pathname' non e' una directory la chiamata fallisce;
- O_EXCL - E' utilizzato in concomitanza con O_CREAT, in modo che se il
file dovesse essere gia' presente nel filesystem, ritornerebbe
un errore EEXIST, ossia file gia' esistente nel filesystem;
- O_LARGEFILE - Apertura di file molto grandi;
- O_NOCTTY - Se 'pathname' si riferisce ad un terminale, esso non diventera'
il terminale di controllo, anche qualora il processo ancora non
ne abbia uno;
- O_NOFOLLOW - Se 'pathname' e' un collegamento simbolico la chiamata fallisce;
- O_TRUNC - Se usato un file aperto in scrittura, tronca la grandezza a 0;
3 - Flag delle modalita' di operazione sui file (in combinazione)
-----------------------------------------------------------------
- O_APPEND - La posizione corrente viene impostata alla fine del file;
- O_ASYNC - Apre il file in modalita' asincrona;
- O_CLOEXEC - Attiva la modalita' close-on-exec sul file;
- O_DIRECT - Esegue l'I/O dalla memoria in user-space in modo asincrono;
- O_NOATIME - Blocca l'aggiornamento dei tempi d'accesso del file;
- O_NONBLOCK - Apre il file in modalita' non bloccante per l'I/O;
- O_NDELAY - Su Linux e' simile alla O_NONBLOCK, altrimenti causa il ritorno
da una read() con un valore nullo;
- O_SYNC - Apre il file per l'I/O sincrono. Qualsiasi scrittura di dati si
blocchera' all'arrivo di tutti i dati sull'hardware sottostante;
- O_DSYNC - Apre il file per l'I/O sincrono. Qualsiasi scrittura di dati si
blocchera' alla conferma dell'arrivo sull'hardware sottostante.
*/
int main(int argc, char *argv[]) {
int fd;
char *filename = "/etc/fstab";
/* Si apre un file in sola lettura, il terzo parametro non e' necessario*/
if ( (fd = open(filename, O_RDONLY)) < 0) {
fprintf(stderr, "Err: (%d) - %s\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
/* Si chiude subito il canale di comunicazione stabilito con il kernel,
senza eseguire alcuna operazione aggiuntiva */
close(fd);
/* Due costanti simboliche in relazione tra loro; nel caso specifico se il
file e' gia' presente nel filesystem la funzione open() ritorna un errore
EEXIST */
if ((fd = open(argv[0], O_CREAT | O_EXCL)) < 0) {
fprintf(stderr, "Err: (%d) - %s, %s\n", errno, strerror(errno), *argv);
/* argv[0] e *argv puntano alla medesima stringa, ovvero il nome del
programma in esecuzione. */
exit(EXIT_FAILURE);
}
close(fd);
return(EXIT_SUCCESS);
}