Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
5.3 kB
4
Indexable
Never
/******************************************************************
Welcome to the Operating System examination

You are editing the '/home/esame/prog.c' file. You cannot remove 
this file, just edit it so as to produce your own program according to
the specification listed below.

In the '/home/esame/'directory you can find a Makefile that you can 
use to compile this program to generate an executable named 'prog' 
in the same directory. Typing 'make posix' you will compile for 
Posix, while typing 'make winapi' you will compile for WinAPI just 
depending on the specific technology you selected to implement the
given specification. Most of the required header files (for either 
Posix or WinAPI compilation) are already included in the head of the
prog.c file you are editing. 

At the end of the examination, the last saved snapshot of this file
will be automatically stored by the system and will be then considered
for the evaluation of your exam. Modifications made to prog.c which are
not saved by you via the editor will not appear in the stored version
of the prog.c file. 
In other words, unsaved changes will not be tracked, so please save 
this file when you think you have finished software development.
You can also modify the Makefile if requesed, since this file will also
be automatically stored together with your program and will be part
of the final data to be evaluated for your exam.

PLEASE BE CAREFUL THAT THE LAST SAVED VERSION OF THE prog.c FILE (and of
the Makfile) WILL BE AUTOMATICALLY STORED WHEN YOU CLOSE YOUR EXAMINATION 
VIA THE CLOSURE CODE YOU RECEIVED, OR WHEN THE TIME YOU HAVE BEEN GRANTED
TO DEVELOP YOUR PROGRAM EXPIRES. 


SPECIFICATION TO BE IMPLEMENTED:
Implementare una programma che riceva in input, tramite argv[], i nomi
di N differenti file F1 ... FN, con N maggiore o uguale a 1, che dovranno essere creati
o troncati se gia' esistenti.
Per ognuno dei file dovra' essere attivato un nuovo processo che ne gestira' il contenuto 
(indichiamo quindi con P1 ... PN i processi che dovranno essere attivati).
Ciascun processo Pi leggera' dallo standard input 5 caratteri per volta in modo atomico
rispetto alle attivita' degli altri processi, e dovra' scriverli sul file che sta gestendo.
Anche la scrittura dei 5 caratteri sul file destinazione deve risultare come un'azione atomica,
ovvero i caratteri non possono essere scritti sui file individualmente.

L'applicazione dovra' gestire il segnale SIGINT (o CTRL_C_EVENT nel caso
WinAPI) in modo tale che quando il processo originale venga colpito esso dovra' 
riportare su standard output i 5 ultimi caratteri correntemente presenti 
su ciascuno degli N file gestiti. Tutti gli altri processi non dovranno 
eseguire alcuna attivita' in caso di arrivo di segnalazione.

In caso non vi sia immissione di dati sullo standard input, e non vi siano segnalazioni,
l'applicazione dovra' utilizzare non piu' del 5% della capacita' di lavoro della CPU.

*****************************************************************/
#ifdef Posix_compile
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <fcntl.h>
#else
#include <windows.h>
#endif

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

int N;
char** file_names;
int pid;
int parent_pid;
void func_child(int fd);
int sem_id; //id del semaforo accessibile a tutti i figli
int* array_fd;
void func_signal();

int main(int argc, char** argv) {
	N = argc-1;
	if(N == 0) {
		printf("errore argomenti\n");
		exit(-1);
	}
	file_names = malloc(sizeof(char*)*N);
	for(size_t i=0; i<N; i++){
		file_names[i] = argv[i+1];
	}
	sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT|0664);
	if(sem_id == -1) {
		printf("errore creazione semaforo\n");
		exit(-1);
	}
	int semctl_return = semctl(sem_id, 0, SETVAL, 1); //0 è il numero di semaforo, che e' solo uno. SETVAL indica quale operazione voglio fare: imposta il token.
        // 1 è il token che imposto all'inizio.
	if(semctl_return == -1) {
		printf("errore impostazione semaforo\n");
		exit(-1);
	}
	array_fd = malloc(sizeof(int)*N);
	for(size_t i=0; i<N; i++) {
		array_fd[i] = creat(file_names[i], 0664);
		pid = fork();
		if(pid == -1) {
			printf("errore creazione processo\n");
			exit(-1);
		}else if(pid == 0) {
			func_child(array_fd[i]);
		}else{
			parent_pid = getpid();
			signal(SIGINT, func_signal);
		}
	}
}

void func_child(int fd){
	char buffer[6];
	struct sembuf so;
	while(1){ 
		so.sem_num = 0; //wait
		so.sem_op = -1;
		so.sem_flg = 0;
		int semop_check = semop(sem_id, &so, 1); //ho una sola operazione
		if(semop_check == -1) {
			printf("errore operazione semaforo\n");
			exit(-1);
		}
		read(STDIN_FILENO, buffer, 5);
		write(fd, buffer, 5); 
                so.sem_num = 0; //signal
                so.sem_op = 1; 
                so.sem_flg = 0;
                semop_check = semop(sem_id, &so, 1); 
		if(semop_check == -1) {
                        printf("errore operazione semaforo\n");
                        exit(-1);
                }

	}
}


void func_signal() {
	char buffer[6];
	for(size_t i=0; i<N; i++){
		read(array_fd[i], buffer, 5);
		write(STDOUT_FILENO, buffer, 5);
	}
}
Leave a Comment