Difference between revisions of "SYS CALL viste a lezione."
(→SIGNAL) |
|||
(35 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | + | ==Controllo processi== | |
+ | ===FORK=== | ||
Crea un nuovo processo duplicando il processo chiamante. Il nuovo processo , chiamato figlio, é un duplicato esatto del processo chiamante , chiamato padre. | Crea un nuovo processo duplicando il processo chiamante. Il nuovo processo , chiamato figlio, é un duplicato esatto del processo chiamante , chiamato padre. | ||
Line 32: | Line 33: | ||
esempio3(fork e malloc):<br/> | esempio3(fork e malloc):<br/> | ||
− | (sottolineerei che lo spazio di indirizzamento è di fatto separato: i due processi hanno una analoga visione dell'indirizzamento logico, che però è specifico di ogni processo e i dati sono memorizzati fisicamente in aree di memoria diverse. am_20131110) | + | '''(sottolineerei che lo spazio di indirizzamento è di fatto separato: i due processi hanno una analoga visione dell'indirizzamento logico, che però è specifico di ogni processo e i dati sono memorizzati fisicamente in aree di memoria diverse. am_20131110)''' |
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
#include <stdio.h> | #include <stdio.h> | ||
Line 49: | Line 50: | ||
else { | else { | ||
p = malloc(sizeof(int)); | p = malloc(sizeof(int)); | ||
− | printf("%d %p pid : %d , ppid : %d \n",*p,p,getpid(),getppid()); //i puntatori restituiranno lo stesso indirizzo di memoria sia per il padre che per il figlio perché condividono lo stesso spazio di indirizzamento | + | printf("%d %p pid : %d , ppid : %d \n",*p,p,getpid(),getppid()); //i puntatori restituiranno lo stesso indirizzo di memoria sia per il padre che per il figlio |
− | + | sleep(1); //perché condividono lo stesso spazio di indirizzamento | |
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | ||
+ | ===_EXIT=== | ||
Termina il proceso chiamante. | Termina il proceso chiamante. | ||
− | esempio1 | + | |
+ | esempio1: | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
#include <stdio.h> | #include <stdio.h> | ||
Line 68: | Line 71: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | esempio2(atexit) | + | esempio2(atexit): |
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
#include <stdio.h> | #include <stdio.h> | ||
Line 93: | Line 96: | ||
− | + | ===WAIT=== | |
Aspetta che un processo cambi di stato. | Aspetta che un processo cambi di stato. | ||
Line 110: | Line 113: | ||
printf(" padre : %d figlio : %d \n",getpid(),pid); | printf(" padre : %d figlio : %d \n",getpid(),pid); | ||
sleep(10); | sleep(10); | ||
− | waitpid(pid,status,0); | + | waitpid(pid,&status,0); |
− | printf(" exit status %d \n",WEXITSTATUS(status)); | + | printf(" exit status %d \n",WEXITSTATUS(status)); //Macro che restituisce l' exit status del figlio,cioè gli otto bit meno significativi dello status che il figlio |
− | } | + | } //specifica in una chiamata di _exit o exit o come argomento di ritorno del main. |
else { | else { | ||
printf(" figlio : %d padre : %d \n",getpid(),getppid()); | printf(" figlio : %d padre : %d \n",getpid(),getppid()); | ||
Line 136: | Line 139: | ||
printf(" padre : %d figlio : %d \n",getpid(),pid); | printf(" padre : %d figlio : %d \n",getpid(),pid); | ||
sleep(5); | sleep(5); | ||
− | waitpid(pid,status,0); | + | waitpid(pid,&status,0); |
− | if (WIFEXITED(status)) | + | if (WIFEXITED(status)) //Macro che restituisce true se il figlio termina normalmente, cioé chiamando _exit o exit oppure tramite il return del main |
printf(" exit status %d \n", WEXITSTATUS(status)); | printf(" exit status %d \n", WEXITSTATUS(status)); | ||
− | else if(WIFSIGNALED(status) ) | + | else if(WIFSIGNALED(status) ) //Macro che restituisce true se il figlio é terminato da un segnale |
− | printf("signal : %d \n", WTERMSIG(status) ); | + | printf("signal : %d \n", WTERMSIG(status) ); //Macro che restituisce il numero del segnale che causa la terminazione del processo figlio |
} | } | ||
else { | else { | ||
Line 153: | Line 156: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | ===EXEC=== | ||
+ | Esegue un programma. | ||
+ | La famiglia di funzioni exec() rimpiazza l'immagine del processo corrente con l'immagine di un nuovo processo. | ||
+ | |||
+ | esempio1: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/wait.h> | ||
+ | |||
+ | int main (int argc, char *argv[]){ | ||
+ | pid_t pid; | ||
+ | if( pid = fork() ){ | ||
+ | int status; | ||
+ | printf(" padre : %d figlio : %d \n",getpid(),pid); | ||
+ | sleep(5); | ||
+ | waitpid(pid,&status,0); | ||
+ | if (WIFEXITED(status)) | ||
+ | printf(" exit status %d \n", WEXITSTATUS(status)); | ||
+ | else if( WIFSIGNALED(status) ) | ||
+ | printf("signal : %d \n", WTERMSIG(status) ); | ||
+ | } | ||
+ | else { | ||
+ | char *args[] = {"ls","-l",(char *)0}; | ||
+ | execvp("ls",args); //funzione di libreria che prende in input il path(p) e un vettore(v). | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | esempio2: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/wait.h> | ||
+ | |||
+ | int main (int argc, char *argv[]){ | ||
+ | pid_t pid; | ||
+ | if( pid = fork() ){ | ||
+ | int status; | ||
+ | printf(" padre : %d figlio : %d %s \n",getpid(),pid,argv[1]); | ||
+ | sleep(5); | ||
+ | waitpid(pid,&status,0); | ||
+ | if (WIFEXITED(status)) | ||
+ | printf(" exit status %d \n", WEXITSTATUS(status)); | ||
+ | else if( WIFSIGNALED(status) ) | ||
+ | printf("signal : %d \n", WTERMSIG(status) ); | ||
+ | } | ||
+ | else { | ||
+ | execvp(argv[2],argv+2); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==Gestione File== | ||
+ | * int open(const char *path, int oflag, ...);<br/> | ||
+ | * int creat(const char *path, mode_t mode); | ||
+ | * int close(int filedes); | ||
+ | * off_t lseek(int filedes, off_t offset, int whence); | ||
+ | * ssize_t read(int filedes, void *buf, size_t nbyte); | ||
+ | * ssize_t write(int filedes, const void *buf, size_t nbyte); | ||
+ | |||
+ | Qualche esempio? Iniziamo con i file "con il buco" visti a lezione? | ||
+ | |||
+ | |||
+ | |||
+ | ===OPEN/WRITE/CLOSE=== | ||
+ | |||
+ | *Open: apre e possibilmente crea un file o un device. | ||
+ | *Write: scrive su il file descriptor. | ||
+ | *Close: chiude il file descriptor. | ||
+ | |||
+ | |||
+ | Esempio1: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | |||
+ | |||
+ | int main ( int argc , char *argv[] ){ | ||
+ | int fd = open( argv[1] , O_RDWR | O_CREAT | O_TRUNC ,0666); | ||
+ | write( fd , argv[2] , strlen( argv[2] ) ); | ||
+ | close( fd); | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===LSEEK/READ=== | ||
+ | |||
+ | |||
+ | *Lseek: sposta l'offset del file descriptor. | ||
+ | *Read: legge da un file descriptor. | ||
+ | |||
+ | |||
+ | |||
+ | Esempio1(sparse file o file ciambella): | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | |||
+ | |||
+ | int main ( int argc , char *argv[] ){ | ||
+ | int fd = open( argv[1] , O_RDWR | O_CREAT | O_TRUNC ,0666); | ||
+ | write( fd , argv[2] , strlen( argv[2] ) ); | ||
+ | lseek( fd, 1000000 , SEEK_SET ); | ||
+ | write( fd , argv[2] , strlen( argv[2] ) ); | ||
+ | close( fd); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | Esempio2(copia di un file): | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | #define BUFFSIZE 1024 | ||
+ | |||
+ | char buff[BUFFSIZE]; | ||
+ | |||
+ | |||
+ | |||
+ | int main ( int argc , char *argv[] ){ | ||
+ | int fin = open( argv[1] , O_RDONLY ); | ||
+ | int fout = open( argv[2] , O_RDWR | O_CREAT | O_TRUNC ,0666); | ||
+ | ssize_t n; | ||
+ | while( ( n = read( fin , buff , BUFFSIZE ) ) != 0 ){ | ||
+ | write( fout , buff , n ); | ||
+ | } | ||
+ | close( fin); | ||
+ | close( fout); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | Esempio3(copia di uno sparse file): | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | #define BUFFSIZE 1024 //la copia avviene per blocchi di 1024B | ||
+ | |||
+ | char buff[BUFFSIZE]; | ||
+ | |||
+ | int isEmpty( char *s , int l ){ | ||
+ | int i; | ||
+ | for( i = 0 ; i < l ; i++ ) | ||
+ | if( s[i] != 0 ) return (0); | ||
+ | return(1); | ||
+ | |||
+ | |||
+ | # if 0 | ||
+ | for ( i = 0 ; ( i < l ) && ( s[i] != 0 ) ; i++ ) | ||
+ | ; | ||
+ | return ( i == l ); //codice più compatto | ||
+ | |||
+ | |||
+ | for( i = 0 ; i < l ; i++ ) | ||
+ | if( s[i] != 0 ) goto nonempty; | ||
+ | return1; | ||
+ | nonempty: | ||
+ | return0; //in stile kernel | ||
+ | #endif | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | int main ( int argc , char *argv[] ){ | ||
+ | int fin = open( argv[1] , O_RDONLY ); | ||
+ | int fout = open( argv[2] , O_RDWR | O_CREAT | O_TRUNC ,0666); | ||
+ | ssize_t n; | ||
+ | while( ( n = read( fin , buff , BUFFSIZE ) ) != 0 ){ | ||
+ | if (isEmpty( buff , n ) ) //il codice in questo esempio é ottimizzato per gli sparse file. | ||
+ | lseek( fout , n , SEEK_CUR ); | ||
+ | else | ||
+ | write( fout , buff , n ); | ||
+ | } | ||
+ | close( fin); | ||
+ | close( fout); | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
+ | Esempio4(Buffer ed efficienza): | ||
+ | <syntaxhighlight lang="C"> | ||
+ | /*eseguire lo script di cui sotto in modo da osservare come il buffer modifichi l'efficienza della copia per blocchi di byte | ||
+ | |||
+ | dd if=/dev/urandom of=casual bs=1024 count=102400 | ||
+ | for size in 128 256 512 1024 2048 4096 | ||
+ | do | ||
+ | time ./eseguibile casual ricasual $size | ||
+ | done | ||
+ | */ | ||
+ | |||
+ | |||
+ | #include <stdio.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | |||
+ | int isEmpty( char *s , int l ){ | ||
+ | int i; | ||
+ | for( i = 0 ; i < l ; i++ ) | ||
+ | if( s[i] != 0 ) return (0); | ||
+ | return(1); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | int main ( int argc , char *argv[] ){ | ||
+ | int fin = open( argv[1] , O_RDONLY ); | ||
+ | int fout = open( argv[2] , O_RDWR | O_CREAT | O_TRUNC ,0666); | ||
+ | int buffsize = atoi( argv[3] ); | ||
+ | char buff[buffsize]; | ||
+ | ssize_t n; | ||
+ | while( ( n = read( fin , buff , buffsize ) ) != 0 ){ | ||
+ | if (isEmpty( buff , n ) ) | ||
+ | lseek( fout , n , SEEK_CUR ); | ||
+ | else | ||
+ | write( fout , buff , n ); | ||
+ | } | ||
+ | close( fin); | ||
+ | close( fout); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===TRUNCATE=== | ||
+ | |||
+ | |||
+ | *Truncate: tronca il file a una specifica lunghezza. | ||
+ | |||
+ | Esempio(viene usata per creare File Buco Nero): | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <unistd.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <fcntl.h> | ||
+ | |||
+ | int main( int argc , char *argv[] ) { | ||
+ | int fd = open( argv[1] , O_WRONLY | O_CREAT | O_TRUNC , 0666 ); | ||
+ | ftruncate( fd , atoi( argv[2] ) ); | ||
+ | close( fd ); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===DUP=== | ||
+ | |||
+ | *Dup: duplica il file descriptor. | ||
+ | |||
+ | Esempio: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include<stdio.h> | ||
+ | #include<fcntl.h> | ||
+ | #include <unistd.h> | ||
+ | |||
+ | int main( int argc , char *argv[]){ | ||
+ | int fd = open( argv[1] , O_WRONLY | O_CREAT | O_TRUNC , 0666 ); | ||
+ | close(1); | ||
+ | dup(fd); //dup2(fd,1) produce lo stesso effetto | ||
+ | printf("Hello World \n"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | ===FUNZIONI SULLE DIRECTORY=== | ||
+ | |||
+ | Esempio1: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <dirent.h> | ||
+ | |||
+ | |||
+ | int mystrcmp( const void *a , const void *b ){ | ||
+ | char **pa = (char **)a; | ||
+ | char **pb = (char **)b; | ||
+ | return strcmp( *pa , *pb ); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | int main ( int argc , char *argv[] ){ | ||
+ | DIR *d; | ||
+ | struct dirent *de; | ||
+ | char **names; | ||
+ | int i , count = 0; | ||
+ | d = opendir( argv[1] ); | ||
+ | while( ( de = readdir(d) ) != NULL ) | ||
+ | count++; | ||
+ | rewinddir(d); | ||
+ | names = (char **)calloc( count , sizeof(char *) ); | ||
+ | count=0; | ||
+ | while( ( de = readdir(d) ) != NULL ) | ||
+ | names[count++] = strdup( de->d_name ); | ||
+ | closedir(d); | ||
+ | qsort( names , count , sizeof(char *) , mystrcmp ); | ||
+ | for( i = 0 ; i < count ; i++ ) | ||
+ | printf(" %s ", names[i] ); | ||
+ | printf("\n"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
+ | Esempio2: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include<stdio.h> | ||
+ | #include<stdlib.h> | ||
+ | #include<string.h> | ||
+ | #include<dirent.h> | ||
+ | |||
+ | |||
+ | int main( int argc , char *argv[] ){ | ||
+ | int count; | ||
+ | int i; | ||
+ | struct dirent **de; | ||
+ | count = scandir( argv[1] , &de , NULL , alphasort ); | ||
+ | for ( i = 0 ; i < count ; i++ ){ | ||
+ | printf("%s ",de[i]->d_name); | ||
+ | free(de[i]); | ||
+ | } | ||
+ | printf("\n"); | ||
+ | free(de); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
+ | ==Segnali== | ||
+ | ===SIGNAL=== | ||
+ | |||
+ | Esempio1(programma riluttante a morire): | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include<stdio.h> | ||
+ | #include<signal.h> | ||
+ | |||
+ | void no( int sn ) | ||
+ | { | ||
+ | printf("io non termino! %d\n" , sn ); | ||
+ | } | ||
+ | |||
+ | |||
+ | int main( int argc , char *argv ) | ||
+ | { | ||
+ | signal( SIGTERM , no ); | ||
+ | signal( SIGINT , no ); | ||
+ | while(1){ | ||
+ | pause(); | ||
+ | printf("ciao\n"); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | Esempio2(il figlio termina): | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include<stdio.h> | ||
+ | #include<signal.h> | ||
+ | #include<sys/types.h> | ||
+ | #include<sys/wait.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | |||
+ | void child( int sn ) | ||
+ | { | ||
+ | int status; | ||
+ | wait(&status); | ||
+ | printf("il figlio termina! \n" ); | ||
+ | } | ||
+ | |||
+ | |||
+ | int main( int argc , char *argv ) | ||
+ | { | ||
+ | signal( SIGCHLD , child ); | ||
+ | if ( fork() > 0 ){ | ||
+ | while(1) | ||
+ | pause(); | ||
+ | } | ||
+ | else { | ||
+ | sleep(3); | ||
+ | exit(1); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
Correggetemi se ho scritto delle sciocchezze. | Correggetemi se ho scritto delle sciocchezze. | ||
− | + | -Pirata- |
Latest revision as of 11:48, 4 December 2013
Controllo processi
FORK
Crea un nuovo processo duplicando il processo chiamante. Il nuovo processo , chiamato figlio, é un duplicato esatto del processo chiamante , chiamato padre.
esempio1:
#include <stdio.h>
#include <unistd.h>
void main (void){
if(fork()){
printf("uno %d %d \n", getpid(), getppid() ); // getpid() stampa il pid del processo corrente , getppid() stampa il pid del processo padre
sleep(2);} //se togliessimo lo sleep;il processo figlio stamperebbe come getppid() 1,perché essendo il padre terminato e lui rimasto orfano,il nuovo padre diventa init
else
printf("due %d %d \n",getpid(), getppid() );
}
esempio2(una piccola osservazione sull'eredità del buffer):
#include <stdio.h>
#include <unistd.h>
void main (void){
printf("cucù! : "); //notare la differenza se nella sringa metto \n
if(fork())
printf("uno %d %d \n", getpid(), getppid() );
else
printf("due %d %d \n",getpid(), getppid() );
}
esempio3(fork e malloc):
(sottolineerei che lo spazio di indirizzamento è di fatto separato: i due processi hanno una analoga visione dell'indirizzamento logico, che però è specifico di ogni processo e i dati sono memorizzati fisicamente in aree di memoria diverse. am_20131110)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main (void){
int *p;
if( fork() ){
p = malloc(sizeof(int));
*p = 45;
printf("%d %p pid : %d , ppid : %d \n",*p,p,getpid(),getppid());
sleep(2);
}
else {
p = malloc(sizeof(int));
printf("%d %p pid : %d , ppid : %d \n",*p,p,getpid(),getppid()); //i puntatori restituiranno lo stesso indirizzo di memoria sia per il padre che per il figlio
sleep(1); //perché condividono lo stesso spazio di indirizzamento
}
}
_EXIT
Termina il proceso chiamante.
esempio1:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main (int argc,char *argv[]){
_exit(0); //Sys call che termina il processo chiamante
}
esempio2(atexit):
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void at1(void){
printf("at1 \n");
}
void at2(void){
printf("at2 \n");
}
int main (int argc,char *argv[]){
printf("brutal kill \n");
atexit(at1); //funzione di libreria che termina il processo passato come argomento
atexit(at2);
}
//le funzioni passate ad atexit vengono eseguite in modo inverso rispetto all'invocazione
WAIT
Aspetta che un processo cambi di stato.
esempio1:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main (int argc, char *argv[]){
pid_t pid;
if( pid = fork() ){
int status;
printf(" padre : %d figlio : %d \n",getpid(),pid);
sleep(10);
waitpid(pid,&status,0);
printf(" exit status %d \n",WEXITSTATUS(status)); //Macro che restituisce l' exit status del figlio,cioè gli otto bit meno significativi dello status che il figlio
} //specifica in una chiamata di _exit o exit o come argomento di ritorno del main.
else {
printf(" figlio : %d padre : %d \n",getpid(),getppid());
sleep(1);
exit(1);
}
}
esempio2:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main (int argc, char *argv[]){
pid_t pid;
if( pid = fork() ){
int status;
printf(" padre : %d figlio : %d \n",getpid(),pid);
sleep(5);
waitpid(pid,&status,0);
if (WIFEXITED(status)) //Macro che restituisce true se il figlio termina normalmente, cioé chiamando _exit o exit oppure tramite il return del main
printf(" exit status %d \n", WEXITSTATUS(status));
else if(WIFSIGNALED(status) ) //Macro che restituisce true se il figlio é terminato da un segnale
printf("signal : %d \n", WTERMSIG(status) ); //Macro che restituisce il numero del segnale che causa la terminazione del processo figlio
}
else {
int *p;
printf(" figlio : %d padre : %d \n",getpid(),getppid());
sleep(1);
p = (int *)42;
*p = 43;
exit(2);
}
}
EXEC
Esegue un programma. La famiglia di funzioni exec() rimpiazza l'immagine del processo corrente con l'immagine di un nuovo processo.
esempio1:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main (int argc, char *argv[]){
pid_t pid;
if( pid = fork() ){
int status;
printf(" padre : %d figlio : %d \n",getpid(),pid);
sleep(5);
waitpid(pid,&status,0);
if (WIFEXITED(status))
printf(" exit status %d \n", WEXITSTATUS(status));
else if( WIFSIGNALED(status) )
printf("signal : %d \n", WTERMSIG(status) );
}
else {
char *args[] = {"ls","-l",(char *)0};
execvp("ls",args); //funzione di libreria che prende in input il path(p) e un vettore(v).
}
}
esempio2:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main (int argc, char *argv[]){
pid_t pid;
if( pid = fork() ){
int status;
printf(" padre : %d figlio : %d %s \n",getpid(),pid,argv[1]);
sleep(5);
waitpid(pid,&status,0);
if (WIFEXITED(status))
printf(" exit status %d \n", WEXITSTATUS(status));
else if( WIFSIGNALED(status) )
printf("signal : %d \n", WTERMSIG(status) );
}
else {
execvp(argv[2],argv+2);
}
}
Gestione File
- int open(const char *path, int oflag, ...);
- int creat(const char *path, mode_t mode);
- int close(int filedes);
- off_t lseek(int filedes, off_t offset, int whence);
- ssize_t read(int filedes, void *buf, size_t nbyte);
- ssize_t write(int filedes, const void *buf, size_t nbyte);
Qualche esempio? Iniziamo con i file "con il buco" visti a lezione?
OPEN/WRITE/CLOSE
- Open: apre e possibilmente crea un file o un device.
- Write: scrive su il file descriptor.
- Close: chiude il file descriptor.
Esempio1:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main ( int argc , char *argv[] ){
int fd = open( argv[1] , O_RDWR | O_CREAT | O_TRUNC ,0666);
write( fd , argv[2] , strlen( argv[2] ) );
close( fd);
}
LSEEK/READ
- Lseek: sposta l'offset del file descriptor.
- Read: legge da un file descriptor.
Esempio1(sparse file o file ciambella):
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main ( int argc , char *argv[] ){
int fd = open( argv[1] , O_RDWR | O_CREAT | O_TRUNC ,0666);
write( fd , argv[2] , strlen( argv[2] ) );
lseek( fd, 1000000 , SEEK_SET );
write( fd , argv[2] , strlen( argv[2] ) );
close( fd);
}
Esempio2(copia di un file):
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFFSIZE 1024
char buff[BUFFSIZE];
int main ( int argc , char *argv[] ){
int fin = open( argv[1] , O_RDONLY );
int fout = open( argv[2] , O_RDWR | O_CREAT | O_TRUNC ,0666);
ssize_t n;
while( ( n = read( fin , buff , BUFFSIZE ) ) != 0 ){
write( fout , buff , n );
}
close( fin);
close( fout);
}
Esempio3(copia di uno sparse file):
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFFSIZE 1024 //la copia avviene per blocchi di 1024B
char buff[BUFFSIZE];
int isEmpty( char *s , int l ){
int i;
for( i = 0 ; i < l ; i++ )
if( s[i] != 0 ) return (0);
return(1);
# if 0
for ( i = 0 ; ( i < l ) && ( s[i] != 0 ) ; i++ )
;
return ( i == l ); //codice più compatto
for( i = 0 ; i < l ; i++ )
if( s[i] != 0 ) goto nonempty;
return1;
nonempty:
return0; //in stile kernel
#endif
}
int main ( int argc , char *argv[] ){
int fin = open( argv[1] , O_RDONLY );
int fout = open( argv[2] , O_RDWR | O_CREAT | O_TRUNC ,0666);
ssize_t n;
while( ( n = read( fin , buff , BUFFSIZE ) ) != 0 ){
if (isEmpty( buff , n ) ) //il codice in questo esempio é ottimizzato per gli sparse file.
lseek( fout , n , SEEK_CUR );
else
write( fout , buff , n );
}
close( fin);
close( fout);
}
Esempio4(Buffer ed efficienza):
/*eseguire lo script di cui sotto in modo da osservare come il buffer modifichi l'efficienza della copia per blocchi di byte
dd if=/dev/urandom of=casual bs=1024 count=102400
for size in 128 256 512 1024 2048 4096
do
time ./eseguibile casual ricasual $size
done
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int isEmpty( char *s , int l ){
int i;
for( i = 0 ; i < l ; i++ )
if( s[i] != 0 ) return (0);
return(1);
}
int main ( int argc , char *argv[] ){
int fin = open( argv[1] , O_RDONLY );
int fout = open( argv[2] , O_RDWR | O_CREAT | O_TRUNC ,0666);
int buffsize = atoi( argv[3] );
char buff[buffsize];
ssize_t n;
while( ( n = read( fin , buff , buffsize ) ) != 0 ){
if (isEmpty( buff , n ) )
lseek( fout , n , SEEK_CUR );
else
write( fout , buff , n );
}
close( fin);
close( fout);
}
TRUNCATE
- Truncate: tronca il file a una specifica lunghezza.
Esempio(viene usata per creare File Buco Nero):
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main( int argc , char *argv[] ) {
int fd = open( argv[1] , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
ftruncate( fd , atoi( argv[2] ) );
close( fd );
}
DUP
- Dup: duplica il file descriptor.
Esempio:
#include<stdio.h>
#include<fcntl.h>
#include <unistd.h>
int main( int argc , char *argv[]){
int fd = open( argv[1] , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
close(1);
dup(fd); //dup2(fd,1) produce lo stesso effetto
printf("Hello World \n");
}
FUNZIONI SULLE DIRECTORY
Esempio1:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
int mystrcmp( const void *a , const void *b ){
char **pa = (char **)a;
char **pb = (char **)b;
return strcmp( *pa , *pb );
}
int main ( int argc , char *argv[] ){
DIR *d;
struct dirent *de;
char **names;
int i , count = 0;
d = opendir( argv[1] );
while( ( de = readdir(d) ) != NULL )
count++;
rewinddir(d);
names = (char **)calloc( count , sizeof(char *) );
count=0;
while( ( de = readdir(d) ) != NULL )
names[count++] = strdup( de->d_name );
closedir(d);
qsort( names , count , sizeof(char *) , mystrcmp );
for( i = 0 ; i < count ; i++ )
printf(" %s ", names[i] );
printf("\n");
}
Esempio2:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dirent.h>
int main( int argc , char *argv[] ){
int count;
int i;
struct dirent **de;
count = scandir( argv[1] , &de , NULL , alphasort );
for ( i = 0 ; i < count ; i++ ){
printf("%s ",de[i]->d_name);
free(de[i]);
}
printf("\n");
free(de);
}
Segnali
SIGNAL
Esempio1(programma riluttante a morire):
#include<stdio.h>
#include<signal.h>
void no( int sn )
{
printf("io non termino! %d\n" , sn );
}
int main( int argc , char *argv )
{
signal( SIGTERM , no );
signal( SIGINT , no );
while(1){
pause();
printf("ciao\n");
}
}
Esempio2(il figlio termina):
#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
#include <stdlib.h>
void child( int sn )
{
int status;
wait(&status);
printf("il figlio termina! \n" );
}
int main( int argc , char *argv )
{
signal( SIGCHLD , child );
if ( fork() > 0 ){
while(1)
pause();
}
else {
sleep(3);
exit(1);
}
}
Correggetemi se ho scritto delle sciocchezze. -Pirata-