본문 바로가기

리눅스 프로그래밍

[운영체제] 세마포어를 사용해 프로세스통신 구현해보기_Server방식

// 클라이언트에서 정렬하는 클라이언트 오리엔티드 방식과 다르게 서버의 어디로 갈지 미리 정하고 통신하는 방법

// server.c

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <errno.h>

#include <sys/time.h>


#define fifoSize 1024

#define serverSize 32768

#define clientSize 8192


union semun{

        int val;

        struct  semid_ds *buf;

        unsigned short *array;

};


int initsem(key_t semkey){

        union semun semunarg;

        int status =0, semid;


        semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0644);

        if(semid == -1){

                if(errno == EEXIST){

                        semid = semget(semkey, 1, 0);

                }

        }

        else{

                semunarg.val = 1;

                status =  semctl(semid, 0, SETVAL, semunarg);

        }


        if(semid == -1 || status == -1){

                perror("initsem");

                return(-1);

        }


        return semid;

}

int semlock(int semid){

        struct sembuf buf;


        buf.sem_num = 0;

        buf.sem_op = -1;

        buf.sem_flg = SEM_UNDO;

        if(semop(semid, &buf, 1) == -1){

                perror("semlock failed");

                exit(1);

        }

        return 0;

}


int semunlock(int semid){

        struct sembuf buf;


        buf.sem_num = 0;

        buf.sem_op = 1;

        buf.sem_flg = SEM_UNDO;

        if(semop(semid, &buf, 1) == -1){

                perror("semunlock failed");

                exit(1);

        }

        return 0;

}


void sort(int *buf, int bufoff){

        int i,j,temp;

        for(i=0; i<bufoff; i++){

                for(j=0; j<bufoff; j++){

                        if(buf[i] <= buf[j]){

                                temp = buf[i];

                                buf[i] = buf[j];

                                buf[j] = temp;

                        }

                }

        }

}

int main(void) {

        int pd[8], n, i, j, l, k, bufoff=0;

        int buf[serverSize];

        int rbuf[fifoSize];

        char computeFifo[20] = "./computeNode";

        pid_t pid;

        struct timeval start, end, total, gap;


        memset(&start, 0, sizeof(start));

        memset(&end, 0, sizeof(end));

        memset(&gap, 0, sizeof(gap));

        memset(&total, 0, sizeof(total));


        int fd;


        for(i=0; i<8; i++){

                computeFifo[13] = '1'+i;

                if (mkfifo(computeFifo, 0666) == -1){

                    perror("mkfifo");

                    exit(1);

                 }

        }


        for(i=0; i<8; i++){

                computeFifo[13] = '1'+i;

                if ((pd[i] = open(computeFifo, O_RDONLY)) == -1){

                    perror("open");

                    exit(1);

                }

        }



        off_t off;

        if((pid = fork())==0){

                int semid;

                if((semid = initsem(1)) < 0) exit(1);


                if((fd = open("serverDataChild.dat", O_CREAT | O_WRONLY | O_TRUNC ,0600)) == -1){

                        perror("fopen");

                        exit(1);

                }

                //gettimeofday(&start, NULL);

                for(i=0; i<8; i++){

                        while(1){

                                semlock(semid);

                                gettimeofday(&start, NULL);

                                if((n=read(pd[i],rbuf,sizeof(int)*fifoSize))>0){

                                        gettimeofday(&end, NULL);

                                        gap.tv_usec = end.tv_usec - start.tv_usec;

                                        gap.tv_sec = end.tv_sec - start.tv_sec;

                                        total.tv_sec += gap.tv_sec;

                                        if(gap.tv_usec>0){

                                                total.tv_usec += gap.tv_usec;

                                        }


                                        //printf("communication time : %ld %ld\n", gap.tv_sec, gap.tv_usec);


                                        memset(&start, 0 ,sizeof(start));

                                        memset(&end, 0, sizeof(end));

                                        memset(&gap, 0, sizeof(gap));


                                        //printf("communication time : %ld %ld\n", total.tv_sec, total.tv_usec);

                                        for(j=0; j<(n/4); j++){

                                                buf[bufoff] = rbuf[j];

                                                bufoff++;

                                        }

                                        //printf("child unlock\n");

                                        semunlock(semid);

                                }

                                else {

                                        //printf("child unlock\n");

                                        semunlock(semid);

                                        break;

                                }

                        }

                }

                //printf("communication time : %ld %ld\n", total.tv_sec, total.tv_usec);

                /*gettimeofday(&end, NULL);

                gap.tv_usec = end.tv_usec - start.tv_usec;

                gap.tv_sec = end.tv_sec - start.tv_sec;

                printf("communication time : %ld %ld\n", gap.tv_sec, gap.tv_usec);

                total.tv_sec += gap.tv_sec;

                if(gap.tv_usec < 0){

                        total.tv_usec += gap.tv_usec;

                }*/

                printf("communication time : %ld %ld\n", total.tv_sec, total.tv_usec);

                printf("Child Server:");


                memset(&start, 0 ,sizeof(start));

                memset(&end, 0, sizeof(end));

                memset(&gap, 0, sizeof(gap));


                semlock(semid);


                //gettimeofday(&start,NULL);

                sort(buf, bufoff);

                //gettimeofday(&end, NULL);


                //gap.tv_usec = end.tv_usec - start.tv_usec;

                //gap.tv_sec = end.tv_sec - start.tv_sec;

                printf("sort time : %ld %ld\n", gap.tv_sec, gap.tv_usec);

                //total.tv_sec += gap.tv_sec;

                //if(gap.tv_usec < 0){

                //        total.tv_usec += gap.tv_usec;

                //}

                memset(&start, 0 ,sizeof(start));

                memset(&end, 0, sizeof(end));

                memset(&gap, 0, sizeof(gap));


                gettimeofday(&start,NULL);

                write(fd,buf,sizeof(buf));

                gettimeofday(&end, NULL);


                gap.tv_usec = end.tv_usec - start.tv_usec;

                gap.tv_sec = end.tv_sec - start.tv_sec;

                printf("write time : %ld %ld\n",gap.tv_sec, gap.tv_usec);

                total.tv_sec += gap.tv_sec;

                if(gap.tv_usec < 0){

                        total.tv_usec += gap.tv_usec;

                }


                printf("total time : %ld초 %ldus\n", total.tv_sec, total.tv_usec);


                printf("sizeof server:%d\n", bufoff);

                semunlock(semid);

                exit(1);

        }

        else if(pid ==-1){ perror("fork");exit(1);}

        else{

                int semid;

                if((semid = initsem(1)) < 0) exit(1);


                if((fd = open("serverDataParent.dat", O_CREAT | O_WRONLY | O_TRUNC, 0600)) == -1){

                        perror("fopen");

                        exit(1);

                }

                for(i=0; i<8; i++){

                        while(1){

                                semlock(semid);

                                //printf("parent lock\n");

                                if((n=read(pd[i],rbuf,sizeof(int)*fifoSize))>0){

                                        for(j=0; j<(n/4); j++){

                                                buf[bufoff] = rbuf[j];

                                                bufoff++;

                                        }

                                        //printf("parent unlock\n");

                                        semunlock(semid);

                                }

                                else{

                                        //printf("parent unlock\n");

                                        semunlock(semid);

                                        break;

                                }

                        }

                }

                semlock(semid);

                printf("Parent Server: ");

                sort(buf,bufoff);


               // for(i=0;i<bufoff;i++){

                write(fd,buf,sizeof(buf));

                    //    printf("%d ",buf[i]);

                //}

                //printf("\n");

                printf("sizeof server: %d\n", bufoff);


                semunlock(semid);

        }

        for(i=0; i<8; i++){

                close(pd[i]);

        }

        close(fd);


        return 0;

}


