Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/idSEM.h>
- #include <sys/stat.h>
- #include <sys/shm.h>
- #include <sys/wait.h>
- #include <sys/msg.h>
- #include <sys/ipc.h>
- #include <sys/types.h>
- #include <signal.h>
- #include <err.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <time.h>
- #include <stdint.h>
- /*
- Opracować zestaw programów typu producent - konsument realizujących
- następujący schemat synchronicznej komunikacji międzyprocesowej:
- • Proces 1: czyta dane ze standardowego strumienia wejściowego
- i przekazuje je w niezmienionej formie do procesu 2 poprzez mechanizm
- komunikacyjny K1.
- • Proces 2: pobiera dane przesłane przez proces 1. Konwertuje dane
- otrzymane z procesu 1 do postaci heksadecymalnej i przekazuje do procesu 3
- poprzez mechanizm komunikacyjny K2.
- • Proces 3: pobiera dane wyprodukowane przez proces 2 i wypisuje je na
- standardowym strumieniu diagnostycznym. Jednostki danych powinny zostać
- wyprowadzone po 15 w pojedynczym wierszu i oddzielone spacjami.
- Wszystkie trzy procesy powinny być powoływane automatycznie z jednego procesu
- inicjującego. Po powołaniu procesów potomnych proces inicjujący wstrzymuje pracę.
- Proces inicjujący wznawia pracę w momencie kończenia pracy programu (o czym
- niżej), jego zadaniem jest „posprzątać” po programie przed zakończeniem działania.
- */
- #define INPUT 2048
- int i,j,k,p,len; //VARIABLES USER IN LOOPS ETC
- //ID ARRAYS
- int PIDs[3]; //STORING CHILD PROCESSES' PIDS
- int idSEM[3]; //STORING SEMAPHORS ID
- //SHMEM
- char *shm; //SHMEM ALLOCATED MEMORY
- //DATA
- char data[INPUT]; //DATA
- char hexData[INPUT*4+1]; //HEX DATA
- //FILES
- char sourceFileName[64]; //FILE NAME [USED IN WORK WITH FILE MODE]
- FILE *sourceFile; //WORK WITH FILE MODE FILE POINTER
- FILE *PIDsFile; //FILE WHICH CONTAINS PIDS OF CHILD PROCESSES
- //FLAGS
- int mode; //PROGRAM'S WORK MODE FLAG
- int working=1; //WORK STATE FLAG
- int stopped=0; //STOP FLAG
- int synchronization=1; //PROCESSES SYNC FLAG
- //---------------------QUEUE FUNCTIONS---------------------
- //MESSAGE STRUCT
- struct mymsgbuf {
- long type;
- int request;
- char hex[INPUT*4];
- }msg1;
- struct mymsgbuf msg2;
- //MSG1 - SENDING
- //MSG2 - RECEIVING
- //OPEN QUEUE
- int open_queue() {
- key_t key = ftok(".", 'm');
- if((queue = msgget( key, IPC_CREAT | 0660 )) == -1)
- return(-1);
- return(queue);
- }
- //DELETE EXISTING QUEUE
- int remove_queue(){
- if( msgctl( queue, IPC_RMID, 0) == -1)
- return(-1);
- return(0);
- }
- //RECEIVE MESSAGE (QUEUE)
- int read_message( int qid, long type, struct mymsgbuf *qbuf ){
- int result, length;
- length = sizeof(struct mymsgbuf) - sizeof(long);
- if((result = msgrcv( qid, qbuf, length, type, 0)) == -1)
- return(-1);
- return(result);
- }
- //SEND MESSAGE (QUEUE)
- int send_message( int qid, struct mymsgbuf *qbuf ){
- int result, length;
- length=sizeof(struct mymsgbuf)-sizeof(long);
- if((result = msgsnd( qid, qbuf, length, 0)) == -1)
- return(-1);
- return(result);
- }
- //SENDING A MESSAGE USING QUEUE
- void write_queue(){
- msg1.type=1;
- msg1.request=1;
- strcpy(msg1.hex,hexData);
- if(send_message(queue,&msg1)==-1){
- perror("Sending...");
- exit(1);
- }
- }
- //READING A MESSAGE USING QUEUE
- void read_queue(){
- msg2.type=1;
- msg2.request=1;
- read_message(queue,msg2.type,&msg2);
- strcpy(hexData,msg2.hex);
- }
- //--------------------PIDS AND PROCESS SYNC FUNCTIONS-------------------
- int returnNextProcess(){
- i=0;
- while(i<3){
- if(PIDs[i]==getPIDs() && i!=2) return i+1;
- i++;}
- return 0;
- }
- void unlockProcess(){
- synchronization=1; //SETTING PROCESSES' OWN STATE TO LOCKED
- kill(PIDs[returnNextProcess()],SIGCONT); //AFTER RECEIVING SIGCONT SIGNAL, PROCESS SETS synchronization=0
- }
- //RETURNS A POINTER TO SHMEM
- void* createSharedMemory(int command){
- int shmid;
- char *shm;
- key_t key;
- //--------CREATING SHARED MEMORY------------
- if ((key = ftok(".", 'c')) == -1)
- errx(1, "Error creating key..."); //ERRS - DISPLAY TEXT ON STDERR
- if ((shmid = shmget(key, sizeof(char)*INPUT, IPC_CREAT | 0666)) < 0)
- errx(2, "Error creating shared memory...");
- if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
- errx(3, "Error allocating the shared memory...");
- if(command){ //COMMAND!=0 -> SHMEM IS DELETED
- shmdt(shm);
- shmctl(shmid, IPC_RMID, NULL);
- return 0;
- }
- return (void*)shm;
- }
- //EXPORTING PIDS TO "PIDs.txt" FILE
- void exportPIDs(){
- if(PIDsFile = fopen("PIDs.txt","w")){
- for(i=0;i<3;i++) fprintf(PIDsFile,"%d ",PIDs[i]);
- fclose(PIDsFile);
- }else fprintf(stderr,"\nError creating the PIDs file...\n");
- unlockProcess();
- }
- //READ PIDs FROM A FILE, SAVE THEM TO PIDs[] ARRAY
- void getPIDs(int first,int second){
- while(synchronization){;}
- if(PIDsFile = fopen("PIDs.txt","r")){
- for(i=0;i<3;i++) fscanf(PIDsFile,"%d",&PIDs[i]);
- fclose(PIDsFile);
- }else fprintf(stderr,"\nError opening PIDs.txt file...\n");
- unlockProcess();
- }
- //CLEANER
- void cleanUp(){
- createSharedMemory(1); //DELETE SHMEM
- remove_queue(); //REMOVE QUEUE
- system("rm PIDs.txt"); //DELETE PIDs FILE
- kill(getPIDs(),SIGKILL); //EXECUTE PARENT PROCESS
- }
- //MAIN PROCESS SIGNALS HANDLER
- void mainHandler(int signal){
- switch(signal){
- case SIGINT: //SIGINT - END WORK
- fprintf(stderr,"\nParent process: PID[%d], Exiting...\n", getPIDs());
- for(i=0;i<=2;i++) kill(PIDs[i],SIGKILL); //SIGKILL - SHUT DOWN PROCESS
- working=0;
- break;
- case SIGUSR1: //SIGUSR1 (10) - STOP A PROCESS
- if(!stopped){
- stopped=1;
- for(i=0;i<=2;i++) kill(PIDs[i],signal);
- fprintf(stderr,"Stopping the work...\n");
- }
- break;
- case SIGUSR2: //SIGUSR2 - RETURNING TO WORK
- if(stopped){
- fprintf(stderr,"Returning to work...\n");
- stopped=0;
- for(i=0;i<=2;i++) kill(PIDs[i],signal);
- }
- break;
- default:
- break;
- }
- }
- //CHILD PROCESSES SIGNALS HANDLER
- void childHandler(int signal){
- if(signal==SIGCONT) synchronization=0; //SYNCHRINIZATION OF READING
- else kill(getpPIDs(),signal);
- if(signal==SIGUSR1) working=0; //STOP FLAG
- if(signal==SIGUSR2){
- if (!working) sleep(1);
- working=1; //RETURN TO WORK FLAG
- }
- }
- //CONVERT TO A HEX STRING AND SAVE OUTPUT TO hexData
- void stringToHexString(char *input){
- i=0, j=0, len=0;
- uint8_t *temp = (uint8_t*)input;
- for(i = 0; i <strlen(temp); i++) {
- sprintf((char*)(hexData+j),"%02X", 0xFF & temp[i]);
- j+=2;
- }
- hexData[j+1] = '\0';
- }
- void printHexData(){
- for(p=0;p<strlen(hexData);p+=2){
- if(k%15==0) {fprintf(stderr,"\n"); k=0;}
- fprintf(stderr,"%c%c ",hexData[p],hexData[p+1]);
- k++;
- }
- }
- void p1(){
- getPIDs(1,2); //READING PIDS FROM THE PIDs.txt FILE
- sleep(1);
- while (1) {
- while(synchronization){;}
- while(!working){;} //CAN BE PAUSED BY SENDING SIGUSR1 SIGNAL
- readData();
- }
- }
- void p2(){
- getPIDs(2,3); //READING PIDS FROM THE PIDs.txt FILE
- while (1) {
- while(synchronization){;}
- strcpy(data,shm);
- stringToHexString(data); //CONVERTING TO HEX DATA, SAVING TO hexData
- while(!working){;} //CAN BE PAUSED BY SENDING SIGUSR1 SIGNAL
- //fprintf(stderr,"[P2:%d] data: %s\n",getpid(),data);
- write_queue();
- unlockProcess();
- }
- }
- void p3(){
- getPIDs(3,1); //READING PIDS FROM THE PIDs.txt FILE
- kill(PIDs[0],SIGCONT); //SENDING INFORMATION TO PROCESS 1 THAT PROCESS 3 CAN START THE WORK
- while (1) {
- while(synchronization){;}
- //fprintf(stderr,"Process 3 PID[%d] hexdata: \n",getpid());
- while(!working){;}
- read_queue();
- printHexData(); //PRINTING HEX DATA
- unlockProcess();
- }
- }
- void createProcesses(){
- for (i=0;i<=2;i++){
- if((PIDs[i]=fork())==0){ //CREATING CHILD PROCESSES
- fprintf(stderr,"Process %d PID[%d] PPID[%d]\n", i+1, getpid(), getppid());
- //MAKING SURE CHILD PROCESSES CAN HANDLE ALL SIGNALS
- for(k =1; k<=64; k++) signal(k,childHandler);
- switch (i){
- case 0: p1(); break;
- case 1: p2(); break;
- case 2: p3(); break;
- default: fprintf(stderr,"Error creating processes...");
- }
- }
- }
- }
- int main() {
- fprintf(stderr,"Parent process PID[%d] PPID[%d]\n", getPIDs(), getpPIDs());
- for(k =1; k<=64; k++) signal(k,mainHandler);
- //--------Choose work mode-------------------//
- fprintf(stderr,"\n1. Interactive\n2. Read from a file\n3. Read from /dev/urandom\n");
- while((mode!='1')&&(mode!='2')&&(mode!='3')){
- fprintf(stderr,"Choose work mode:\n");
- mode=getchar();
- getchar();
- }
- if(mode=='2'){
- fprintf(stderr,"\nEnter a FULL path to a file (with file extension)\n");
- scanf("%s", sourceFileName);
- getchar();
- }
- switch (mode){
- case '1': //INTERACTIVE
- fprintf(stderr,"\nEnter data (Full string):\n");
- fgets(data,INPUT,stdin);
- data[strlen(data)-1]='\0';
- strcpy(shm,data);
- unlockProcess(2);
- break;
- case '2': //READING FROM A FILE
- if(sourceFile=fopen(sourceFileName,"r")){
- while(fread(shm,sizeof(char),INPUT,sourceFile)){
- unlockProcess(2);
- while(synchronization){;}
- }
- fclose(sourceFile);
- kill(getpPIDs(),SIGINT);
- sleep(10);
- }else{
- fprintf(stderr,"Could not open the file...\n");
- kill(getpPIDs(),SIGINT);}
- break;
- case '3': //READING FROM /dev/urandom
- if(sourceFile = fopen("/dev/urandom", "r")){
- fgets(shm, INPUT, sourceFile);
- unlockProcess(2);
- fclose(sourceFile);
- }else{
- fprintf(stderr,"Could not open the file /dev/urandom\n");
- kill(getpPIDs(),SIGINT);}
- break;
- default:
- fprintf(stderr,"You entered wrong mode number... Try again:%d",mode);
- kill(getpPIDs(),SIGINT);
- }
- open_queue(); //CREATING A QUEUE
- shm = createSharedMemory(0); //CREATING SHMEM
- createProcesses(); //CREATING CHILD PROCESSES
- sleep(1);
- exportPIDs(); //SAVING PIDS TO FILE
- while (working) pause(); //STOPPING PARENT PROCESS' WORK
- cleanUp(); //HITMAN
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement