Thread: Passing a struct with 2 dynamic arrays through a pipe and reading it's data

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    3

    Passing a struct with 2 dynamic arrays through a pipe and reading it's data

    Hello all! I have a homework for uni. My homework is to make project using fork and using the method of pipelining to passing data through child and father processess. Well we need to creat two pipes. 1st pipe send a txt file that you will write in there the result of "Ps -A" and 2nd pipe will return the pids and their priorities. The proffessor said we should use dynamic arrays and through a structure we should pass the array of pids and the array of ppids back to child.Child prints both arrays on screen. The problem i have is child fills the arrays all good here but when i send them to the father, father doesn't simply read the arrays from struct and doesn't print anything on screen can you help me with this?

    Code:
    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<string.h>
    #include <sys/resource.h>
    #define buff 256
    
    	
    	 struct dyna
     	{
     	int *pids;
      	int *ppids;
     	};
    
    	int main(int argc, char *argv[]){
    	int child_id;
    	int pipe_pc[2],pipe_cp[2];
    	int result_pc,result_cp;
    	int lines1,i;
    	if (argc!=2)//elegxos gia to an ta arguments pou edwse o xristis einai arxeio1 arxeio2
    	{
    		  fprintf(stderr,"Lathos arithmos orismaton.To swsto einai %s filename.txt\n",argv[0]);
    		  exit(1);
    	}
    	else {
    		result_pc=pipe(pipe_pc);
    		if (result_pc==-1) exit(-1);
    		result_cp=pipe(pipe_cp);
    		if (result_cp==-1) exit(-1);
    
    		struct dyna dyn;		
    	
    		child_id=fork();
    		if (child_id==-1) exit(-1);
    		//child
    		if (child_id==0){
       	 	char child_read_msg[buff];
        		close(pipe_pc[1]);
    		memset(child_read_msg,0,buff);
        		read(pipe_pc[0],child_read_msg, buff);
        		printf("\nchild process:child read from father: %s\n",child_read_msg);
        		char child_write_msg[buff]="lol",lines[buff]="lines.txt",* pch,**grammes;
    		FILE *pFile1,*pFile2;
    		long lSize1,lSize2;
    		char *buffer1,*command,*buffer2;
    		size_t file1str,file2str;
    	
    		command = (char*)malloc(strlen("wc -l >")+strlen(child_read_msg)+strlen(lines));
    		sprintf(command,"ps -A> %s",child_read_msg);
    		system(command);
    	
    			//vazoume ta periexomena tou processes.txt se enan buffer
    			pFile1 = fopen ( child_read_msg, "rb" ); 
    			fseek (pFile1, 0 , SEEK_END);
     			 lSize1 = ftell (pFile1);
      			rewind (pFile1);
    			buffer1 = (char*) malloc (sizeof(char)*lSize1);
      			if (buffer1 == NULL) {fputs ("Memory error",stderr); }
      			file1str = fread (buffer1,1,lSize1,pFile1);
      			if (file1str != lSize1) {fputs ("Reading error",stderr); }
    			fclose(pFile1);
    
    
    			//vriskoume ton arithmon grammon tou arxeiou
    			sprintf(command,"wc -l %s>%s",child_read_msg,lines);
    			system(command);
    			pFile2 = fopen ( lines, "rb" ); 
    			fseek (pFile2, 0 , SEEK_END);
     			 lSize2 = ftell (pFile2);
      			rewind (pFile2);
    			buffer2 = (char*) malloc (sizeof(char)*lSize1);
      			if (buffer2 == NULL) {fputs ("Memory error",stderr); }
      			file2str = fread (buffer2,1,lSize2,pFile2);
      			if (file2str != lSize2) {fputs ("Reading error",stderr); }
    			fclose(pFile2);
    			sscanf(buffer2,"%d",&lines1); //lines1= arithmos grammon tou processes.txt
    			sprintf(command,"rm -r %s",lines);
    			system(command);
    			free(buffer2);
    
    			i=0;
      			dyn.pids=(int *)calloc(sizeof(int),lines1); //desmeuei mnimi dinamika gia ton proto pinaka tis struct pou periexei ta pid
      			pch = strtok (buffer1,"\n");
      			while (pch != NULL)
      			{
       			 	sscanf(pch,"%d",&dyn.pids[i]);
        				pch = strtok (NULL, "\n");
    				i++;
      			}
    		
    			
    			dyn.ppids=(int *)calloc(sizeof(int),lines1);
    			for (i=1;i<lines1;i++) /*Gemizei ton pinaka kai vazei tis proteraiotites tis kathe diergasias */
    			{
    				dyn.ppids[i]=getpriority(PRIO_PROCESS,dyn.pids[i]);
    			}
    
    			//for (i=1;i<lines1;i++){
    		 	//printf("%d\n",dyn.ppids[i]); 
    			//}
    
        		close(pipe_cp[0]);
        		write(pipe_cp[1], &dyn,sizeof(dyn));
        		
    		}
    		//parent
    		else {
        		close(pipe_pc[0]);
       	 	write(pipe_pc[1], argv[1],strlen(argv[1]));
        		printf("\nparent process: father wrote to child: %s\n",argv[1]);
    
       	 	wait(NULL);
       		
       	 	close(pipe_cp[1]);//kleinoume to write-end, o pateras mono diabazei apo to pipe_cp
        		read(pipe_cp[0],&dyn,sizeof(dyn));//parent diabazei ayto poy exei grapsei to paidi
    
    		for (i=1;i<lines1;i++){
    		printf("%d\n",dyn.ppids[i]);
    		}
    
    		}
    		return 0;
    	}
    }

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You have several problems. The first one I caught was in the parent code. You use dyn and lines1 without actually initializing them. They get values in the child section, but by then, you have two totally separate processes, so the fact that lines1 has been set in the child process has no effect on lines1 in the parent process. Also, you don't allocate memory for dyn.pids or dyn.ppids in the parent process. You should probably move the code that builds the file and counts lines1 into the common section, above the fork. Then parent and child both know how many lines there will be.

    The second issue is your struct dyna. When you read sizeof(dyn), you are only reading enough bytes for 2 pointers, not the entire arrays. See Question 7.28. Besides, when you send dyn, you are only sending dyn.pids and dyn.ppids, not the elements of the arrays. dyn.pids and dyn.ppids are only two addresses, so when the parent gets them, the addresses will be meaningless and there will be no array data. Your current method would require sending each part of dyn separately, since you can only send contiguous chunks of memory through write, and there's no guarantee that the two calls to malloc will give you contiguous memory.

    It would make more sense and make your code easier if you made struct dyna contain only one copy of a pid and ppid, then made an array of struct dyna's, like so:

    Code:
    struct dyna {
        int pid;
        int ppid;
    }
    
    // child code - allocate dyn with a single calloc, and read it in from the file
    struct dyna *dyn = calloc(sizeof(*dyn), lines1);  // allocate lines1 elements of struct dyna in an array
    while (pch != NULL
    {
        sscanf(pch, "%d", &(dyn[i].pid));
        pch = strtok(NULL, "\n");
        i++;
    }
    ...
    // writes all data to the pipe in a single call
    write(pipe_cp[1], dyn, sizeof(*dyn) * lines1);  // writes all data
    Then, in your parent code, you allocate an array of struct dyna, just like in the child code, and read it all in with one read command, using the same size calculation as for the calloc and write command.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Passing data from file to arrays
    By Chris5 in forum C Programming
    Replies: 16
    Last Post: 12-06-2010, 11:13 PM
  2. Struct types and dynamic arrays
    By simone.marras in forum C Programming
    Replies: 6
    Last Post: 03-14-2009, 10:56 AM
  3. Passing 2D dynamic arrays
    By s_siouris in forum C Programming
    Replies: 5
    Last Post: 11-12-2008, 08:08 AM
  4. Save data from two struct arrays in one .dat file
    By IndioDoido in forum C Programming
    Replies: 5
    Last Post: 03-27-2008, 03:50 PM
  5. passing a struct to a named pipe
    By hickersonj in forum C Programming
    Replies: 4
    Last Post: 10-05-2007, 11:02 AM