fork() created process don't execute in parallel - c

I got an integer matrix in shared memory with n colums, so I create n processes, each of them make the sum of a colum. The problem is that they don't execute in parallel. There is the code (this doesn't actually do the sum, was to test):
int pid2[n];
i=0;
do{
pid2[i] = fork();
if(pid2[i]==-1) printf("fork() fail!\n");
else if(pid2[i]==0){
printf("Start process %d \n", i);
sleep((rand() % 50)/10);
printf("Process %d terminated" ,i);
}
else i++;
}
while(i<n&&pid2[i]>0);
What I get is that it runs in this order process 3, 2, 1 and ends in the same order, always. But the sleep is random, so the arrival time should be random too! Also I don't understand why it starts from process 3.

Your code is wrong and don't do what you think.
In the case of fork() success, the caller increments i, and then the final test of the while is false, so the original process terminates. While the new process executes its code "start 0", "terminates 0", then jumps to the test which is true and then fork again, etc. So your processes are always produced one after the other in the same order.
Here is the corrected code (with random seeding):
int pid2[n];
i=0;
do{
pid2[i] = fork();
if(pid2[i]==-1) printf("fork() fail!\n");
else if(pid2[i]==0){
printf("Start process %d \n", i);
sleep((rand() % 50)/10);
printf("Process %d terminated" ,i);
exit(0); // ends the child
}
else i++;
}
while(i<n&&pid2[i-1]>0); // test is last pid is correct

When you don't seed random number generator with srandom function, you'll always get the same sequence of "random" numbers. Usually you seed it doing srandom(time(NULL)) call.
Check this simple program:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("%d\n", rand());
return 0;
}
On my computer it always outputs 1804289383.
Also, when you call rand in your child process it always inherits parent's state of random-number-generating-machine, so your children will always generate the same random number. You shall generate this random number before forking. In the following code all children return the same random value:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define CHILDREN 3
int main(void) {
int i;
for (i = 0; i < CHILDREN; ++i) {
if (fork() == 0) {
printf("rand is %d in child %d\n", rand(), i);
return 0;
}
wait(NULL);
}
return 0;
}
Last thing is, creating some processes one-after-another doesn't mean they will get processor's time in that order. It's perfectly OK that when you fork your first child, processor's context will return to the parent, who will do another fork, and then processor's context will be assigned to the second child, not the first one.
Code that works:
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define CHILDREN 3
int main(void) {
int pid, i, children = 0;
srand(time(NULL));
double sleeptime;
for (i = 0; i < CHILDREN; ++i) {
sleeptime = (rand() % 50) / 10.0;
pid = fork();
if (pid == -1) {
perror("fork failed");
} else if (pid == 0) {
printf("Child %d crated\n", i);
fflush(stdout);
sleep(sleeptime);
printf("Child %d terminated\n", i);
fflush(stdout);
return 0;
} else {
++children;
}
}
// wait for all childredn
for (i = 0; i < children; ++i) {
wait(NULL);
}
return 0;
}

Related

System call how to make parent wait for child

