Difference between revisions of "SYS CALL viste a lezione."

From Sistemi Operativi
Jump to navigation Jump to search
 
(41 intermediate revisions by 2 users not shown)
Line 1: Line 1:
* FORK
+
==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 31: Line 32:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
esempio3(fork e malloc):
+
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)'''
 
<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
 
#include <stdio.h>
 
#include <stdio.h>
Line 48: 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);
+
sleep(1);                                                          //perché condividono lo stesso spazio di indirizzamento
 
}
 
}
 
}  
 
}  
Line 55: Line 57:
  
  
 +
===_EXIT===
 +
Termina il proceso chiamante.
  
* WAIT
+
esempio1:
 +
<syntaxhighlight lang="C">
 +
#include <stdio.h>
 +
#include <unistd.h>
 +
#include <stdlib.h>
 +
 
 +
int main (int argc,char *argv[]){
 +
_exit(0);                    //Sys call che termina il processo chiamante
 +
}
 +
</syntaxhighlight>
 +
 
 +
esempio2(atexit):
 +
<syntaxhighlight lang="C">
 +
#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
 +
</syntaxhighlight>
 +
 
 +
 
 +
===WAIT===
 
Aspetta che un processo cambi di stato.
 
Aspetta che un processo cambi di stato.
  
Line 67: Line 107:
 
#include <sys/wait.h>
 
#include <sys/wait.h>
  
int main (int argc, char* argv[]){
+
int main (int argc, char *argv[]){
 
pid_t pid;
 
pid_t pid;
 
if( pid = fork() ){
 
if( pid = fork() ){
Line 73: 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 {
 +
printf(" figlio : %d  padre : %d \n",getpid(),getppid());
 +
sleep(1);
 +
exit(1);
 +
}
 +
}
 +
</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 \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 {
 
else {
 +
int *p;
 
printf(" figlio : %d  padre : %d \n",getpid(),getppid());
 
printf(" figlio : %d  padre : %d \n",getpid(),getppid());
 
sleep(1);
 
sleep(1);
exit(1);
+
p = (int *)42;
 +
*p = 43;
 +
exit(2);
 
}
 
}
 
}
 
}
 
</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)
+
-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-