// client.c

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>


#define fifoSize 1024

#define datablockNum 8


void sort(int* buf, int size){

        int i,j, temp;

        for(i=0; i<size; i++){

                for(j=0; j<size; j++){

                        if(buf[i] < buf[j]){

                                temp = buf[i];

                                buf[i] = buf[j];

                                buf[j] = temp;

                        }

                }

        }

}

int main(void) {

        int pd[8], n, i,j,l,k, value_s=0,value_c=0, bufoff=0;

        int buf[8][fifoSize*datablockNum];

        char computeNode[20] = "./computeNode";


        int fd;


        char clientData[8][12] = {

                "client0.dat",

                "client1.dat",

                "client2.dat",

                "client3.dat",

                "client4.dat",

                "client5.dat",

                "client6.dat",

                "client7.dat"

        };

        for(i=0; i<8; i++){

                computeNode[13] = '1'+i;

                if ((pd[i] = open(computeNode, O_WRONLY)) == -1){

                        perror("open");

                        exit(1);

                }

        }

        for(i=0; i<8; i++){

                value_s = i;

                value_c = value_s+fifoSize;

                bufoff=0;

                for(l=0; l<datablockNum/2; l++){

                        for(j=0; j<fifoSize; j++){

                                buf[i][bufoff] = value_s;

                                bufoff++;

                                value_s += 8;

                                if((value_s-i)%1024 == 0 && (value_s-i) >= 1024 ){

                                        value_s += 1024;

                                }

                        }

                        for(j=0; j<fifoSize; j++){

                                buf[i][bufoff] = value_c;

                                value_c += 8;

                                bufoff++;

                                if((value_c-i)%1024 == 0){

                                        value_c += 1024;

                                }

                        }

                }

        }

        for(i=0; i<8; i++){

                if(fork() == 0){

                        if((fd = open(clientData[i], O_CREAT | O_WRONLY | O_TRUNC, 0600)) == -1){

                                perror("fopen");

                                exit(1);

                        }


                        if(write(pd[i], buf[i], sizeof(buf[i]))==-1){

                                perror("write error");

                        }


                        sort(buf[i], sizeof(buf[i])/4);


                        if(write(fd,buf[i],sizeof(buf[i]))==-1){

                                perror("file write error");

                        }


                        printf("Client Process %d success\n", (int)getpid());

                        exit(1);

                }

                else wait(NULL);

        }

        for(i=0; i<8; i++){

                close(pd[i]);

        }

        close(fd);

        return 0;

}