Estratto del documento

Programma di gestione file e processi

Creazione e gestione di un file di testo

Il programma crea un file, si mette in attesa di leggere stringhe da tastiera che andrà a scrivere di volta in volta nel file. Quando la stringa letta risulterà essere "END", il programma scrive "END" nel file, lo chiude e termina.

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main() {
    int car_scrit;
    int car_let=0;
    char buffer[80];
    int fd=open("file.txt", O_CREAT|O_WRONLY|O_TRUNC , 0777);
    int k=strlen(buffer); // Salvo la lunghezza del buffer
    buffer[car_let]='/0';
    buffer[k-1]=buffer[k];

    while(strcmp(buffer,"END")!=0) {
        car_scrit=write(fd, buffer, car_let); // Scrivo sul file aperto il numero di caratteri acquisiti dalla lettura che ora stanno in buffer
        for(int i=0;i<80;i++) {
            buffer[i]=0; // Dopo che ho copiato tutto sul file svuoto il buffer perché dentro ci deve essere solo "END" se voglio poter fare il confronto
        }
        car_let=read(0,&buffer,80); // Rifaccio la lettura
        k=strlen(buffer);
        buffer[k-1]=buffer[k];
    }
    printf("Ho terminato di acquisire caratteri da tastiera\n");
    write(fd,buffer,k);
    close(fd);
    return 0;
}

Lettura di un file e stampa a video

Programma che apre in sola lettura il file precedentemente creato e stampa a video il suo contenuto.

#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<fcntl.h>

main() {
    int fd=open("da_copiare.txt",O_RDONLY);
    char buff[100];
    int nread;
    
    nread=read(fd,buff,100);
    write(1,buff,nread);

    close(fd);

    return 0;
}

Copia di un file

Programma che copia il contenuto di un file preesistente (parametro argv[1]) in un nuovo file (parametro argv[2]).

#include <stdio.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/wait.h>

int main(int argc, char*argv[]) {
    /* argv[0] è il nome del programma eseguibile, argv[1] e argv[2] sono i due parametri, quindi argc (che è il numero di parametri + 1) deve essere pari a tre */

    int nread;
    char buff[100];

    if (argc != 3) { /* Se passo un numero errato di parametri dico errore */
        printf("Errore, sbagliato il numero dei parametri\n");
        exit(0);
    }

    int fd_input=open(argv[1], O_RDWR);
    int fd_output=creat(argv[2], 0777);
    /* Altro modo per creare il file è int fd_output=open(argv[2],O_CREAT|O_RDWR|O_TRUNC , 0777); */
    int sl=strlen(buff);
    while(( nread=read(fd_input,buff,sl)) > 0) {
        write(fd_output,buff,nread);
    }

    close(fd_input);
    close(fd_output);

    return 0;
}

Processi padre e figlio

Il processo figlio crea un nuovo file (il cui nome deve essere specificato come argomento), il processo padre attende il completamento del figlio e successivamente legge il contenuto del file.

#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>
#define N 256

int main (int argc, char **argv) {
    int nread, nwrite = 0, atteso, status, fileh, pid;
    char st1[N];
    char st2[N] = "";
    /* Apertura in lettura/scrittura */
    fileh = open(argv[1], O_CREAT|O_RDWR|O_TRUNC, 0644);
    if (fileh == -1)
        perror("open error");
    if((pid=fork()) < 0) {
        perror("fork error");
        close(fileh);
        exit(-1);
    }
    else if (pid==0) {
        /* Figlio: legge una stringa che l'utente immette da tastiera */
        scanf("%s",st1);
        nwrite = write(fileh, st1, strlen(st1));
        if (nwrite == -1)
            perror("write error");
        exit(0);
    }
    else {
        atteso=wait(&status); /* Attesa del figlio */
        lseek(fileh, 0, SEEK_SET);
        nread = read(fileh, st2, N);
        if (nread == -1)
            perror("read error");
        printf("nread=%d\n",nread);
        printf("Il figlio ha scritto la stringa %s\n", st2);
        close(fileh);
        return(0);
    }
    exit(0);
}

