I am tryimg to write a C program that will search an array of integers for another given integer. However, to speedup the search, the search is done in parallel by two child processes. The parent process reads in the number of integers, and then the integers in an array. It also reads in the integer to be searched. It then creates two child processes. The first child process searches the first half of the array, and the second child process searches the second half. If the integer is found, its index in the array is sent to the parent through a pipe. If it is not found, a -1 is sent to the parent through a pipe. The parent waits for both child processes to finish and then prints an appropriate message.
I have consulted some books and this is what i came up with. There is a small problem though...the two child processes are running one after the other rather than parallel. what changes should i make?
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include <string.h>
void main ()
{
int i,status,num1,num2,num3,num4, fd1[2], fd2[2];
int a[1000];
char b[5],c[5],d[5],e[5];
pid_t pid1,pid2;
printf("\n\n\nEnter how many numbers - ");
scanf("%d",&num1);
//printf("\n\nEnter the %d numbers below -\n",num1);
for (i=0;i<num1;i++)
{
printf("%d : ",i);
scanf("%d",&a[i]);
}
printf("\n\nEnter the number to search - ");
scanf("%d",&num2);
pipe(fd1);
pipe(fd2);
pid1=fork();
if (pid1==0)
{
printf("this is the child 1\n");
for (i=0;i<(num1/2);i++)
{
if (a[i]==num2)
{
printf("found by process 1\n");
sprintf(b,"%d",i);
sprintf(c,"%d",-1);
write(fd1[1],&b,4);
write(fd2[1],&c,4);
//kill(0,1);
break;
}
printf("%d\n",a[i]);
}
_exit ( EXIT_FAILURE ) ;
}
else
if (pid1>0)
{
pid2=fork();
if (pid2==0)
{
printf("this is the child 2\n");
for (i=(num1/2);i<num1;i++)
{
if (a[i]==num2)
{
printf("found by process 2\n");
sprintf(b,"%d",-1);
sprintf(c,"%d",i);
write(fd1[1],&b,4);
write(fd2[1],&c,4);
//kill(0,1);
break;
}
printf("%d\n",a[i]);
}
_exit(EXIT_FAILURE);
}
}
if (waitpid (pid1, &status, 0)>0 && waitpid (pid2, &status, 0)>0)
{
read(fd1[0],d,4);
read(fd2[0],e,4);
num3=atoi(d);
num4=atoi(e);
if (num3>0) printf("value of i is %d\n",num3);
if (num4>0) printf("value of i is %d\n",num4);
}
}
Your code is fine, but remember that processor time is given out in rather large slices. That is, a short computation is often finished before the other process has even received a processor time slice. Insert a few calls to sleep into your loops, and you will see the concurrency.
Are we sure your system has more than one core? If it has only one processor, the processes will run one after the other anyway.
Related
I'm trying to write a C program in which the main process creates two children: Ping and Pong. Ping prints “ping” followed by a number, and Pong prints “pong” followed by a number, the output must be as the sample run in Figure 1:"
Here is what I tried to do:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void main(){
//initializing pipes
int td[2];
int td2[2];
pipe(td);
pipe(td2);
int pid=fork();
if(pid){ //in parent process
int pid2=fork();
if(pid2){// still in parent process
//1st time
int number1;
printf("Enter a number: ");
scanf("%d",&number1);
write(td[1],&number1,sizeof(number1));
printf("<>");
write(td2[1],&number1,sizeof(number1));
printf("--");
//2nd time
int number2;
printf("Enter a number: ");
scanf("%d",&number2);
write(td[1],&number2,sizeof(number2));
printf("<>");
write(td2[1],&number2,sizeof(number2));
printf("--");
}
else{// in pong process
int number;
read(td2[0],&number,sizeof(number));
printf("pong%d \n",number);
}
}
else{ //in ping process
int number;
read(td[0],&number,sizeof(number));
printf("ping%d \n",number);
}
}//main end
explanation: the problem that I faced here, is that the pong gets printed before ping and the parent process doesn't wait for its children to end ( and some output gets printed after root/desktop etc..)
Another problem that I solved, I had read method in the parent process, it fixed my problem because I know that read forces the program to wait until something is written to the pipe, but in this case, we have "write" in the parent process, so the parent is not waiting
I also tried to implementing wait(NULL) but it doesn't seem to work.
any suggestion would be much appreciated
It appears that you (your instructor) are over-complicating.
So, you want your main() to do
int main(void) {
int n;
//set up pipes and forks
printf("Enter a number"); scanf("%d", &n);
// make child1 output " ping<n>\n"
puts(" <>");
// make child2 output " pong<n>\n"
printf(" --\nEnter a second number"); scanf("%d", &n);
// make child1 output " ping<n>\n"
puts(" <>");
// make child2 output " pong<n>\n"
puts(" -- THE END --");
// close pipes
return 0;
}
So, except for "ping" vs "pong" (and using different pipes) the children are absolutely identical. Maybe we can send the string with the number and keep the number of functions down? No ... what about setting the string when creating the process? This sounds better
// set up pipes and forks
int pipes1[2], pipes2[2];
pipe(pipes1);
if (fork() == 0) /* child #1 */ child("ping", pipes1);
close(pipes1[0]); // the read end of the pipe belongs to the child
pipe(pipes2);
if (fork() == 0) /* child #2 */ child("pong", pipes2);
close(pipes2[0]); // we are not using the read end of the pipe
Now... how do we make a child (children are waiting at their read() call) work? Well, easy! We write on our end of the pipe
scanf("%d", &n); // get value from user
write(pipes1[1], &n, sizeof n); // automatically unblock child1
write(pipes2[1], &n, sizeof n); // automatically unblock child2
Repeat these statements for the 2nd user input.
Don't forget to close the write ends of the pipes
close(pipes1[1]);
close(pipes2[1]);
And that's the main() function. What about the function for the children? The child(char *sign, int pipes[2])?
void child(char *sign, int pipes[2]) {
close(pipes[1]); // close write end
int i;
for (;;) {
if (read(pipes[0], &i, sizeof i)) {
printf(" %s%d\n", sign, i); // print and go back to waiting at the read()
} else {
break; // exit the loop when read fails
}
}
close(pipes[0]); // no more reading
exit(EXIT_SUCCESS); // not going back to main()
}
My goal from the code is the following:
-Generate a random number between a given range
-Make user guess the number using the child process
-Make the parent tell the user if guess should be higher/lower
-If guess is correct give a signal for the child to exit.
Current code:
int main() {
int randomnumber = 1+ rand() % 51;
int guess;
pid_t pid=fork();
bool signal=false;
if(pid<0){
printf("Fork failed");
}
if(pid==0){
printf("Enter your guess: \n");
}
while(1)
{
if(pid==0){
if(signal==true)
exit(0);
scanf("%d", &guess);
}
print("test1"); //put this for debugging purposes and only executed once instead of twice
if(pid>0){
print("test2"); //this doesn't execute so I can conclude that parent isn't executing for some reason
wait(NULL);//before adding this parent used to execute and I got an infinite amount of prints which is normal, adding it made the parent not execute
if(guess>randomnumber){
printf("Guess should be lower");
}
if(guess<randomnumber){
printf("Guess should be higher");
}
if(guess==randomnumber){
printf("WIN");
signal=true;
break;
}
}
}
return 1;
}
Any idea what I can do to synchronize both of them? Why doesn't the parent execute after adding the wait function, it should at least execute the parent before wait(NULL).
As some some users remarked in comments this cannot be done unless I implement inter-process communication or a shared memory.
I'm splitting a file, sending through pipe(), having children find the sum of their designated section of the file, returning the calculated sum to the parent through pipe(), and having the parent calculate the sum of the child sums.
I've got a working program. My issues is that it hangs after receiving showing the proper final value.
I'm not sure what I'm doing to have the parent expect more information, but I'd bet it has something to do with my for() loop containing my child code.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int numchild;
int i, j, len, fpos=0, val, count=0, total=0, alltotal=0;
pid_t pid;
int nums = 1000;
FILE * file;
printf("How many children to use: ");
scanf("%d", &numchild);
printf("\nWill use %d child process(es).\n", numchild);
int fd[2*numchild][2]; //parent+child pipe
// create all pipes
for (i=0; i<2*numchild; i++)
{
pipe(fd[i]);
}
for (i=0; i<numchild; i++)
{
if((pid = fork()) == 0) // child process
{
pid = getpid();
// read from parent
len = read(fd[i][0], &fpos, sizeof(fpos));
if (len > 0)
{
file = fopen("file1.dat", "r");
fseek (file, fpos, SEEK_SET);
count = 0;
total = 0;
printf("Child(%d): Recieved position: %d\n", pid, fpos);
// read from file starting at fpos
// add values read to a total value
while (count < (nums/numchild))
{
fscanf(file, "%i", &val);
total += val;
count++;
}
//write to parent
write(fd[i+numchild][1], &total, sizeof(total));
printf("Child(%d): Sent %d to parent.\n", pid, total);
}
else
{
printf("Child(%d): Error with len\n", pid);
}
_exit;
}
// parent process
pid = getpid();
fpos = ((i*nums*5)/numchild); // 5 is the offset of the file values
// write to child process
printf("Parent(%d): Sending file position to child\n", pid);
write(fd[i][1], &fpos, sizeof(fpos));
// wait for child responce
len = read(fd[i+numchild][0], &total, sizeof(total));
if (len > 0)
{
printf("Parent(%d): Recieved %d from child.\n", pid, total);
alltotal += total;
printf("Parent(%d): Total: %d\n", pid, alltotal);
}
else
{
printf("Parent(%d): Error with len\n", pid);
}
}
}
I can't ask more questions, but if this is on Linux or Unix like systems (perhaps all posix):
You must do a wait (man 2 wait) for each of your child processes in your main program or you will create zombie processes.
Not knowing what environment you are running in makes it impossible for me to test this to determine if that is the cause of your not exiting properly.
Also (this is more like a comment), each cycle through the loop you are forking one child, then feeding it data, then getting a response, then printing the total. Is that really what you want to do? You don't need to create a bunch of pipes if you are only running one child at a time.
My guess is that you want to have some actual concurrency. You can do this by having a loop that creates all of the children followed by another loop that feeds them data, followed by a third loop that looks at the results and sums them, followed by a fourth loop that waits for each to terminate (to avoid zombies).
I would consider using poll or select to read the returns -- after all, there is no guarantee that the children will finish in order.
I won't select this as an answer until other people let me know this is probably what fixed it, but I believe that my program was hanging because the main() function wasn't actually returning anything. When I went to put in time collection (save begin time, end time, calculate difference, output) it had to be done outside of my for loop, so it was the last statement right inside my main() method. This seems to have stopped the hanging.
Right after calling fork() in your if-statement, you need to call wait(). This makes causes your parent to wait for your child to exit, and then continue he execution when the child exits.
I am writing a C program in Ubuntu 10 to create processes, display process ID and to kill process. I'm using kill() command to kill a process ID that user entered via scanf. However, the scanf is not working at all. I tried to add "space" before %d but nothing happened. Appreciate if anyone can help!
Following are my codes:
include <stdio.h>
include <unistd.h>
include <signal.h>
include <sys/types.h>
include <stdlib.h>
main ()
{
int x;
int pid[10]; // to store fork return value
int p[10]; // to store process ID
// Create 5 new processes and store its process ID
for (x=1;x<=5;x++)
{
if ((pid[x]=fork())==0)
{
p[x]=getpid();
printf("\n I am process: %d, my process ID: %d\n",x,p[x]); // Display process number and PID
}
else
exit(0);
}
{
int y;
y=p[x];
printf("Please enter a process ID to kill: ");
scanf(" %d", &y); //waiting for user input
printf("\nThe process %d is killed.\n",y);
kill(y,9); //Values 9 represents SIGKILL
}
}
Your parent process exits, and so does every process you spawn afterwards (their return value of fork is different than 1 so they exit). If a process has no parent it becomes an "orphan" and has special handling by the OS (some other process adopts it). Are you sure this is the behavior you were looking for?
EDIT:
This is probably what you meant to write:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
int main ()
{
int x;
int pid[10]; // to store fork return value
pid_t parent = getpid();
// Create 5 new processes and store its process ID
for (x=1;x<=5;x++)
{
if ((pid[x]=fork())!=0)
{
printf("\n I spawned process: %d, its process ID: %d\n",x,pid[x]); // Display process number and PID
}else{
while(1){}
}
}
if(getpid() == parent){
int y;
y=pid[x];
printf("Please enter a process ID to kill: ");
scanf(" %d", &y); //waiting for user input
printf("\nThe process %d is killed.\n",y);
kill(y,9); //Values 9 represents SIGKILL
}else{
printf("THIS SHOULD NOT HAPPEN!");
}
return 0;
}
fork returns twice, each time in a different process. One very important thing to realize about the two processes is that they do not share memory. That means that by calling getpid in the child and saving that in an array you are unable to see that value in the parent's copy of the variable.
What you most likely want to do is something like:
for (...) {
if ((pid[x]=fork()) == 0) {
printf("child created, pid = %d\n", getpid());
while(1) sleep(1000); /* children will never run outside this loop */
} else {
continue;
}
}
/* this code only runs in the parent */
I have written a program where I have created a child process. Both the parent process and child process do calculation in two parts- parent_part1 , parent_part2 and child_part1, child_part2.
My aim is to run the (parent_part1,child_part1,parent_part2 ,child_part2) sequence for let us say 5 times. For this purpose I have used while(var_child++<10) and while(var_par++<10) and successfully achieved it.
Now, I will define ONE SUCCESSFUL calculation is execution of (parent_part1,child_part1,parent_part2 ,child_part2) sequence for 5 times and display the final correct value.
I want to find such 100 SUCCESSFUL calculation and for the same purpose I have used OUTER loop (i.e., while(t1++<100) ), but I am not getting the SUCCESSFUL calculation for 100 times , sometimes I got 40 SUCCESSFUL result, and hanged after parent_part1 or parent_part2 or child_part1 or child_part2 etc. and some other times I got 20 or 95 SUCCESSFUL result, and hanged after parent_part1 or parent_part2 or child_part1 or child_part2 etc.
What is the reason and how to overcome this ?
Thank you in advance . The program is as below.
#include<stdio.h>
#include<signal.h>
int flagp=0,flagc=0,var_child=0,var_par=0;
void write_child()
{
if(flagc==0)
{
/* do some computation here*/
printf("Child_part1 \n");
flagc=1;
}
else
{
/* do some computation here*/
flagc=0;
printf("Child_part2 \n");
}
}
void write_parent()
{
if(flagp==0)
{
/* do some computation here*/
printf("Parent_part1 \n");
flagp=1;
}
else
{
/* do some computation here*/
printf("Parent_part2 \n");
flagp=0;
}
}
int main(int ac, char **av)
{
printf("Starting...\n");
int t1=0;
pid_t childpid = fork();
printf("childpid=%d,getppid()=%d \n",childpid,getppid());
while(t1++<100)
{
var_child=0;
var_par=0;
if ( childpid == 0 )
{
// child process
printf("\n\nt1=%d ",t1);
while(var_child++<10)
{
kill(getppid(), SIGCONT); //sending singal to parent
signal(SIGCONT, write_child);
pause();
}
}
else
{
//parent process
printf("\n\nt1=%d ",t1);
while(var_par++<10)
{
kill(childpid, SIGCONT); //sending singal to child
signal(SIGCONT, write_parent);
pause();
}
} // end of else
}
return 0;
}
Are you sure this logic is correct?
while(var_par++<10)
Apart from that, you are not catching the signal from the parent process. you are creating a lot of zombie processes when the child terminates and by killing the parent from child, you are creating orphans. Both will take system resources and might hit the upper limit on consecutive executions. Try catching the signal and see how it behaves.