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
}
}
}
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
-
Sistemi operativi - teoria completa
-
Sistemi operativi - Thread nei sistemi operativi
-
Sistemi operativi
-
Sistemi operativi - Syscall fork