Padre che uccide il figlio

Il padre crea un figlio e dopo tre secondi lo uccide.

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    int pid;
    if ((pid=fork()) < 0) {
        perror("fork error");
        exit(-1);
    }
    else if (pid == 0) {
        /* Il figlio attende in un ciclo con busy waiting fino a quando riceve il segnale SIGKILL che lo fa terminare */
        for (;;)
            printf("Sono il figlio e sto ciclando all'infinito!\n");
        printf("Questo messaggio non dovrebbe mai essere visualizzato!\n");
        exit(0);
    }
    else {
        /* Il padre invia un segnale SIGKILL al figlio */
        sleep(3);
        kill(pid, SIGKILL);
        printf("\nSono il padre e ho ucciso il figlio!!\n");
        exit(1);
    }
}

Processo padre crea N figli

Processo padre crea N figli (N è passato come parametro) e aspetta la fine della loro esecuzione.

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(int argc,char**argv[]) {
    int status, i;
    pid_t pid;
    int N=atoi(argv[1]);

    /* Il padre crea N processi figli */
    for (i=0; i<N ; i++)
        if ((pid=fork())==0) {
            sleep(1);
            exit(10+i);
        }

    printf("Il numero è %d/n",N);
    /* Il padre attende i figli */
    while ((pid=waitpid(-1, &status, 0)) > 0) {
        if (WIFEXITED(status))
            printf("Il figlio %d ha terminato correttamente con exit status=%d\n",pid,WEXITSTATUS(status));
        else
            printf("Il figlio %d non ha terminato correttamente\n",pid);
    }
    exit(0);
}

Programma che riceve due stringhe da linea di comando

Il nome del file da creare e la stringa da scrivere nel file appena creato. Per farlo partire dal terminale di Linux si fa così:

lo chiamo Scrivifile.c
cd Scrivania
gcc scrivifile.c -o scivifile
./scrivifile "qui_scrivo.txt" "vdgdgdfgdfgdfgfdgdfgfdsg"
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<fcntl.h>

int main(int argc , char*argv[]) {
    //argv[0] è il nome dell'eseguibile
    //argv[1] è il primo parametro, il nome del file da creare
    //argv[2] è il secondo parametro, la stringa da scrivere nel file
    //argc è il numero di parametri che passo da linea di comando, che è pari a 2 parametri + 1

    if(argc !=3) { // Gestisco il caso in cui erro a mettere i parametri
        printf("Errore nell'immissione dei parametri /n");
        exit(0);
    }

    umask(0); // Per far passare tutti i valori di rwx che metto nella open
    int fd= open(argv[1],O_CREAT|O_TRUNC| O_RDWR,0777); // Creo il file il cui nome lo passo da shell
    int x=strlen(argv[2]); // La lunghezza della stringa che passo come secondo parametro è pari ad x
    write(fd,argv[2],x); // Scrivo nel file creato fd i primi x byte del secondo parametro

    close(fd);

    return 0;
}

Gestione di segnali tra processi

Programma in cui un processo crea N processi figli con N pari letto da tastiera e termina subito dopo. I processi figlio di indice i n/2 ≤ i < n inviano il segnale SIGUSR1 rispettivamente ai processi di indice (i-n/2) e terminano. I rimanenti processi figlio si mettono in attesa del segnale SIGUSR1 e poi terminano.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void signalHandler(int s) {
    if (s==SIGUSR1) {
        printf("Process PID:%d received signal\n",getpid());
    }
}

int main() {
    int n;
    printf("Greetings dott.Falken...please insert n:");
    scanf("%d",&n);
    if (n%2!=0) {
        n++;
        printf("You've inserted odd number so i add+1 (%d)\n",n);
    }
    pid_t p[n];
    int i=0;
    while(i<n) {
        p[i]=fork();
        if(!p[i]) {
            if(i<n/2) {
                signal(SIGUSR1,signalHandler);
                printf("Process n.%d PID:%d PPID:%d waiting for signal\n",i,getpid(),getppid());
                pause();
                exit(0);
            }
            else {
                sleep(1);
                printf("Process n.%d PID:%d PPID:%d sending signal to PID.(i-n/2):%d\n",i,getpid(),getppid(),p[i-n/2]);
                if(kill(p[i-n/2],SIGUSR1)<0)
                    perror("Error kill");
                exit(0);
            }
        }
        i++;
    }
    i=0;
    while(i<n) {
        int status;
        waitpid(p[i],&status,0);
        printf("Process PID:%d terminated with status %d\n",p[i],status);
        i++;
    }
    exit(0);
}

