codice:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <math.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
#define MSGKEY 88 //chiave per la coda dei messaggi del processo padre
#define MSGTYPE 1 //tipo per messaggio da ricevere
#define SEMKEY 89
int semid; //identificatore dell'array di semafori
int msgid; //identificatore della coda dei messaggi del processo padre
struct operation{
char type;
int i;
int j;
};
struct Processo{
int n_processo;
pid_t my_pid;
};
void mywrite(char *string);
int main(int argc, char *argv[]){
if(argc != 6){
mywrite("ERRORE: Corretta esecuzione: ./ipc.x matA.txt matB.txt matC.txt <ordine-mat> <num-processi>\n");
exit(1);
}
int N = atoi(argv[4]);
int numP = atoi(argv[5]); //numero processi
int fdA, fdB, fdC;
//indici per i cicli
int i, j, k, w;
if((fdA = open(argv[1], O_RDONLY, 644)) == -1){
mywrite("ERRORE apertura argv[1]\n");
exit(1);
}
if((fdB = open(argv[2], O_RDONLY, 644)) == -1){
mywrite("ERRORE apertura argv[2]\n");
exit(1);
}
if((fdC = open(argv[3], O_RDWR, 666)) == -1){
mywrite("ERRORE apertura argv[3]\n");
exit(1);
}
//da qua provo soluzione bomber
char *test;
char testo[N];
int dimensione=1000; //grandezza arbitraria abbastanza grande
read(fdA, testo, dimensione);
int num;
test = strtok (testo,"\n");
int **matA = (int**) malloc(N * sizeof(int*));
for(i=0; i<N; i++){
matA[i] = (int*)malloc(N * sizeof(int));
}
for(i=0; i<N; i++){
for(j=0; j<N; j++){
num=atoi(test); // converto da ascii a numero intero
matA[i][j] = num;
test= strtok (NULL,"\n");
}
}
key_t keyA=123;
int id_mA;
if ((id_mA = shmget(keyA,sizeof(matA) , IPC_CREAT|0666)) == -1) {
mywrite("Errore memoria condivisa matA");
shmctl(id_mA, IPC_RMID, NULL);
exit(1);
}
matA=shmat(id_mA, NULL, 0);
char testoB[N];
int dimensioneB=1000; //grandezza arbitraria abbastanza grande
read(fdB, testoB, dimensioneB);
test = strtok (testoB,"\n");
int **matB = (int**) malloc(N * sizeof(int*));
for(i=0; i<N; i++){
matB[i] = (int*)malloc(N * sizeof(int));
}
for(i=0; i<N; i++){
for(j=0; j<N; j++){
num=atoi(test); // converto da ascii a numero intero
matB[i][j] = num;
test= strtok (NULL,"\n");
}
}
key_t keyB=456;
int id_mB;
if ((id_mB = shmget(keyB,sizeof(matB) , IPC_CREAT|0666)) == -1) {
mywrite("Errore memoria condivisa matB");
shmctl(id_mB, IPC_RMID, NULL);
exit(1);
}
matB=shmat(id_mB, NULL, 0);
int **matC = (int**) malloc(N * sizeof(int*));
for(i=0; i<N; i++){
matC[i] = (int*)malloc(N * sizeof(int));
}
for(i=0; i<N; i++){
for(j=0; j<N; j++){
matC[i][j] = 0;
}
}
key_t keyC=789;
int id_mC;
if ((id_mC = shmget(keyC,sizeof(matC) , IPC_CREAT|0666)) == -1) {
mywrite("Errore memoria condivisa matC");
shmctl(id_mC, IPC_RMID, NULL);
exit(1);
}
matC=shmat(id_mC, NULL, 0);
//risultato somma elementi di C
int *somma=(int*) malloc(sizeof(int*));
key_t keyN=111;
int id_N;
if ((id_N = shmget(keyN,sizeof(int),IPC_CREAT|0666)) == -1) {
mywrite("Errore memoria condivisa somma");
shmctl(id_N, IPC_RMID, NULL);
exit(1);
}
somma= shmat(id_N, NULL, 0);
struct sembuf * sops = (struct sembuf *) malloc (2*sizeof(struct sembuf));
//Creazione di un array di numP semafori
//Il semaforo 0 sincronizza il processo 1, sem 1 sincronizza processo 2 e cosi via..
key_t keysem=ftok(".", 'a');
if((semid = semget(SEMKEY, numP ,0666|IPC_EXCL|IPC_CREAT)) == -1){
mywrite("ERRORE creazione array di semafori");
semctl(semid, 0, IPC_RMID, 0);
exit(1);
}
//inizializzo i semafori e li metto in attesa
for(i=0; i<numP ; i++){
sops[0].sem_num = i;
sops[0].sem_op = 1; //attende che valga 0 per avere il via libera
sops[0].sem_flg = 0;
semop(semid, sops, 1);
}
//array di strutture che mi andrà a collegare ogni processo col proprio pid
struct Processo processi[numP];
int fdFtoC[2];
pipe(fdFtoC);
pid_t pid_padre=getpid();
if((msgid = msgget(MSGKEY, (0666|IPC_CREAT|IPC_EXCL))) == -1) {
mywrite("Creazione della coda di messaggi fallita");
exit(1);
}
//creo i processi e li salvo nell'array processi
int num_processo;
pid_t pid;
for(num_processo=0; num_processo<numP; num_processo++){
pid=fork();
if (pid == -1){
mywrite("ERRORE fork");
exit(1);
}
else if (pid == 0){ //figlio i
close(fdFtoC[1]); //chiudo l'output, il figlio legge e basta
processi[num_processo].n_processo= num_processo;
processi[num_processo].my_pid=getpid();
struct Processo mex= { num_processo, processi[num_processo].my_pid};
if(msgsnd(msgid, &mex, sizeof(struct Processo), 0) == -1){ //Sono stato creato, sono libero
mywrite("ERRORE invio messaggio al padre");
exit(1);
}
}else{ //padre
close(fdFtoC[0]); //chiudo l'input, il padre scrive e basta
}
}
int continuo=1;
while(continuo){
if(getpid()==pid_padre){ //codice del padre
for(i=0;i<N;i++){
for(j=0; j<N ;j++){
struct Processo *mex;
mex = (struct Processo *) malloc(sizeof(struct Processo));
if(msgrcv(msgid, mex, sizeof(struct Processo), MSGTYPE, 0) == -1){
mywrite("ERRORE ricezione messaggio dalla coda");
exit(1);
}
struct operation next; next.i=i; next.j=j; next.type='M';
sops[0].sem_num = mex->n_processo;
sops[0].sem_op = -1; //sblocco il semaforo a cui mando l'operazione
sops[0].sem_flg = 0;
semop(semid, sops, 1);
//padre scrive su pipe al figlio la prossima operazione
if(write(fdFtoC[1], &next, sizeof(struct operation)) == -1){
mywrite("ERRORE scrittura su pipe");
exit(1);
}
free(mex);
}
struct Processo *mex;
mex = (struct Processo *) malloc(sizeof(struct Processo));
if(msgrcv(msgid, mex, sizeof(struct Processo), MSGTYPE, 0) == -1){
mywrite("ERRORE ricezione messaggio dalla coda");
exit(1);
}
struct operation next; next.i=i; next.type='S';
sops[0].sem_num = mex->n_processo;
sops[0].sem_op = -1; //sblocco il semaforo a cui mando l'operazione
sops[0].sem_flg = 0;
semop(semid, sops, 1);
if(write(fdFtoC[1], &next, sizeof(struct operation)) == -1){
mywrite("ERRORE scrittura su pipe");
exit(1);
}
free(mex);
}
}else{ //codice figlio
for(i=0; i<numP ; i++){
if(getpid()==processi[i].my_pid){
sops[0].sem_num = i; //Semaforo numero i
sops[0].sem_op = 0; //attende che il semaforo valga zero
sops[0].sem_flg = 0;
sops[1].sem_num = i; //semaforo i
sops[1].sem_op = 1; //acquisisce la risorsa
sops[1].sem_flg = 0;
semop(semid, sops, 2);
char temp[100];
sprintf(temp, "Processo: %d\t\tpid:%d\n\t\tHo acquisito la risorsa, svolgo l'operazione\n\n", i+1, processi[i].my_pid);
mywrite(temp);
//figlio legge da pipe l'operazione che dovrà svolgere
struct operation *next;
next = (struct operation *) malloc(sizeof(struct operation));
if(read(fdFtoC[0], &next, sizeof(struct operation)) == -1){
mywrite("ERRORE lettura da pipe");
exit(1);
}
if(next->type=='M')
for(k=0 ; k<N ; k++)
matC[next->i][next->j] += matA[next->i][k] * matB[k][next->j];
if(next->type=='S')
for(w=0; w<N ; w++)
somma+=matC[next->i][w];
sprintf(temp, "Processo: %d\t\tpid:%d\n\t\tHo svolto l'operazione, lo comunico al padre\n\n", i+1, processi[i].my_pid);
mywrite(temp);
struct Processo mex= { i, processi[i].my_pid};
if(msgsnd(msgid, &mex, sizeof(struct Processo), 0) == -1){ //ho svolto l'operazione
mywrite("ERRORE invio messaggio al padre");
exit(1);
}
free(next);
}
}
}
continuo=0;
}
//stampo la matrice C su file
char porzione[32];
for (i = 0 ; i < N ; i++){
for (j = 0 ; j < N ; j++){
lseek(fdC, 0, SEEK_END);
sprintf(porzione, "%d\t", matC[i][j]);
write(fdC, porzione, sizeof(porzione));
}
lseek(fdC, 0, SEEK_END);
sprintf(porzione, "\n");
write(fdC, porzione, sizeof(porzione));
}
sprintf(porzione, "La somma degli elementi della matrice C é: %d\n", *somma);
mywrite(porzione);
for(i=0; i<N; i++){
free(matA[i]);
}
free(matA);
for(i=0; i<N; i++){
free(matC[i]);
}
free(matC);
for(i=0; i<N; i++){
free(matC[i]);
}
free(matC);
shmctl(id_N, IPC_RMID, NULL);
free(somma);
//rimuovo i semafori
semctl(semid, 0, IPC_RMID, 0);
//rimuovo la coda di messaggi
msgctl(msgid, IPC_RMID, NULL);
shmctl(id_mA, IPC_RMID, NULL);
shmctl(id_mB, IPC_RMID, NULL);
shmctl(id_mC, IPC_RMID, NULL);
}
void mywrite(char *string){
write(1, string, strlen(string));
}