This is my code system call in C.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int n;
int i;
pid_t pid;
int time = 1000;
int sum = 0;
int main(void) {
printf("n: ");
scanf("%d", &n);
pid = fork();
if (pid < 0) {
printf("Fork Failed");
exit(-1);
} else if (pid == 0) {
//child
for (i = 1; i <= n; i++) {
sum += i;
}
printf("Sum of 1 to %d: %d\n", n, sum); // this is ok
} else {
// parent
wait(&time);
printf("Sum of 1 to %d: %d\n", n, sum); // this always return 0;
}
return 0;
}
I don't know why in parent's code block, the sum is always equal to 0.
How to make parent wait for child or am I doing something wrong ?
Waiting for the child works. However, your expectations are wrong.
Apparently you think that computations in the child process after the fork are visible in the parent process. They are not. The child is a new copy of the parent program at the time of fork. At that time, the parent's sum is 0 and stays that way.
There are several mechanisms to pass data from child to parent (the search term is interprocess communication, IPC).
exit() status
files
shared memory
pipes
signals
message queues
anything else I have missed
The issue here is the variable sum is not shared by the parent & child process, after fork() call the child will have its own copy of the variable sum.
Use shmget(),shmat() from POSIX api. Or use pthread which will share the same memory space for the newly created thread.
Update---
Added the shared memory to your code hopes this helps.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
int n;
int i;
pid_t pid;
int time = 1000;
int main(void) {
int shmid;
int *sum;
printf("n: ");
scanf("%d", &n);
/*request the shared memory from the OS using the shmget()*/
shmid = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
pid = fork();
if (pid < 0) {
printf("Fork Failed");
exit(-1);
} else if (pid == 0) {
//child
/* shmat() returns a char pointer which is typecast here
to int and the address is stored in the int pointer. */
sum = (int *) shmat(shmid, 0, 0);
for (i = 1; i <= n; i++) {
*sum += i;
}
printf("Sum of 1 to %d: %d\n", n, *sum); // this is ok
/* each process should "detach" itself from the
shared memory after it is used */
shmdt(sum);
} else {
// parent
wait(&time);
sum = (int *) shmat(shmid, 0, 0);
printf("Sum of 1 to %d: %d\n", n, *sum); // this always return 0;
shmdt(sum);
/*delete the cretaed shared memory*/
shmctl(shmid, IPC_RMID, 0);
}
return 0;
}
Refer for more info- https://man7.org/linux/man-pages/man2/shmget.2.html

fork() in C. I need explanation on this code

So, i have this piece of C code
I can't grasp what the second 'for' segment is about. When does it get terminated abnormally?
Can someone enlighten me on that?
#include<unistd.h>
#include<stdio.h>
#include <sys/wait.h>
#define N 30
int main() {
pid_t pid[N];
int i;
int child_status;
for (i = 0; i < N; i++) {
pid[i] = fork();
if (pid[i] == 0) {
sleep(60 - 2 * i);
exit(100 + i);
}
}
for (i = 0; i < N; i++) {
pid_t wpid = waitpid(pid[i], & child_status, 0);
if (WIFEXITED(child_status)) {
printf("Child%d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status));
} else {
printf("Child%d terminated abnormally\n", wpid);
}
}
return (0);
}
When child is terminate ,to be able to find with which value the child was terminated (either with exit or with return) i have to pash the second parametre in waitpid() with pointer to an integer.So in that integer on return from the call it will include 2 types of information
a) if child was terminated well with return or exit or stoped unexpectedly
b)the second type will be having the termination value.
If i want to know the information from (a) i need to use the macro WIFEXITED(), if this give me true the (b) emerged from macro WEXITSTATUS().This is a simple example
#include <stdio.h>
#include <stdlib.h> /* For exit() */
#include <unistd.h> /* For fork(), getpid() */
#include <sys/wait.h> /* For waitpid() */
void delay() { /* Just delay */
int i, sum=0;
for (i = 0; i < 10000000; i++)
sum += i;
printf("child (%d) exits...\n", getpid());
exit(5); /* Child exits with 5 */
}
int main() {
int pid, status;
pid = fork();
if (pid == 0) /* child */
delay();
printf("parent (%d) waits for child (%d)...\n", getpid(), pid);
waitpid(pid, &status, 0);
if (WIFEXITED(status)) /* Terminated OK? */
printf("child exited normally with value %d\n", WEXITSTATUS(status));
else
printf("child was terminated abnormaly.\n");
return 0;
}
SOS The macro WEXITSTATUS() return only the 8 least important bits of the value when the child is terminate.So if the child wants to "say" something to his parent through exit/waitpid it must be a number up to 255.

rand command line concurrency programming

Hi i've got some problems with generating random numbers with concurrency programming, on exit() i would like ti use rand -M 6 but i don't know how, i've tried to use rand() in some ways but the childrens always returns the same number. Thanks a lot.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#define NUM_KIDS 5
int i, sum;
int main()
{
pid_t child_pid;
int status;
for (i=0; i<NUM_KIDS; i++) {
switch (child_pid = fork()) {
case -1:
/* Handle error */
fprintf(stderr,"Error #%03d: %s\n", errno, strerror(errno));
break;
case 0:
/* Perform actions specific to child */
printf("Hi, my PID is %d\n", getpid());
exit(/*here i'd like to use rand -M 6*/);
printf("Hi, my PID is %d and you should never see this message\n", getpid());
break;
default:
/* Perform actions specific to parent */
printf("I'm the proud parent with PID %d of a child with PID %d\n", getpid(), child_pid);
break;
}
}
i = 0;
while ((child_pid = wait(&status)) != -1) {
printf("PARENT: PID=%d. Got info of child with PID=%d, status=%d\n",
getpid(), child_pid, status/256);
sum += status/256;
}
if (errno == ECHILD) {
printf("In PID=%6d, no more child processes, sum: %d\n", getpid(), sum);
exit(EXIT_SUCCESS);
}
return 0;
}
You need to seed the random-number generator with srand(unsigned int).
The seed is just a number that initiates the random-number formula. With the same seed, the same sequence of numbers will always show up. I recommend seeding rand() with either clock() from time.h, or the time since January 1, 1970 in seconds (time in computers is often stored as the number of seconds since January 1, 1970).
The problem with calling rand() from the child process is that it will always be the first call to rand() in that process, so the value will always be the same each time.
What you can do instead is generate the return values in an array in the parent, then the children can grab the value they want from the array.
int main()
{
pid_t child_pid;
int status;
int rvals[NUM_KIDS];
srand(time(NULL));
for (i=0; i<NUM_KIDS; i++) {
rvals[i] = rand();
}
for (i=0; i<NUM_KIDS; i++) {
...
case 0:
printf("Hi, my PID is %d\n", getpid());
exit(rvals[i]);

creating a second process in C

Im new in C programming and i have to do this:
Write a program that creates a second process, and then in both processes outputs the process ID and the owners user ID.
I don't know if thats right and how to continue from here. Here is what i have:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
int ChildPID;
printf("This is the parent process number %d\n",getpid());
if ((ChildPID = fork()) == -1) {
perror("Could not fork");
exit(EXIT_FAILURE);
}
if (ChildPID == 0) {
//----In the child process
printf("This is the child process, number %d parent number %d\n", getpid(), getppid());
}
return(EXIT_SUCCESS);
}
The piece of code given below gives your solution. Here you can clearly identify parent code and child process code. Both are printing their corresponding pids.
void ExecuteChild(void);
void ExecuteParent(void);
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ExecuteChild();
else
ExecuteParent();
}
void ExecuteChild(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("CHILD[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Child Exiting -------------\n");
}
void ExecuteParent(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("PARENT[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Parent Exiting -------------\n");
}

fork()ing - Idle Children

So I need to iterate fork() several times, creating child processes. The child processes are supposed to "do little or not processing" for example;
while(1)
sleep(1)
The parent is then supposed to gather the PID's of the children and kill them (harsh, I know!).
However they way I'm doing it at the minute executes the code in the "parent" block several times, but I only need it to execute once.
Here is an example; you need to store the pids in a table (here p[]).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#define NSUB 10
int main ()
{
int i, n = NSUB, p[NSUB], q;
for (i = 0; i < n; i++) {
printf ("Creating subprocess %d ...\n", i);
p[i] = fork();
if (p[i] < 0) { perror ("fork"); exit (1); }
if (p[i] == 0) { /* subprocess */
printf ("Subprocess %d : PID %d\n", i, (int) getpid());
while (1) pause ();
exit (0);
}
}
sleep(2);
for (i = 0; i < n; i++) {
printf ("Killing subprocess %d ...\n", i);
if (kill (p[i], SIGTERM) < 0) perror ("kill");
}
for (i = 0; i < n; i++) {
printf ("waiting for a subprocess ...\n");
q = wait (NULL);
printf ("Subprocess terminated: PID %d\n", q);
}
exit (0);
}

Resources