Comunicazione tra processi tramite pipe

Programma in cui un processo crea 2 processi figli P1 e P2. Successivamente vengono effettuate le seguenti operazioni: il processo padre invia tramite pipe il pid di P1 (pid1) a P2. Il processo P2 dopo aver ricevuto il pid del fratello esegue una exec passando pid1 come parametro di ingresso al nuovo eseguibile. Il nuovo eseguibile invia un segnale di tipo SIGUSR2 a P1 e termina. P1 aspetta il segnale SIGUSR2 e termina.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

void signalReceived(int s) {
    if(s==SIGUSR2) {
        printf("4-PID1 signal received:%d\n",s);
        exit(0);
    }
}

int main() {
    pid_t pid1, pid2;
    int vector[2];
    int status1, status2;

    if(pipe(vector)<0)
        perror("Error creating pipe\n");

    printf("Partenza, Sono il padre PID: %d\n",getpid());
    pid1=fork();

    if (!pid1) { // P1
        signal(SIGUSR2,signalReceived);
        printf("Sono P1 con PID:%d e PPID:%d\n",getpid(),getppid());
        printf("4-Sono P1 con PID:%d e PPID:%d e aspetto la signal\n",getpid(),getppid());
        pause();
    }
    else {
        printf("Sono il padre PID: %d\n",getpid());

        pid2=fork();
        if (!pid2) { // P2
            printf("Sono P2 con PID:%d e PPID:%d\n",getpid(),getppid());
            close(vector[1]);
            if(read(vector[0],&pid1,sizeof(pid1))<0)
                printf("Error reading pipe\n");
            else
                printf("1-Sono P2 con PID:%d e PPID:%d e ho letto dalla pipe il PID P1:%d\n",getpid(),getppid(),pid1);
            printf("2-Inizio eseguibile.\n");

            char buff[10];
            sprintf(buff,"%d",pid1);
            if(execl("19_07_07_exec",buff,0)<0)
                perror("Errore eseguibile\n");

        }
        else {
            printf("Sono il padre PID:%d\n",getpid());
            close(vector[0]);
            if(write(vector[1],&pid1,sizeof(pid1))<0)
                perror("Errore write pipe\n");
            else
                printf("1-Padre scrive nella pipe PID:%d\n",pid1);

            waitpid(pid1,&status1,0);
            printf("5-PID1 terminated with status %d\n",status1);
            waitpid(pid2,&status2,0);
            printf("5-PID2 terminated with status %d\n",status2);

            exit(0);
        }
    }
}

Eseguibile per inviare segnali

Eseguibile che invia un segnale di tipo SIGUSR2 a un altro processo.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc,char *argv[]) {
    // argc è il numero di parametri passati
    printf("2-Ciao sono l'eseguibile\n");
    int pid1=atoi(argv[0]);
    printf("3-Sono l'eseguibile e invio la signal: %d al PID:%d\n",SIGUSR2,pid1);

    if(kill(pid1,SIGUSR2)<0)
        perror("Errore kill:");

    exit(0);
}

Gestione di file tramite pipe e segnali

Un processo padre attiva un figlio, apre un file già esistente (vecchio.txt), legge una riga per volta (80 caratteri) e la trasferisce tramite pipe al figlio, alla fine invia una stringa "END_FILE", e invia un segnale SIGUSR1 al figlio. Il figlio crea un file nuovo.txt con i permessi r--rw-rwx, legge dalla pipe una riga per volta e la scrive sul file, stampando a video una riga per volta fin quando non riceve il segnale SIGURS1.

#include<librerie>
int aspetta=0;
void SIGURS1_handler(int);

int main() {
    int nread;
    int nread_figlio;
    int piped[2];
    pipe(piped);
    char buffer[80];
    char buffer_figlio[80];
    char my_stringa[20]="END";
    int fd1=open("vecchio.txt",O_RDONLY);
    int fd2=open("nuovo.txt",O_RDWR|0_TRUNC|O_CREAT,0467);
    int pid=fork();
    if(pid<0) {
        printf("errore fork");
    }
    else if(pid==0) { // figlio
        close(piped[1]);
        while(aspetta){
            nread_figlio=read(piped[0],buffer_figlio,80);
            write(fd2,buffer_figlio,nread_figlio);
            write(1,buffer_figlio,nread_figlio);
            bzero(buffer_figlio,80); // Ripulisco il buffer
        }
        signal(SIGURS1,SIGURS1_handler);
        exit(0);
    }
    else { // padre
        close(piped[0]);
        while(nread=read(fd1,buffer,80)>0){
            write(piped[1],buffer,nread);
            bzero(buffer,80); // Ripulisco il buffer
        }
        write(piped[1],&my_stringa,strlen(my_stringa));
        kill(pid,SIGURS1);
        exit(0);
    }
}

void SIGURS1_handler(int sig) {
    aspetta=1;
    printf("è arrivato il segnale signal\n",sig);
}

Verifica di numero pari

Programma che verifica se il numero passato come parametro è pari e gestisce processi figli.

#include<librerie>

int main(int argc,char*argv[]) {
    if(argc !=2) {
        printf("errore\n");
        exit(2);
    }

    if(N%2 ==0){
        printf("va bene, è un numero pari\n");
    }
    else {
        printf("errore, il numero è dispari, reimmettere il numero!\n");
        exit(2);
    }

    pid_t pid;
    char buffer[100];
    char Array[100];
    boolean var;
    int fd=open("figli.dat",O_CREAT|O_TRUNC|O_RDWR,0777);
    int N=atoi(argv[1]);
    
    for(int i=0;i<N;i++){
        pid=fork();
        if(pid<0) perror("errore fork\n");
        else if(pid==0) { // Codice figlio i-simo
            printf("sono il figlio con PID:%d e PPID:%d\n",getpid(),getppid());
            // Siccome i parametri del main possono essere solo stringhe converto la i da intero a stringa mettendola in un buffer
            sprintf(buffer,"%d",i);
            char*argv[]={"file",buffer,"figli.dat",(char)*0};
            execv("file",argv);
            printf("questa stampa sarà visualizzata solo in caso di errore della exec\n");
            exit(2);
        }
        else { // Codice padre
            printf("sono il padre\n");
            write(fd,&pid,sizeof(int));
            Array[i]=pid;
        }
    }

    lseek(fd,0,SEEK_SET);

    for(int i=0;i<N;i++){
        pid=Array[i]; // Leggo il pid di ogni figlio dall'array
        if (i==0) { // La prima volta solo eseguo queste istruzioni
            int n=rand()%10; // Casualment
            decido se inviare SIGURS1 o SIGURS2 al prim
        }
    }
}
Anteprima
Vedrai una selezione di 10 pagine su 107
Sistemi operativi (programmazione system call e java multithread) Pag. 1 Sistemi operativi (programmazione system call e java multithread) Pag. 2
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 6
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 11
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 16
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 21
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 26
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 31
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 36
Anteprima di 10 pagg. su 107.
Scarica il documento per vederlo tutto.
Sistemi operativi (programmazione system call e java multithread) Pag. 41
1 su 107
D/illustrazione/soddisfatti o rimborsati
Acquista con carta o PayPal
Scarica i documenti tutte le volte che vuoi
Dettagli
SSD
Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher matrix0909 di informazioni apprese con la frequenza delle lezioni di Sistemi operativi e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli studi della Campania "Luigi Vanvitelli" o del prof Aversa Rocco.
Appunti correlati Invia appunti e guadagna

Domande e risposte

Hai bisogno di aiuto?
Chiedi alla community