I have N number of childs that needs to do some work in a loop while being synchronized with each other at the same time. Namely, if a child process is at its i'th iteration, all the other childs should be at i'th iteration. I need to synchronize them with semaphores but I can't find how to do it. This is the code I wrote:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/sem.h>
void sem_signal(int semid, int val) {
struct sembuf semaphore;
semaphore.sem_num = 0;
semaphore.sem_op = val;
semaphore.sem_flg = 0;
semop(semid, &semaphore, 1);
}
void sem_wait(int semid, int val) {
struct sembuf semaphore;
semaphore.sem_num = 0;
semaphore.sem_op = (-1 * val);
semaphore.sem_flg = 0;
semop(semid, &semaphore, 1);
}
int main() {
int sem_worker = semget(1, 1, 0700 | IPC_CREAT);
semctl(sem_worker, 0, SETVAL, 0);
int process_index = 0;
int N = 4, pid;
for (process_index = 0; process_index < N; process_index++) {
pid = fork();
if (pid == -1) {
printf("ERROR: cannot fork!\n");
return EXIT_FAILURE;
}
if (pid == 0)
break;
}
if (pid!=0) // parent
pause();
else {
int i = 0;
while (i < 3) {
printf("process %d: i: %d\n", process_index, i);
sem_signal(sem_worker, 1); // increase the semaphore by one
sem_wait(sem_worker, N); // wait for all the other childs
i += 1;
}
}
}
But when I run it, it can't continue after the first iteration.
process 0: i: 0
process 1: i: 0
process 3: i: 0
process 2: i: 0
process 0: i: 1
I understand why this happens. It's because one of the processes makes the semaphore 0 and continue to next iteration but all the other ones still waits. So how should I write my code to solve this problem?
P.S: I have taken sem_signal and sem_wait functions from somewhere else so I'm not sure how it works but I'm sure that they are working correctly. For example, if I write sem_wait(my_sem, num_of_children) in parent to wait all the child processes and increase my_sem by 1 in childs when they finish, it works.
As it is mentioned in the comments, you can create a barrier using semaphores and use it to synchronize your processes. You need to create your barrier in a shared memory and set a non-zero value for your semaphores' pshared parameter to share it among processes:
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <signal.h>
#include <unistd.h>
typedef struct {
int n;
int count;
sem_t mutex;
sem_t turnstile;
sem_t turnstile2;
} barrier_t;
void init_barrier(barrier_t *barrier, int n)
{
barrier->n = n;
barrier->count = 0;
sem_init(&barrier->mutex, 1, 1); // second parameter is pshared
sem_init(&barrier->turnstile, 1, 0);
sem_init(&barrier->turnstile2, 1, 0);
}
void phase1(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (++barrier->count == barrier->n) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstile);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstile);
}
void phase2(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (--barrier->count== 0) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstile2);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstile2);
}
void wait_barrier(barrier_t *barrier)
{
phase1(barrier);
phase2(barrier);
}
int shmid, KEYSHM=123456;
int main(int argc, char const* argv[]) {
barrier_t* barrier;
shmid = shmget(KEYSHM, sizeof(barrier_t), 0700 | IPC_CREAT);
barrier = (barrier_t*) shmat(shmid, 0, 0);
int N = 4;
init_barrier(barrier, N);
shmdt(barrier);
int process_index, pid;
for (process_index = 0; process_index < N; process_index++) {
pid = fork();
if (pid == -1) {
printf("ERROR: cannot fork!\n");
return EXIT_FAILURE;
}
if (pid == 0)
break;
}
if (pid != 0) // parent
pause();
else {
int i = 0;
while (i < 3) {
barrier = (barrier_t*) shmat(shmid, 0, 0);
printf("process %d: i: %d\n", process_index, i);
i += 1;
wait_barrier(barrier);
shmdt(barrier);
}
if (process_index == 3){
kill(getppid(), SIGKILL);
}
}
}
process 0: i: 0
process 1: i: 0
process 2: i: 0
process 3: i: 0
process 2: i: 1
process 3: i: 1
process 0: i: 1
process 1: i: 1
process 3: i: 2
process 2: i: 2
process 0: i: 2
process 1: i: 2
Related
I thought that wait() fuction will wait until the proces has done, however it receives a signal -1. Does anyone know the reason of the problem? May be the problem is my shared memory? So I tried to make a debugging, and in the debbuging mode there is no problem like when I run my code in normal mode.
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <unistd.h>
#include <errno.h>
#define PROCESSES 3
struct shdata
{
int x;
};
void childf(int shared_memory, int index)
{
// connect shared memory
struct shdata* shm = (struct shdata*)shmat(shared_memory, NULL, 0);
if(shm == (void*)-1)
{
perror("shmat");
exit(0);
}
// initialize x as 0
if(index == 0)
{
shm->x = 0;
}
// increment x
shm->x++;
//show x
printf("Proces %d: x = %d\n", index, shm->x);
// disconnect shared memory
if(shmdt(shm) == -1)
{
perror("shmdt");
exit(0);
}
// end child process
exit(0);
}
int main(int argc, const char * argv[]) {
// create shared memory
int shared_memory = shmget(IPC_PRIVATE, 4096, 0600 | IPC_CREAT | IPC_EXCL);
if(shared_memory == -1)
{
perror("shmget");
return 1;
}
// create child processes
for (int i = 0; i < PROCESSES; i++)
{
int pid = fork();
if(pid == -1)
{
perror("fork");
return 5;
}
if(pid == 0)
{
childf(shared_memory, i);
}
}
// wait for child processes
for(int i = 0; i < PROCESSES; i++)
{
int wait_res = wait(NULL);
if(wait_res < 0)
{
perror("wait");
return 6;
}
}
// delete shared memory
int delete_memory = shmctl(shared_memory, IPC_RMID, NULL);
if(delete_memory == -1)
{
perror("shmctl");
return 4;
}
return 0;
}
There what I gets:
Proces 0: x = 1 Proces 1: x = 2 Proces 2: x = 3 wait: Interrupted system call Program ended with exit code: 6
But from time to time I dont receive this error. So what is the problem?
I expected:
Proces 0: x = 1 Proces 1: x = 2 Proces 2: x = 3 Program ended with exit code: 0
An otherwise benign signal can always interrupt wait (and other blocking system calls). If you are not interested in signals, just go back to waiting.
Instead of this
wait_res = wait(NULL);
use this:
while ((wait_res = wait(NULL)) == -1) {
if (errno != EINTR) break;
}
This question already has answers here:
How to use shared memory with Linux in C
(5 answers)
Closed 4 years ago.
This is essentially what I want to do, but the outputs are junk data. What are some of the different options I have for making the child's array visible from inside the parent process?
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int foo[3]; //initialize array
pid_t pid;
pid = fork(); //create child thread
if (pid == 0) { //child:
foo[0] = 0; foo[1] = 1; foo[2] = 2; //populate array
}
else { //parent:
wait(NULL); //wait for child to finish
printf("%d %d %d", foo[0], foo[1], foo[2]); //print contents of array
}
return 0;
}
Using mmap you can create a shared memory block in your parent process. This is a basic example removing error checking for brevity.
You want to sure the proper protections and flags are set for your needs. Then hand off the address returned by mmap to your child process.
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#define LIMIT_MAP 5
void child_worker(void *map)
{
int map_value = -1;
int idx = 0;
while (map_value != LIMIT_MAP) {
map_value = *((int *) map + (idx * sizeof(int)));
printf("Map value: %d\n", map_value);
idx++;
sleep(2);
}
}
int main(int argc, char *argv[])
{
printf("Starting Parent Process...\n");
long page_size = sysconf(_SC_PAGESIZE);
void *memory_map = mmap(0, page_size, PROT_WRITE | PROT_READ,
MAP_SHARED | MAP_ANONYMOUS, 0, 0);
printf("Memory map created: <%p>\n", memory_map);
pid_t pid = fork();
if (pid == 0) {
sleep(1);
printf("Starting child process\n");
child_worker(memory_map);
printf("Exiting child process...\n");
return 0;
} else {
printf("Continuing in parent process\n");
int set_values[5] = { 1, 2, 3, 4, 5 };
for (int i=0; i < 5; i++) {
printf("Setting value: %d\n", set_values[i]);
*((int *) memory_map + (sizeof(int) * i)) = set_values[i];
sleep(1);
}
waitpid(pid, NULL, 0);
printf("Child process is finished!\n");
}
return 0;
}
If fork isn't a requirement and your platform allows for it, pthread is one option. Depending on how your array is being operated on, create a thread pool passing each worker thread a copy of your array.
This is a contrived example but maybe you can pull something from it:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#define THREAD_COUNT 3
#define ITER_LIMIT 7
struct worker_params {
int idx;
int max;
bool done;
double *data;
double condition;
};
void *worker(void *arg)
{
struct worker_params *wp = (struct worker_params *) arg;
int count = 0;
while ( 1 ) {
wp->data[wp->idx] = drand48();
if (wp->max == count)
wp->done = true;
sleep(1);
count++;
}
return NULL;
}
int main(int argc, char *argv[])
{
double data[THREAD_COUNT] = { 0.0 };
pthread_t worker_1, worker_2, worker_3;
pthread_t worker_threads[] = { worker_1, worker_2, worker_3 };
struct worker_params wps[] = {
{ .idx=0, .condition=0.1, .data=data, .done=0 },
{ .idx=1, .condition=0.2, .data=data, .done=0 },
{ .idx=2, .condition=0.3, .data=data, .done=0},
};
for (int i=0; i < THREAD_COUNT; i++) {
wps[i].max = (rand() % ITER_LIMIT) + 2;
pthread_create(&worker_threads[i], NULL, worker, (void *) &wps[i]);
}
// Continue on main execution thread
int running = 1;
while ( running ) {
for (int i=0; i < THREAD_COUNT; i++) {
if (wps[i].done) {
printf("Limit hit in worker <%d>\n", i + 1);
running = 0;
break;
}
printf("Data in worker <%d> :: %g\n", i + 1, wps[i].data[i]);
}
sleep(1);
}
return 0;
}
I'm implementing a solution to a problem that uses shared memory, but somehow, my code seems to "freeze" between a print statement and an if statement.
Here's the relevant code snippet:
#include "ch_problem_headers.h"
int main(int argc, char *argv[])
{
int semid, shmid;
int i;
int waiting_C, waiting_H = 0; // shared
int c_pid,h_pid;
time_t t;
// There should be three semaphores: S for when to pass the molecule on,
// SC for the carbon waiting, and SH for the hydrogen waitin
unsigned short seminit[NUM_SEMS];
struct common *shared;
union semun semctlarg;
srand((unsigned)time(&t));
if((semid = semget(IPC_PRIVATE, NUM_SEMS, IPC_CREAT|0777)) < 0)
{
perror("semget");
exit(EXIT_FAILURE);
}
// Initialize semaphores
seminit[S_SEM] = 1;
seminit[SC_SEM] = 0;
seminit[SH_SEM] = 0;
semctlarg.array = seminit;
// Apply initialization
if((semctl(semid, NUM_SEMS, SETALL, semctlarg)) < 0)
{
perror("semctl");
exit(EXIT_FAILURE);
}
// Get shared memory id
if((shmid = shmget(IPC_PRIVATE, 1*K, IPC_CREAT|IPC_EXCL|0660)) < 0)
{
perror("shmget");
exit(EXIT_FAILURE);
}
// Retrieve pointer to shared data structure
if((shared = (struct common *)shmat(shmid, 0, 0)) < 0)
{
perror("shmat");
exit(EXIT_FAILURE);
}
shared->waiting_C = 0;
shared->waiting_H = 0;
printf("ready to fork\n");
// fork process C
c_pid = fork();
printf("c_pid is %d\n", c_pid);
if(c_pid == 0)
{
printf("I'm process C!/n");
// wait on S
semWait(semid, S_SEM);
// if waiting_H >= 4
if(shared->waiting_H >= 4)
{
// signal SH four times
for(i = 0; i < 4; i++)
{
semSignal(semid, SH_SEM);
printf("H");
}
// Decrement waiting_H by 4
shared->waiting_H -= 4;
// Signal S
semSignal(semid, S_SEM);
}
// Otherwise, increment waiting_C by 1
else
{
shared->waiting_C += 1;
// Signal S and wait for SC
semSignal(semid, S_SEM);
semWait(semid, SC_SEM);
}
}
else
{
printf("C's process id is %d\n", c_pid);
printf("ready to fork again\n");
// fork process H
h_pid = fork();
printf("Is h_pid zero? %d\n", (h_pid == 0));
if(h_pid == 0)
{
printf("I'm process H!/n");
// Wait on S
semWait(semid, S_SEM);
// If waiting_h >= 3
if(shared->waiting_H >= 3)
{
// Signal SH three times, decrement waiting_H by 3, signal SC, decrement
for(i = 0; i < 3; i++)
{
printf("H");
semSignal(semid, SH_SEM);
}
shared->waiting_H -=3;
semSignal(semid, SC_SEM);
shared->waiting_C -= 1;
semSignal(semid, S_SEM);
// waitng_C by 1, and signal S
}
// Otherwise, increment waiting_H by 1, signal S, and wait on SH
else
{
shared->waiting_H += 1;
semSignal(semid, S_SEM);
semWait(semid, SH_SEM);
}
}
else
{
printf("In the parent\n");
}
}
}
And the relevant header file:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define K 1024
#define NUM_SEMS 3
#define SEMKEY 77
#define SHMKEY 77
#define S_SEM 0
#define SH_SEM 1
#define SC_SEM 2
#define NUM_H 4
#define NUM_C 1
union semun
{
unsigned short *array;
};
struct common
{
int waiting_C;
int waiting_H;
};
void semWait(int semid, int semaphore)
{
struct sembuf psembuf;
psembuf.sem_op = -1;
psembuf.sem_flg = 0;
psembuf.sem_num = semaphore;
semop(semid, &psembuf, 1);
return;
}
void semSignal(int semid, int semaphore)
{
struct sembuf vsembuf;
vsembuf.sem_op = 1;
vsembuf.sem_flg = 0;
vsembuf.sem_num = semaphore;
semop(semid, &vsembuf, 1);
return;
}
The program output when run is as follows:
Parent output (correct) :
ready to fork
c_pid is 2977
C's process ID is 2977
ready to fork again
Is h_pid zero? 0
In the parent
Child output:
Is h_pid zero? 1
c_pid is 0
I tried running the program in valgrind, and the program simply halted after the child output. I'm confused as to how this is possible, as the program seems to simply stop between the c_pid print statement and the if(c_pid == 0) statement.
Does anyone have any idea why this might be? Thanks so much.
it's my first time posting here. I'm new to OS programming.
So I have this program that I found online and decided to modify it. The parent creates a char array that contains a random letter. This letter is passed to the child, and the child removes it.
I have trouble retrieving the letter from the child. I'm getting something, but they're not the correct letters.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define BUFFER_SIZE 10
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
#else
union semun
{
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
#endif
int main(int argc, char* argv[])
{
int sem_set_id;
union semun sem_val;
int child_pid;
int i, j = 0, k;
struct sembuf sem_op;
int rc;
struct timespec delay;
srand(time(NULL));
sem_set_id = semget(IPC_PRIVATE, 1, 0600);
if (sem_set_id == -1)
{
perror("main: semget");
exit(1);
}
printf("semaphore set created, semaphore set id '%d'.\n", sem_set_id);
sem_val.val = 0;
rc = semctl(sem_set_id, 0, SETVAL, sem_val);
child_pid = fork();
char letter[BUFFER_SIZE];
int fd[2];
switch (child_pid)
{
case -1:
//fail
perror("fork");
exit(1);
case 0: //child
close(fd[1]);
for (i = 0; i < BUFFER_SIZE; i++)
{
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
read(fd[0], &letter[i], sizeof(letter[i]));
printf("Consumer removes ");
printf("['%c'] ", letter[i]);
printf("at index [%d]\n", i);
printf("\n");
fflush(stdout);
close(fd[1]);
}
break;
default: //parent
close(fd[0]);
for (i = 0; i < BUFFER_SIZE; i++)
{
//usleep(100);
letter[i] = (char)num(i);
write(fd[1], &letter[i], sizeof(letter[i]));
printf("Producer creates ");
printf("['%c'] ", letter[i]);
printf("at index [%d]\n", i);
printf("\n");
fflush(stdout);
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
if (rand() > 3 *(RAND_MAX/4))
{
delay.tv_sec = 0;
delay.tv_nsec = 10;
nanosleep(&delay, NULL);
}
close(fd[1]);
}
break;
}
return 0;
}
int num(int i)
{
i = rand() % (90 - 65) + 65;
return i;
}
Here is a sample output:
semaphore set created, semaphore set id '2850903'.
Producer creates ['N'] at index [0]
Producer creates ['M'] at index [1]
Consumer removes ['0'] at index [0]
Consumer removes ['P'] at index [1]
Producer creates ['E'] at index [2]
Producer creates ['I'] at index [3]
Producer creates ['X'] at index [4]
Consumer removes [''] at index [2]
Consumer removes ['�'] at index [3]
Consumer removes ['�'] at index [4]
Producer creates ['Q'] at index [5]
Consumer removes [''] at index [5]
Producer creates ['M'] at index [6]
Consumer removes [''] at index [6]
Producer creates ['F'] at index [7]
Consumer removes [''] at index [7]
Producer creates ['M'] at index [8]
Producer creates ['D'] at index [9]
Consumer removes [''] at index [8]
Consumer removes [''] at index [9]
EDIT1
I used shared memory. The child only recognizes the last letter that the parent added on the array and repeats it.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/shm.h>
#define BUFFER_SIZE 10
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
#else
union semun
{
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
#endif
int main(int argc, char* argv[])
{
char letter[BUFFER_SIZE];
int shmid;
void *shm = NULL;
shmid = shmget((key_t)1, sizeof(int), 0666|IPC_CREAT);
shm = shmat(shmid, 0, 0);
int *shared = (int*)shm;
*shared = 0;
int sem_set_id;
union semun sem_val;
int child_pid;
int i, j = 0, k;
struct sembuf sem_op;
int rc;
struct timespec delay;
srand(time(NULL));
sem_set_id = semget(IPC_PRIVATE, 1, 0600);
if (sem_set_id == -1)
{
perror("main: semget");
exit(1);
}
printf("semaphore set created, semaphore set id '%d'.\n", sem_set_id);
sem_val.val = 0;
rc = semctl(sem_set_id, 0, SETVAL, sem_val);
child_pid = fork();
switch (child_pid)
{
case -1:
//fail
perror("fork");
exit(1);
case 0: //child
for (i = 0; i < BUFFER_SIZE; i++)
{
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
printf("Consumer removes ");
printf("['%c'] ", *shared);
printf("at index [%d]\n", i);
printf("\n");
fflush(stdout);
}
break;
default: //parent
for (i = 0; i < BUFFER_SIZE; i++)
{
//usleep(100);
shm = shmat(shmid, 0, 0);
*shared = num(i);
printf("Producer creates ");
printf("['%c'] ", *shared);
printf("at index [%d]\n", i);
printf("\n");
fflush(stdout);
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
if (rand() > 3 *(RAND_MAX/4))
{
delay.tv_sec = 0;
delay.tv_nsec = 10;
nanosleep(&delay, NULL);
}
}
break;
}
return 0;
}
int num(int i)
{
i = rand() % (90 - 65) + 65;
return i;
}
When you use fork, each variable is duplicated to each process - ie each process has its own copy of already defined variables-, and new variables are process dependent. So, you cannot simply shared memory like that.
In your case, your write in an array and read in another one, which is not initialized, because each process (child and parent) has its own memory.
Take a look at : How to share memory between process fork()? It would explain to you how to use shared memory between processes created with fork (shm_open(), shm_unlink(), mmap(), etc.).
EDIT
By reading your code, title and question, you mix 2 way to share data between child and parent. So you have 2 choices :
Use shared memory and semaphore : array are shared between process, and semaphore ensure you that you can read or write some part of shared array. No need of read, write and fd
Or use a pipe : don't need shared memory and semaphore, just use a pipe, ie fd read and write.
Choice 1
The first argument of mmap is pretty same as malloc. So in your case with array you should have something like that :
...
char * glob_array = mmap(NULL, sizeof(char) * BUFFER_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
child_pid = fork();
....
You can now use glob_array in both child and parent. In this case, don't use read or write and fd, data are directly available in glob_array (ie if you need first data, use glob_array[0] directly, glob_array[1] for second and so on). Also, semaphore ensure you about simultaneous read/write.
Choice 2
By re-reading your code, I think I pass over something : you maybe want to use read and write to pass values from child to parent. So you need pipe. On original code you pasted, move declaration of fd before fork and initialize pipe :
int fd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
child_pid = fork();
And it will be work without sharing array ;) Also read in a pipe will block until a data is available, so, you don't need semaphore.
My problem is the stock doesnt change i think there is something wrong in the if statement pid[i] == 0. I doenst get the prints from the "father process part" of my code only from the childs.
#include <stdio.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/types.h>
#define NUM_CHILDS 3
#define LOOPS 6
#define FILLING_UP 20
#define SHMSEGSIZE sizeof(int)
int main() {
int shmID1, shmID2, *stock, *flag, loop_i, pid[NUM_CHILDS], i;
loop_i = 1;
shmID1 = shmget(IPC_PRIVATE, SHMSEGSIZE, IPC_CREAT | 0644);
shmID2 = shmget(IPC_PRIVATE, SHMSEGSIZE, IPC_CREAT | 0644);
stock = (int *) shmat(shmID1, 0, 0);
flag = (int *) shmat(shmID2, 0, 0);
*stock = 20;
*flag = 1;
for (i = 0; i < NUM_CHILDS; i++) {
pid[i] = fork();
if(pid[i] == -1) {
printf("error by crating a child!\n\n");
return -1;
}
if (pid[i] == 0) {
printf("Child %d: %d", i, pid[i]);
while(*flag==1) {
if(*stock>0) {
*stock--;
usleep(100000);
}
}
shmdt(flag);
shmdt(stock);
return 0;
}
else {
while(loop_i <= LOOPS) {
usleep(100000);
printf("Actual stock: %d\n", *stock);
if(*stock<=0) {
*stock += FILLING_UP;
loop_i++;
printf("Stock is filled up");
}
}
*flag = 0;
}
}
for (i = 0; i < NUM_CHILDS; i++) {
waitpid(pid[i], NULL, 0);
}
printf("Programm ends", LOOPS, *stock);
shmdt(flag);
shmdt(stock);
shmctl(shmID1, IPC_RMID, 0);
shmctl(shmID2, IPC_RMID, 0);
return 0;
}
The fork() in Linux is used to create new process. Also after forking, it returns 0 in child process and returns pid of child process in parent process. So in parent process pid!=0. Hence the statement inside the if(pid==0) will not execute in parent process.
You should reset loop_i to 1. Otherwise the while loop in the parent will run LOOPS times for the first child and 0 times for the other children.
loop_i = 1;
while(loop_i <= LOOPS) {
...
}