System call interrotte da segnali
Esempio: gestore SIGINT, interruzione system call pause
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void miogestore
(int num_segnale
) {
printf("catturato segnale %d\n", num_segnale
);
}
#define USE_PERROR 0 // vedere anche quando: valore 1
int main
() {
struct sigaction act =
{ 0 };
act.
sa_handler = miogestore;
int res = sigaction
(SIGINT, &act,
NULL);
if (res ==
-1) {
perror
("errore nella sigaction");
exit
(1);
}
res = pause
();
printf("return value pause: %d\n", res
);
if (res ==
-1) {
#if USE_PERROR
perror
("causa errore pause");
#else
switch (errno
) {
case EINTR:
printf("Interrotta da segnale.\n");
break;
// pause ammette solo EINTR come errore, vedere: man pause
// quindi SOLO per questa system call ha poco considerare casi errno != EINTR
default:
perror
("causa errore pause");
}
#endif
}
return 0;
}
Esempio: gestore SIGCHLD, interruzione system call
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void myhandler
(int signo
) {
printf("figlio e' terminato\n");
}
int main
() {
struct sigaction sa =
{0};
sa.
sa_handler = myhandler;
int res = sigaction
(SIGCHLD, &sa,
NULL);
printf("[pid=%d] genitore\n", getpid
());
pid_t pid = fork
();
if (pid ==
-1) {
perror
("errore nella fork");
exit
(EXIT_FAILURE
);
}
if (pid ==
0) { // processo figlio
printf("[pid=%d] figlio\n", getpid
());
_exit
(EXIT_SUCCESS
);
}
int s =
30;
res = sleep
(s
);
// genitore potrebbe fare qualcosa di piu' utile
// in questo esempio invoca una system call
if (res >
0)
printf("Genitore termina: sleep terminata prematuramente dopo %d secondi\n", s - res
);
else
printf("Genitore termina: sleep eseguita interamente per %d secondi\n", s
);
return EXIT_SUCCESS;
}
System call open, read, write, close
Scrittura di file
Versione
1:
#include <unistd.h> // read, write, close
#include <fcntl.h> // open
#include <stdlib.h> // exit
#include <stdio.h> // perror
char text[] = "This is a test\n";
int main(int argc, char* argv[]) {
int flags = O_WRONLY | O_CREAT | O_TRUNC; // O_WRONLY: file aperto in sola scrittura
// O_CREAT: se il file non esiste, verra' creato
// O_TRUNC: se il file esiste, trancare il contenuto
// se il file non esiste, allora dobbiamo indicare i permessi
mode_t mode = 0640; // Una costante che inizia con 0 (e non 0x) in C e' in notazione ottale
// 0640: user => rw, group => r, others => nessuno
// alternativa ad usare numero ottale: usare le costanti definite da POSIX
// mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP; // corrisponde a 0644
int fd = open("test.txt", flags, mode);
if (fd == -1) {
perror("Error in open");
exit(1);
}
if (write(fd, text, sizeof(text)) != sizeof(text)) { // verifica che abbiamo scritto tutto quello che volevamo scrivere
// se non e' cosi', terminiamo...
perror("Error in write");
exit(1);
}
if (close(fd)) {
perror("Error in close");
exit(1);
}
return 0;
}
Versione
2 (gestione
EINTR):
#include <unistd.h> // read, write, close
#include <fcntl.h> // open
#include <stdlib.h> // exit
#include <stdio.h> // perror
#include <errno.h>
char text
[] =
"This is a test\n";
int main
(int argc,
char* argv
[]) {
int flags = O_WRONLY | O_CREAT | O_TRUNC;
mode_t mode =
0640;
int fd = open
("test.txt", flags, mode
);
if (fd ==
-1) {
perror
("Error in open");
exit
(1);
}
ssize_t byte_scritti =
0;
ssize_t byte_da_scrivere =
sizeof(text
);
// sizeof funziona correttamente solo text e' dichiarato come array e non un puntatore ad una stringa!
printf("Byte da scrivere: %d\n", byte_da_scrivere
);
while (byte_scritti < byte_da_scrivere
) {
ssize_t res = write
(fd, text + byte_scritti,
sizeof(text
) - byte_scritti
);
if (res ==
-1) { // errore
// analizziamo la causa dell'errore
switch (errno
) {
case EINTR:
// se e' arrivato un segnale, non e' un errore fatale possiamo ritentare la scrittura
continue;
break;
default:
// consideriamo le altre cause come errori fatali non recuperabili
perror
("errore write");
exit
(EXIT_FAILURE
);
}
}
byte_scritti += res;
printf("Byte scritti: %d\n", res
);
}
if (close
(fd
)) {
perror
("Error in close");
exit
(EXIT_FAILURE
);
}
return 0;
}
Comando cat
Realizzazione comando
cat:
#include <unistd.h> // read, write, close
#include <fcntl.h> // open
#include <stdlib.h> // exit
#include <stdio.h> // printf
#include <errno.h> // errno, EINTR
int main
(int argc,
char* argv
[]) {
char buffer
[256];
ssize_t res;
if (argc <
2) {
printf("Usage: %s filename\n", argv
[0]);
exit
(1);
}
int fd = open
(argv
[1], O_RDONLY
);
if (fd ==
-1) {
perror
("Error in open");
exit
(1);
}
while(1) {
res = read
(fd, buffer,
sizeof(buffer
));
if (res ==
-1) {
<