Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.90 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/idSEM.h>
  6. #include <sys/stat.h>
  7. #include <sys/shm.h>
  8. #include <sys/wait.h>
  9. #include <sys/msg.h>
  10. #include <sys/ipc.h>
  11. #include <sys/types.h>
  12. #include <signal.h>
  13. #include <err.h>
  14. #include <errno.h>
  15. #include <fcntl.h>
  16. #include <time.h>
  17. #include <stdint.h>
  18.  
  19.  
  20. /*
  21. Opracować zestaw programów typu producent - konsument realizujących
  22. następujący schemat synchronicznej komunikacji międzyprocesowej:
  23. • Proces 1: czyta dane ze standardowego strumienia wejściowego
  24. i przekazuje je w niezmienionej formie do procesu 2 poprzez mechanizm
  25. komunikacyjny K1.
  26. • Proces 2: pobiera dane przesłane przez proces 1. Konwertuje dane
  27. otrzymane z procesu 1 do postaci heksadecymalnej i przekazuje do procesu 3
  28. poprzez mechanizm komunikacyjny K2.
  29. • Proces 3: pobiera dane wyprodukowane przez proces 2 i wypisuje je na
  30. standardowym strumieniu diagnostycznym. Jednostki danych powinny zostać
  31. wyprowadzone po 15 w pojedynczym wierszu i oddzielone spacjami.
  32. Wszystkie trzy procesy powinny być powoływane automatycznie z jednego procesu
  33. inicjującego. Po powołaniu procesów potomnych proces inicjujący wstrzymuje pracę.
  34. Proces inicjujący wznawia pracę w momencie kończenia pracy programu (o czym
  35. niżej), jego zadaniem jest „posprzątać” po programie przed zakończeniem działania.
  36. */
  37.  
  38. #define INPUT 2048
  39. int i,j,k,p,len; //VARIABLES USER IN LOOPS ETC
  40.  
  41. //ID ARRAYS
  42. int PIDs[3]; //STORING CHILD PROCESSES' PIDS
  43. int idSEM[3]; //STORING SEMAPHORS ID
  44.  
  45. //SHMEM
  46. char *shm; //SHMEM ALLOCATED MEMORY
  47.  
  48. //DATA
  49. char data[INPUT]; //DATA
  50. char hexData[INPUT*4+1]; //HEX DATA
  51.  
  52. //FILES
  53. char sourceFileName[64]; //FILE NAME [USED IN WORK WITH FILE MODE]
  54. FILE *sourceFile; //WORK WITH FILE MODE FILE POINTER
  55. FILE *PIDsFile; //FILE WHICH CONTAINS PIDS OF CHILD PROCESSES
  56.  
  57. //FLAGS
  58. int mode; //PROGRAM'S WORK MODE FLAG
  59. int working=1; //WORK STATE FLAG
  60. int stopped=0; //STOP FLAG
  61. int synchronization=1; //PROCESSES SYNC FLAG
  62.  
  63. //---------------------QUEUE FUNCTIONS---------------------
  64. //MESSAGE STRUCT
  65. struct mymsgbuf {
  66. long type;
  67. int request;
  68. char hex[INPUT*4];
  69. }msg1;
  70. struct mymsgbuf msg2;
  71. //MSG1 - SENDING
  72. //MSG2 - RECEIVING
  73.  
  74. //OPEN QUEUE
  75. int open_queue() {
  76. key_t key = ftok(".", 'm');
  77. if((queue = msgget( key, IPC_CREAT | 0660 )) == -1)
  78. return(-1);
  79. return(queue);
  80. }
  81.  
  82. //DELETE EXISTING QUEUE
  83. int remove_queue(){
  84. if( msgctl( queue, IPC_RMID, 0) == -1)
  85. return(-1);
  86. return(0);
  87. }
  88.  
  89. //RECEIVE MESSAGE (QUEUE)
  90. int read_message( int qid, long type, struct mymsgbuf *qbuf ){
  91. int result, length;
  92. length = sizeof(struct mymsgbuf) - sizeof(long);
  93. if((result = msgrcv( qid, qbuf, length, type, 0)) == -1)
  94. return(-1);
  95. return(result);
  96. }
  97.  
  98. //SEND MESSAGE (QUEUE)
  99. int send_message( int qid, struct mymsgbuf *qbuf ){
  100. int result, length;
  101. length=sizeof(struct mymsgbuf)-sizeof(long);
  102. if((result = msgsnd( qid, qbuf, length, 0)) == -1)
  103. return(-1);
  104. return(result);
  105. }
  106.  
  107. //SENDING A MESSAGE USING QUEUE
  108. void write_queue(){
  109. msg1.type=1;
  110. msg1.request=1;
  111. strcpy(msg1.hex,hexData);
  112. if(send_message(queue,&msg1)==-1){
  113. perror("Sending...");
  114. exit(1);
  115. }
  116. }
  117. //READING A MESSAGE USING QUEUE
  118. void read_queue(){
  119. msg2.type=1;
  120. msg2.request=1;
  121. read_message(queue,msg2.type,&msg2);
  122. strcpy(hexData,msg2.hex);
  123. }
  124.  
  125. //--------------------PIDS AND PROCESS SYNC FUNCTIONS-------------------
  126. int returnNextProcess(){
  127. i=0;
  128. while(i<3){
  129. if(PIDs[i]==getPIDs() && i!=2) return i+1;
  130. i++;}
  131. return 0;
  132. }
  133.  
  134. void unlockProcess(){
  135. synchronization=1; //SETTING PROCESSES' OWN STATE TO LOCKED
  136. kill(PIDs[returnNextProcess()],SIGCONT); //AFTER RECEIVING SIGCONT SIGNAL, PROCESS SETS synchronization=0
  137. }
  138.  
  139. //RETURNS A POINTER TO SHMEM
  140. void* createSharedMemory(int command){
  141. int shmid;
  142. char *shm;
  143.  
  144. key_t key;
  145. //--------CREATING SHARED MEMORY------------
  146. if ((key = ftok(".", 'c')) == -1)
  147. errx(1, "Error creating key..."); //ERRS - DISPLAY TEXT ON STDERR
  148. if ((shmid = shmget(key, sizeof(char)*INPUT, IPC_CREAT | 0666)) < 0)
  149. errx(2, "Error creating shared memory...");
  150. if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
  151. errx(3, "Error allocating the shared memory...");
  152. if(command){ //COMMAND!=0 -> SHMEM IS DELETED
  153. shmdt(shm);
  154. shmctl(shmid, IPC_RMID, NULL);
  155. return 0;
  156. }
  157. return (void*)shm;
  158. }
  159.  
  160. //EXPORTING PIDS TO "PIDs.txt" FILE
  161. void exportPIDs(){
  162. if(PIDsFile = fopen("PIDs.txt","w")){
  163. for(i=0;i<3;i++) fprintf(PIDsFile,"%d ",PIDs[i]);
  164. fclose(PIDsFile);
  165. }else fprintf(stderr,"\nError creating the PIDs file...\n");
  166. unlockProcess();
  167. }
  168.  
  169. //READ PIDs FROM A FILE, SAVE THEM TO PIDs[] ARRAY
  170. void getPIDs(int first,int second){
  171. while(synchronization){;}
  172. if(PIDsFile = fopen("PIDs.txt","r")){
  173. for(i=0;i<3;i++) fscanf(PIDsFile,"%d",&PIDs[i]);
  174. fclose(PIDsFile);
  175. }else fprintf(stderr,"\nError opening PIDs.txt file...\n");
  176. unlockProcess();
  177. }
  178.  
  179. //CLEANER
  180. void cleanUp(){
  181. createSharedMemory(1); //DELETE SHMEM
  182. remove_queue(); //REMOVE QUEUE
  183. system("rm PIDs.txt"); //DELETE PIDs FILE
  184. kill(getPIDs(),SIGKILL); //EXECUTE PARENT PROCESS
  185. }
  186.  
  187. //MAIN PROCESS SIGNALS HANDLER
  188. void mainHandler(int signal){
  189. switch(signal){
  190. case SIGINT: //SIGINT - END WORK
  191. fprintf(stderr,"\nParent process: PID[%d], Exiting...\n", getPIDs());
  192. for(i=0;i<=2;i++) kill(PIDs[i],SIGKILL); //SIGKILL - SHUT DOWN PROCESS
  193. working=0;
  194. break;
  195. case SIGUSR1: //SIGUSR1 (10) - STOP A PROCESS
  196. if(!stopped){
  197. stopped=1;
  198. for(i=0;i<=2;i++) kill(PIDs[i],signal);
  199. fprintf(stderr,"Stopping the work...\n");
  200. }
  201. break;
  202. case SIGUSR2: //SIGUSR2 - RETURNING TO WORK
  203. if(stopped){
  204. fprintf(stderr,"Returning to work...\n");
  205. stopped=0;
  206. for(i=0;i<=2;i++) kill(PIDs[i],signal);
  207. }
  208. break;
  209. default:
  210. break;
  211. }
  212. }
  213.  
  214. //CHILD PROCESSES SIGNALS HANDLER
  215. void childHandler(int signal){
  216. if(signal==SIGCONT) synchronization=0; //SYNCHRINIZATION OF READING
  217. else kill(getpPIDs(),signal);
  218.  
  219. if(signal==SIGUSR1) working=0; //STOP FLAG
  220. if(signal==SIGUSR2){
  221. if (!working) sleep(1);
  222. working=1; //RETURN TO WORK FLAG
  223. }
  224. }
  225.  
  226. //CONVERT TO A HEX STRING AND SAVE OUTPUT TO hexData
  227. void stringToHexString(char *input){
  228. i=0, j=0, len=0;
  229. uint8_t *temp = (uint8_t*)input;
  230. for(i = 0; i <strlen(temp); i++) {
  231. sprintf((char*)(hexData+j),"%02X", 0xFF & temp[i]);
  232. j+=2;
  233. }
  234. hexData[j+1] = '\0';
  235. }
  236.  
  237. void printHexData(){
  238. for(p=0;p<strlen(hexData);p+=2){
  239. if(k%15==0) {fprintf(stderr,"\n"); k=0;}
  240. fprintf(stderr,"%c%c ",hexData[p],hexData[p+1]);
  241. k++;
  242. }
  243. }
  244.  
  245.  
  246. void p1(){
  247. getPIDs(1,2); //READING PIDS FROM THE PIDs.txt FILE
  248. sleep(1);
  249. while (1) {
  250. while(synchronization){;}
  251. while(!working){;} //CAN BE PAUSED BY SENDING SIGUSR1 SIGNAL
  252. readData();
  253. }
  254. }
  255.  
  256. void p2(){
  257. getPIDs(2,3); //READING PIDS FROM THE PIDs.txt FILE
  258. while (1) {
  259. while(synchronization){;}
  260. strcpy(data,shm);
  261. stringToHexString(data); //CONVERTING TO HEX DATA, SAVING TO hexData
  262. while(!working){;} //CAN BE PAUSED BY SENDING SIGUSR1 SIGNAL
  263.  
  264. //fprintf(stderr,"[P2:%d] data: %s\n",getpid(),data);
  265. write_queue();
  266. unlockProcess();
  267. }
  268. }
  269.  
  270. void p3(){
  271. getPIDs(3,1); //READING PIDS FROM THE PIDs.txt FILE
  272. kill(PIDs[0],SIGCONT); //SENDING INFORMATION TO PROCESS 1 THAT PROCESS 3 CAN START THE WORK
  273. while (1) {
  274. while(synchronization){;}
  275. //fprintf(stderr,"Process 3 PID[%d] hexdata: \n",getpid());
  276. while(!working){;}
  277. read_queue();
  278. printHexData(); //PRINTING HEX DATA
  279. unlockProcess();
  280. }
  281. }
  282.  
  283. void createProcesses(){
  284. for (i=0;i<=2;i++){
  285. if((PIDs[i]=fork())==0){ //CREATING CHILD PROCESSES
  286.  
  287. fprintf(stderr,"Process %d PID[%d] PPID[%d]\n", i+1, getpid(), getppid());
  288. //MAKING SURE CHILD PROCESSES CAN HANDLE ALL SIGNALS
  289. for(k =1; k<=64; k++) signal(k,childHandler);
  290.  
  291.  
  292. switch (i){
  293. case 0: p1(); break;
  294. case 1: p2(); break;
  295. case 2: p3(); break;
  296. default: fprintf(stderr,"Error creating processes...");
  297. }
  298. }
  299. }
  300. }
  301.  
  302. int main() {
  303.  
  304. fprintf(stderr,"Parent process PID[%d] PPID[%d]\n", getPIDs(), getpPIDs());
  305. for(k =1; k<=64; k++) signal(k,mainHandler);
  306.  
  307.  
  308.  
  309. //--------Choose work mode-------------------//
  310. fprintf(stderr,"\n1. Interactive\n2. Read from a file\n3. Read from /dev/urandom\n");
  311. while((mode!='1')&&(mode!='2')&&(mode!='3')){
  312. fprintf(stderr,"Choose work mode:\n");
  313. mode=getchar();
  314. getchar();
  315. }
  316. if(mode=='2'){
  317. fprintf(stderr,"\nEnter a FULL path to a file (with file extension)\n");
  318. scanf("%s", sourceFileName);
  319. getchar();
  320. }
  321.  
  322. switch (mode){
  323. case '1': //INTERACTIVE
  324. fprintf(stderr,"\nEnter data (Full string):\n");
  325. fgets(data,INPUT,stdin);
  326. data[strlen(data)-1]='\0';
  327. strcpy(shm,data);
  328. unlockProcess(2);
  329. break;
  330. case '2': //READING FROM A FILE
  331. if(sourceFile=fopen(sourceFileName,"r")){
  332. while(fread(shm,sizeof(char),INPUT,sourceFile)){
  333. unlockProcess(2);
  334. while(synchronization){;}
  335. }
  336. fclose(sourceFile);
  337. kill(getpPIDs(),SIGINT);
  338. sleep(10);
  339. }else{
  340. fprintf(stderr,"Could not open the file...\n");
  341. kill(getpPIDs(),SIGINT);}
  342. break;
  343. case '3': //READING FROM /dev/urandom
  344. if(sourceFile = fopen("/dev/urandom", "r")){
  345. fgets(shm, INPUT, sourceFile);
  346. unlockProcess(2);
  347. fclose(sourceFile);
  348. }else{
  349. fprintf(stderr,"Could not open the file /dev/urandom\n");
  350. kill(getpPIDs(),SIGINT);}
  351. break;
  352. default:
  353. fprintf(stderr,"You entered wrong mode number... Try again:%d",mode);
  354. kill(getpPIDs(),SIGINT);
  355. }
  356.  
  357. open_queue(); //CREATING A QUEUE
  358. shm = createSharedMemory(0); //CREATING SHMEM
  359. createProcesses(); //CREATING CHILD PROCESSES
  360.  
  361. sleep(1);
  362.  
  363. exportPIDs(); //SAVING PIDS TO FILE
  364. while (working) pause(); //STOPPING PARENT PROCESS' WORK
  365.  
  366. cleanUp(); //HITMAN
  367. return 0;
  368. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement