Inconsistent counter value when used in multi-threaded program - c

I'm doing an assignment in C where we have a narrow road that can only support up to three cars at a time. The road is one-way so cars are allowed to go either East or West. Starvation should also be avoided. My implementation so far seems to work generally but I'm having a hard time understanding why the numOfCarsOnRoad variable has inconsistent values (i.e. printing 'Number of cars on the road = 1' twice in the output instead of '.. = 3', '.. = 2', '.. = 1') despite each thread incrementing/decreasing it each time.
Furthermore, I've noticed that if for example three threads "start" one after another (thus calling sleep(1)), they may finish in a different order. I understand that each thread runs in a separate lightweight process but shouldn't the sleep(1) last shorter for the thread that went first? Is there a way to avoid this?
The number of cars (represented by threads) is passed via the cmd args (i.e. '-c 5').
header:
void * crossBridge(void *i);
void parseCarArg(int argc, char *argv[]);
C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include "ask2.h"
sem_t sem;
int numOfCarsOnRoad = 0;
int carsGoingW = 0;
int carsGoingE = 0;
long numOfCars = 0; // used for thread initializations
char currActiveDir = '_'; // either W or E ( _ initially)
void *crossBridge(void *i)
{
int id = *((int *)i);
char direction[5];
if (rand() % 2 == 0) {
strcpy(direction, "West");
carsGoingW++;
}
else {
strcpy(direction, "East");
carsGoingE++;
}
if (currActiveDir == '_')
currActiveDir = direction[0];
printf("Car #%d waiting to pass to the %s...\n", id, direction);
while (currActiveDir != direction[0] || numOfCarsOnRoad == 3)
{
sleep(2);
}
sem_wait(&sem); // enter critical region
numOfCarsOnRoad++;
printf("Car #%d going to the %s. Number of cars on the road = %d\n", id, direction, numOfCarsOnRoad);
sleep(1);
numOfCarsOnRoad--;
sem_post(&sem);
printf("Car #%d crossed to the %s! Number of cars on the road = %d\n", id, direction, numOfCarsOnRoad);
if(direction[0] == 'W') carsGoingW--;
else carsGoingE--;
// helps to avoid starvation
if (numOfCarsOnRoad == 0)
{
if (currActiveDir == 'W' && carsGoingE > 0)
currActiveDir = 'E';
else if (currActiveDir == 'E' && carsGoingW > 0)
currActiveDir = 'W';
}
pthread_exit(NULL);
}
void parseCarArg(int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-c") == 0)
{
if (++i < argc && strlen(argv[i]) > 0)
numOfCars = strtol(argv[i], NULL, 10); // convert to long
if (numOfCars == 0)
{
perror("You must enter a number of cars > 0!\n");
exit(EXIT_FAILURE);
}
break;
}
}
}
int main(int argc, char *argv[])
{
if (argc == 0)
exit(EXIT_FAILURE);
parseCarArg(argc, argv);
srand(time(NULL)); // seed the generator using epoch time in millis
if (sem_init(&sem, 0, 3) == -1)
{
perror("Failed to initialize semaphore!\n");
exit(EXIT_FAILURE);
}
pthread_t cars[numOfCars];
int i;
for (i = 0; i < numOfCars; i++)
{
if (pthread_create(&cars[i], NULL, crossBridge, &i) != 0)
{
perror("Failed to create threads for the cars!\n");
exit(EXIT_FAILURE);
}
}
// wait for all threads to finish
for (i = 0; i < numOfCars; i++)
pthread_join(cars[i], NULL);
sem_destroy(&sem);
return 0;
}

Related

The last thread Don't Run the task like other Threads in C

So in main function I have defined variable for creating variable.
Same thing for process.
Then I fork() the parent process and then inside the child process I have created 4 Threads and above the Main function ı have created the functions Where the Threads will run.
My question is The first 3 Thread works exactly as I want But the Fourth process not working as the First 3 Thread.
Here is my code that Child Process Execute.
I used Ordinary pipe to Write message from Parent Process and Read the Message from Child Process.
readBUFFER stands for the data I read from the Pipe and about 150 character length.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
[const char readMessage\[152\];][1]
void *encrypt(char *data)
{
int shift = 4;
int i = 0;
for(i = 0; data[i] != '\0' ; ++i) {
char sm = data[i];
if(sm> 'a' && sm<='z'){
sm = sm + shift;
if(sm>'z'){
sm = sm - 'z' + 'a' - 1;
}
data[i] = sm;
}
else if(sm >= 'A' && sm<='Z'){
sm = sm + shift;
if(sm > 'Z'){
sm = sm - 'Z' + 'A'-1;
}
data[i] = sm;
}
}
return data;
}
void *threadFunc(void *message) {
printf("encrypted data : %s\n", encrypt(message));
return encrypt(message);
}
int main(void)
{
pthread_t threads[NUM_THREADS];
int pipefds[2];
//pipefds[0] - READ
//pipefds[1] - WRİTE
int returnstatus;
char readBUFFER[152];
int pid;
char writeMessages[152]={"150 characters is between 20 words and 40 words with spaces included in the character count. If spaces are not included in the character count,then 150 "};
returnstatus = pipe(pipefds);
if(returnstatus == -1)
{
printf("Pipe failed!\n");
return 1;
}
pid = fork(); //Child Process Oluşturma
if(pid == -1)
{
printf("Fork failed!\n");
return 2;
}
//Child Process
if(pid == 0)
{
close(pipefds[1]);
read(pipefds[0], readBUFFER , sizeof(readBUFFER));
printf("Child process Reads from pipe --> :%s\n",readBUFFER);
int buffer_size = strlen(readBUFFER);
printf("buffer size : %d\n",buffer_size);
char str[50];
for(int i = 1; i<=NUM_THREADS ;i++)
{
for(int j = ((buffer_size/4) * (i - 1)) ; j<=((buffer_size/4) * i) ; j++)
{
strncat(str , &readBUFFER[j] , 1);
}
printf("%d. Part --> %s\n", i,str);
pthread_create(&threads[i] , NULL , threadFunc , str);
sleep(2);
int pos = 0;
while(str[pos] != '\0')
{
str[pos] = '\0';
}
//pthread_join(threads[i] , NULL);
}
sleep(2);
}
//Parent process
else
{
close(pipefds[0]);
printf("parent process write to the pipe -->\n");
write(pipefds[1], writeMessages , sizeof(writeMessages));
wait(NULL);
printf("Child process Executed!");
}
return 0;
}
Basically encrypt function do the Caesar Encryption.
My question is when I run the First Thread they return the encrypted message but when it comes to the Fourth Thread it returns nothing.
I couldn't solve this problem maybe it's because ı haven't yet had mastered threads.
Let me know if you need more information.
and this is the output I took. Look at the 4 part. It represent the Fourth Thread.

bad file descriptor in c program with forks

this program is supposed to simulate a posix shell in regards to commands with pipes. The example I've tried to simulate and wanna make work is "ls | nl", but it doesn't and I can't figure out why. I've debugged this code for many hours with no success.
I get the error: "nl: input error: Bad file descriptor", and when I've tried not closing any of the file descriptors or closing only some (or in only one of the forks, or only the parent, etc...), and the errors change, or it works but then nl keeps waiting for input. Anyways, I'm pretty sure the errors are in fork_cmd or fork_cmds and has to do with close.
I've included all the code. I know there's nothing wrong with parser.h. I know this is pretty shitty code but it should still work I think.
I'm probably blind, but I would really appreciate it if someone could help me figure it out. Hopefully it's something that I and maybe others can learn something from.
#include "parser.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#define READ 0
#define WRITE 1
void fork_error() {
perror("fork() failed)");
exit(EXIT_FAILURE);
}
void close_error() {
perror("Couldn't close file descriptor");
exit(EXIT_FAILURE);
}
void fork_cmd(char* argv[], int n, int read_pipe[2], int write_pipe[2], int (*all_fds)[2]) {
pid_t pid;
switch (pid = fork()) {
case -1:
fork_error();
case 0:
if (read_pipe != NULL) {
if (dup2(read_pipe[READ], STDIN_FILENO) < 0) {
perror("Failed to redirect STDIN to pipe");
exit(EXIT_FAILURE);
}
}
if (write_pipe != NULL) {
if (dup2(write_pipe[WRITE], STDOUT_FILENO) < 0) {
perror("Failed to redirect STDOUT to pipe");
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < n - 1; i++) {
if (close(all_fds[i][READ]) == -1 || close(all_fds[i][WRITE] == -1)) {
close_error();
}
}
execvp(argv[0], argv);
perror("execvp");
exit(EXIT_FAILURE);
default:
printf("Pid of %s: %d\n", argv[0], pid);
break;
}
}
void fork_cmds(char* argvs[MAX_COMMANDS][MAX_ARGV], int n, int (*fds)[2]) {
for (int i = 0; i < n; i++) {
if (n == 1) {
fork_cmd(argvs[i], n, NULL, NULL, fds);
}
// n > 1
else if (i == 0) {
fork_cmd(argvs[i], n, NULL, fds[i], fds);
}
else if (i == n - 1) {
fork_cmd(argvs[i], n, fds[i - 1], NULL, fds);
}
else {
fork_cmd(argvs[i], n, fds[i - 1], fds[i], fds);
}
}
for (int i = 0; i < n - 1; i++) {
if (close(fds[i][READ]) == -1 || close(fds[i][WRITE] == -1)) {
close_error();
}
}
}
void get_line(char* buffer, size_t size) {
getline(&buffer, &size, stdin);
buffer[strlen(buffer)-1] = '\0';
}
void wait_for_all_cmds(int n) {
// Not implemented yet!
for (int i = 0; i < n; i++) {
int status;
int pid;
if ((pid = wait(&status)) == -1) {
printf("Wait error");
} else {
printf("PARENT <%ld>: Child with PID = %ld and exit status = %d terminated.\n",
(long) getpid(), (long) pid, WEXITSTATUS(status));
}
}
}
int main() {
int n;
char* argvs[MAX_COMMANDS][MAX_ARGV];
size_t size = 128;
char line[size];
printf(" >> ");
get_line(line, size);
n = parse(line, argvs);
// Debug printouts.
printf("%d commands parsed.\n", n);
print_argvs(argvs);
int (*fds)[2] = malloc(sizeof(int) * 2 * (n - 1)); // should be pointer to arrays of size 2
for (int i = 0; i < n - 1; i++) {
if (pipe(fds[i]) == -1) {
perror("Creating pipe error"); // Creating pipe error: ...
exit(EXIT_FAILURE);
}
printf("pipe %d: read: %d, write: %d\n", i, fds[i][READ], fds[i][WRITE]);
}
fork_cmds(argvs, n, fds);
wait_for_all_cmds(n);
exit(EXIT_SUCCESS);
}
The problem was that one of the parenthesis was at the wrong place in both fork_cmd and fork_cmds, it should be like this of course: close(fds[i][WRITE]). This was the original code:
for (int i = 0; i < n - 1; i++) {
if (close(fds[i][READ]) == -1 || close(fds[i][WRITE] == -1))<--
{
close_error();
}
}

How to make a process ring with fork and pipe?

Currently I'm learning C and I'd like to make a ring of n childs process with forks and pipes where n is a number enter in argument, each child could communicate with the next child in one direction like this.
I tried to do it where each child send to the next child its pid but I don't get what I want for instance if I create 3 childs :
PID:1,i in loop : 0, received : 0
PID:2, i in loop : 1, received : 0
PID:3, i in loop : 2, received : 0
But I should get :
PID:1,i in loop : 0, received : 3
PID:2, i in loop : 1, received : 1
PID:3, i in loop : 2, received : 2
Sometimes I receive a value from one random child to another here is my code, I'm not really comfortable with multiples pipes in a loop.
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
if(argc != 2) {
fprintf(stderr, "Usage : %s <integer> [> 2]\n", argv[0]);
exit(EXIT_FAILURE);
}
int number_process = atoi(argv[1]);
if(number_process < 2) {
fprintf(stderr, "Usage : %s <integer> [> 2]\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("Création de %d processus pour une élection : \n", number_process);
int i = 0, j = 0, k = 0;
int * t = (int *) malloc((2 * number_process) * sizeof(int));
for(k = 0; k < number_process; k++) {
pipe(&t[2*i]);
}
for(i = 0; i < number_process; i++) {
if(fork() == 0) {
for(j = 0; j < number_process*2; j++) {
if(j != 2*i && j != ((2*i+3)%(number_process*2))) {
close(t[j]);
}
}
close(t[(2*i+1)%(number_process*2)]);
close(t[((2*i+2)%(number_process*2))]);
int pid = (int) getpid();
write(t[(2*i+3)%(number_process*2)], &pid, sizeof(int));
int in = 0;
read(t[i*2], &in, sizeof(int));
printf("%d : %d\n", in, getpid());
exit(EXIT_SUCCESS);
}
}
return (EXIT_SUCCESS);
}
Here are the problems I have found in the program:
No error checking. Without error checking, it is much harder to find the other errors. Note that read() will return a negative result if an error occurs. In this case, you will probably get EBADF from read().
Once you add the error checking, you would investigate the source of the EBADF error, and notice that the pipes are not initialized correctly. This is due to the line pipe(&t[2*i]); which should use k instead of i. Another way to find this error is by using the address sanitizer or Valgrind, both of which would have found the error immediately (without having to change your code at all). Scoping loop variables inside the loops would have also found this problem immediately, so use for (int i = 0; ...) instead of int i; for (i = ; ...).
The close() function is called twice after the end of a loop on files which are already closed. This error is innocuous, however.
The parent process should wait for its children to exit, and it should also close the pipes first.
The program relies on line-buffering in order to work correctly. A good solution is to fflush(stdout) before calling fork().
Here is an updated version with notes:
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
void usage(const char *prog) {
fprintf(stderr, "Usage : %s <integer> [> 2]\n", prog);
exit(1);
}
int main(int argc, const char * argv[]) {
if(argc != 2) {
usage(argv[0]);
}
int number_process = atoi(argv[1]);
if(number_process < 2) {
usage(argv[0]);
}
printf("Création de %d processus pour une élection : \n", number_process);
// Flush stdout before fork.
fflush(stdout);
// Do not cast the result of malloc
// Use sizeof(*pipes) instead of sizeof(int)
// Prefer descriptive variable names
int *pipes = malloc((2 * number_process) * sizeof(*pipes));
if (!pipes) {
perror("malloc");
exit(1);
}
// Scope loop variables in the loop
for (int i = 0; i < number_process; i++) {
int r = pipe(&pipes[2*i]);
if (r == -1) {
perror("pipe");
exit(1);
}
}
for (int i = 0; i < number_process; i++) {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
// Let's avoid copy/pasting 2*i and (2*i+3)%(number_process*2)
// everywhere, which is hard to read
int infd = pipes[2*i];
int outfd = pipes[(2*i+3)%(number_process*2)];
for (int j = 0; j < number_process*2; j++) {
if (pipes[j] != infd && pipes[j] != outfd) {
close(pipes[j]);
}
}
int self = getpid();
ssize_t amt;
amt = write(outfd, &self, sizeof(int));
if (amt == -1) {
perror("write");
exit(1);
}
int in;
ssize_t r = read(pipes[i*2], &in, sizeof(int));
if (r == -1) {
perror("read");
exit(1);
}
printf("%d : %d\n", in, (int)getpid());
exit(0);
}
}
// Close pipes and wait for children to finish
for (int i = 0; i < number_process * 2; i++) {
close(pipes[i]);
}
for (int i = 0; i < number_process; i++) {
wait(NULL);
}
// Return at end of main() is implicitly "return 0".
}

Using Mutex Lock/Unlock and Broadcast for pthreads in C

This is my first post and I'm excited.
My problem is that I am creating a Rock, Paper, Scissors program in C where the parent process creates 2 threads. The 2 threads then throw a random rock, paper, or scissors and return the value to the parent where it gets counted and spits back the results of 3 rounds, then makes a final tally.
My problem is that I cannot get the threads to initiate correctly, I have them waiting in my thread_function1 but then they only complete one round and even then I don't get two threads back in the results. If someone could please shed some light I would really appreciate it! Thanks
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>
#define NTHREADS 2
struct timeval tv;
void *thread_function1();
void *thread_function2();
char *guess_string(int g);
int wins[3];
int cmd_ready = 0;
int x1=0, x2=1, count=0;
int guess, object, turns, i, j, k,l, winner, cmd, go, y;
pthread_mutex_t cv_m;
pthread_mutex_t count_mutex;
pthread_cond_t cv;
int myindex;
int flag;
int throws[3];
int main(int argc, char *argv[])
{
wins[0] = 0; wins[1] = 0;
if ((argc != 2) || ((turns = atoi(argv[1])) <= 0))
{
fprintf(stderr,"Usage: %s turns\n", argv[0]);
return 0;
}
pthread_t thread_id1, thread_id2;
if (pthread_create(&thread_id1, NULL, thread_function1,&x1) != 0)
perror("pthread_create"),
exit(1);
if (pthread_create(&thread_id2, NULL, thread_function1,&x2) != 0)
perror("pthread_create"),
exit(1);
printf("Beginning %d Rounds...\nFight!\n", turns);
printf("Child 1 TID: %d\n", (unsigned int) thread_id1);
printf("Child 2 TID: %d\n", (unsigned int) thread_id2 );
for(k=0; k<turns; k++)
{
pthread_mutex_lock (&cv_m);
cmd = go;
cmd_ready = 2;
pthread_cond_broadcast(&cv);
pthread_mutex_unlock(&cv_m);
printf("------------------------\n");
printf("Round: %d\n", k+1);
printf("Child %d throws %s!\n",myindex+1, guess_string(myindex));
pthread_mutex_lock (&count_mutex);
winner = find_winner(throws[0], throws[1]);
while(count == 2){
if(winner >= 0)
{
printf("Child %d Wins!\n", winner+1);
wins[winner]++;
printf("6\n");
}else
{
printf("Game is a Tie!\n");
}
go--;
count = 0;
pthread_mutex_unlock(&count_mutex);
}
}
pthread_join(thread_id1,NULL);
pthread_join(thread_id2,NULL);
printf("------------------------\n");
printf("------------------------\n");
printf("Result:\n");
printf("Child 1: %d\n", wins[0]);
printf("Child 2: %d\n", wins[1]);
printf("Ties: %d\n", turns - (wins[0] + wins[1]));
printf("Child %d Wins!\n", (wins[0] > wins[1]) ? 1 : 2);
pthread_mutex_destroy(&cv_m);
pthread_cond_destroy(&cv);
pthread_exit(NULL);
return 0;
}
void *thread_function1(void *p)
{
struct timeval tv;
myindex = *(int *)p;
gettimeofday(&tv, NULL);
srand(tv.tv_sec + tv.tv_usec + getpid());
printf("1\n");
pthread_mutex_lock (&cv_m);
while(cmd_ready == 0)
{
printf("2\n");
pthread_cond_wait(&cv, &cv_m);
}
printf("3\n");
throws[myindex] = rand() % 3;
cmd_ready--;
printf("Ready: %d\n",cmd_ready);
pthread_mutex_unlock (&cv_m);
printf("4\n");
pthread_mutex_lock (&count_mutex);
count++;
printf("Count %d\n", count);
pthread_mutex_unlock(&count_mutex);
while(count == 2){
printf("5\n");
return NULL;
}
}
char *guess_string(int g){
switch(g){
case 0:
return "Rock";
break;
case 1:
return "Paper";
break;
case 2:
return "Scissors";
break;
}
}
int find_winner(int g1, int g2){
if(g1 == g2)
return -1;
else if ((g1 == 2) && (g2 == 0))
return 1;
else if ((g1 == 0) && (g2 == 2))
return 0;
else
return (g1 > g2) ? 0 : 1;
}
You don't appear to be initializing your mutex or condition with pthread_mutex_init or pthread_cond_init.
The variable myindex is being modified by both threads without protection, the second thread to update this variable will be the one that appears to report back.
You are also counting on your threads to begin pending on the condition before main grabs the lock and issues the broadcast, you could have a case where main gets there first and your threads won't be ready.
That should be a start.

Forking 3 processes, using shared memory

I have an assignment, and im beating my head against the wall. It is in C. I have a feeling im close to the solution, however I cant get the program to do whats required. I am changing the numbers and some small details, because most of the class is as stumped as I.
Requirements: Create 3 processes, the first one will increment a shared memory variable "total->value" from 1 to 10000, the second from 10000 to 12000, the third from 12000 to 14000
The process functions are labeled such (process1(), process2(), process3())
and the internals of those functions are as follows
process1()
{
int k = 0;
while (k < 10000)
{
k++;
total->value = total->value + 1;
}
printf("From process 1 = %d/n", total->value);
}
The second would be k < 2000 (because it only needs to increment the shared value 2000 more) and etc.
The main portion of the program is:
main()
{
int shmid;
int pid1;
int pid2;
int pid3;
int ID;
int status;
char *shmadd = (char *)0;
/* Create and connect to a shared memory segmentt */
if ((shmid = shmget(SHMKEY, sizeof (int), IPC_CREAT | 0666)) < 0)
{
perror("shmget");
exit(1);
}
if ((total = (shared_mem *)shmat(shmid, shmadd, 0)) == (shared_mem *)-1)
{
perror("shmat");
exit(0);
}
total->value = 0;
if ((pid1 = fork()) == 0)
process1();
if ((pid1 != 0) && (pid2 = fork()) == 0)
process2();
if ((pid1 != 0) && (pid2 != 0) && (pid3 = fork()) == 0)
process3();
if ((pid1 != 0) && (pid2 != 0) && (pid3 != 0))
{
if ((shmctl(shmid, IPC_RMID, (struct shmid_ds *)0)) == -1)
{
perror("shmctl");
exit(-1);
}
printf("\t\t End of Program.\n");
}
}
What I need is for the first process to finish, before the 2nd starts. I tried inserting a wait(&status) after the process1() (or 2 or 3) calls and am at a loss. Any pointers? (no pun intended) =) there is more to implement, but I believe once I have this part I can handle the rest on my own. I have been intentionally vague in some regards, but I would like to finish this project and more importantly understand it and there are others who want a free lunch. I will provide anything else in the code that is required. Thank you in advance for your help
The output should appear
From process 1 = 10000
From process 2 = 12000
From process 3 = 14000
I believe that Celada's comment/guess on the requirements is correct. However, barring that, and at the risk of doing too much work, the following code fulfills your spec. The use of the gcc built-in __sync_fetch_and_add() is perhaps unnecessary.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/wait.h>
static struct {
int value;
} *total;
static void process1(void) {
int k = 0;
while (k < 10000) {
k++;
__sync_fetch_and_add(&total->value, 1);
}
printf("From process 1 = %d\n", total->value); //<-- not quite right: could be >10000
}
static void process2(void) {
int k = 0;
while (__sync_fetch_and_add(&total->value, 0) != 10000)
;
while (k < 2000) {
k++;
__sync_fetch_and_add(&total->value, 1);
}
printf("From process 2 = %d\n", total->value);
}
static void process3(void) {
int k = 0;
while (__sync_fetch_and_add(&total->value, 0) != 12000)
;
while (k < 2000) {
k++;
__sync_fetch_and_add(&total->value, 1);
}
printf("From process 3 = %d\n", total->value);
}
int main(void) {
int shmid;
int pid1;
int pid2;
int pid3;
int status;
/* Create and connect to a shared memory segment */
if ((shmid = shmget(1234, sizeof *total, IPC_CREAT|0666)) < 0) {
perror ("shmget");
exit (1);
}
if ((total = shmat(shmid, 0, 0)) == (void *)-1) {
perror("shmat");
exit (0);
}
total->value = 0; // not necessary in Linux if IPC_CREAT invoked
if (!(pid1 = fork()))
process1();
else if (!(pid2 = fork()))
process2();
else if (!(pid3 = fork()))
process3();
else {
wait(&status);
wait(&status);
wait(&status);
if ((shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1) {
perror("shmctl");
exit (-1);
}
printf("\t\t End of Program.\n");
}
return 0;
}

Resources