I am trying to add the variable bank into shared memory to explore race conditions and process synchronization using semaphores. When I setup the variable in shared memory my program gives me segmentation fault:11. Can someone explain what I am doing wrong here and how I can go about fixing this? Thanks!
RACE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <semaphore.h>
int shmid;
int shmkey = 585858;
sem_t mutex; // semaphore global variable
struct Bank {
int balance[2];
};
struct Bank *bank;
// routine for thread execution
void* MakeTransactions() {
int i, j, tmp1, tmp2, rint;
double dummy;
// wait on semaphore
//sem_wait(&mutex);
for (i=0; i < 100; i++) {
rint = (rand()%30)-15;
if (((tmp1=bank->balance[0])+rint) >=0 &&
((tmp2=bank->balance[1])-rint)>=0) {
//sem_wait(&mutex);
bank->balance[0] = tmp1 + rint;
//sem_post(&mutex);
for (j=0; j < rint*100; j++) {
dummy=2.345*8.765/1.234; // spend time on purpose
}
//sem_wait(&mutex);
bank->balance[1] = tmp2 - rint;
//sem_post(&mutex);
}
}
// increment value of semaphore
//sem_post(&mutex);
return NULL;
}
int main(int argc, char **argv) {
int i;
void* voidptr = NULL;
// initialize semaphore
sem_init(&mutex, 0, 1);
// shared memory
//bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// create shared memory
shmid = shmget(shmkey, 1024, IPC_CREAT);
// attach to shared memory
bank = shmat(shmid, NULL, 0);
//check if bank is not NULL
bank->balance[0] = 100;
bank->balance[1] = 100;
pid_t pid;
srand(getpid());
printf("\nInit balances A:%d + B:%d ==> %d!",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
pid=fork();
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid == 0) {
printf("\nChild computing ...");
MakeTransactions();
printf("\nChild process complete");
printf("\nLet's check the balances A:%d + B:%d ==> %d ?= 200",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
else {
printf("\nParent computing...\n");
MakeTransactions();
wait(NULL);
printf("\nParent process complete\n");
printf("Let's check the balances A:%d + B:%d ==> %d ?= 200\n\n",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
sem_destroy(&mutex);
// deattach shared memory pointer
shmdt(&bank,NULL);
//munmap(bank, sizeof(struct Bank));
return 0;
}
Okay the reason it gives you a segfault is because you're probably running this program as an unprivileged user. shmat requires privileges. If you are running it under linux you can do this:
sudo setcap cap_ipc_owner=ep ./myprog
to enable it to call shmat etc.
and then run it.
You would've found out about this if you had added a bit of error handling:
shmid = shmget(shmkey, 1024, IPC_CREAT);
if (shmid == -1 ) {
perror("shmget");
exit(errno);
}
// attach to shared memory
bank = shmat(shmid, NULL, 0);
if (bank == (void *)-1) {
perror("bank");
exit(errno);
}
Related
I have coded little program that uses shared memory that sends bytes around basicly.
The problem I have is, I think, that I'm getting stuck in the child process (it prints Process 2: 5000 and then nothing).
Can anyone help me? I'd really appreciate it!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
int main() {
int sem_id;
int shm_id;
key_t key = ftok("shared_memory", 1); // Create key shared memory
key_t keytwo = ftok("semaphore", 1); // Create key semaphore
shm_id = shmget(key, sizeof(int), IPC_CREAT | 0666); // Create shared memory
sem_id = semget(keytwo, 1, IPC_CREAT | 0666); // Create Semaphore
if((shm_id = shmget(key, sizeof(int), IPC_CREAT | 0666)) == -1){ // -1 indicates error
perror("semctl");
exit(1);
} else {
printf("Shared memory created with id: %d \n", shm_id);
}
if((sem_id = semget(keytwo, 1, IPC_CREAT | 0666)) == -1){ // -1 indicates error
perror("semctl");
exit(1);
} else {
printf("Sephamore created with id: %d \n", shm_id);
}
struct sembuf sem_lock = {0, -1, 0}; // Struct for semop to lock
struct sembuf sem_unlock = {0, 1, 0}; // Struct for semop to unlock
char *data = (char *)shmat(shm_id, NULL, 0); // Connect Shared-Memorys to Process
pid_t pid;
semctl(sem_id, 0, SETVAL, 1); //initialize the semaphore with value 1
if((semctl(sem_id, 0, SETVAL, 1)) == -1){ // -1 indicates error
perror("semctl");
exit(1);
} else {
printf("Sephamore initialized \n");
}
pid = fork();
if(pid < 0){
printf("Error");
return 1;
}
int p = 1;
int c = 1;
//16777216 = 1024 * 16384
char *message = (char *) malloc(16777216);
char *read = (char *) malloc(16777216);
for (int KiB = 1; KiB <= 16384; KiB *= 2) {
int bytes = KiB * 1024;
for(int i = 0; i < 1000; i++){
if (pid == 0) {
// Process 2:
semop(sem_id, &sem_lock, 1);
memcpy(read, data, bytes); //"read" data
//printf("%s \n", read) //print to check whether read worked
semop(sem_id, &sem_unlock, 1);
//print to check race condition
printf("Process 2 print: %d \n", p);
p++;
} else {
// Process 1:
for (int i = 0; i < bytes; ++i) {
message[i] = 'a';
}
semop(sem_id, &sem_lock, 1);
printf("%d", sem_id);
memcpy(data, message, bytes);
semop(sem_id, &sem_unlock, 1);
//print to check race condition
printf("Process 1 print: %d \n", c);
c++;
wait(NULL);
}
}
}
shmdt(data); // Remove shared-memory from process
shmctl(shm_id, IPC_RMID, NULL); // Delete shared memory
semctl(sem_id, 0, IPC_RMID); // Delete semaphore
return 0;
}
I was expecting the processes to alternate.
I have tried:
Place locks differently, Add locks, Remove locks, Remove unlocks, sleep(1).
I am not saying this is the reason for the failure, but you are not testing any return codes from these functions. Always test returns, especially if you are seeing problems and / or are new to calls
taking semctl as an example. looking here https://man7.org/linux/man-pages/man2/semctl.2.html you see that it returns a value indicating the result
so here
semctl(sem_id, 0, SETVAL, 1); //initialize the semaphore with value 1
you should do
if(semctl(sem_id, 0, SETVAL, 1) == -1){ // -1 indicates error
perror("semctl");
exit(1);
}
I have the following program:
#include <stdio.h>
#include <sys/types.h>
#define MAX_COUNT 100
void ChildProcess(void);
void ParentProcess(void);
void main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
}
void ChildProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf(" This line is from child, value = %d\n", i);
printf(" *** Child process is done ***\n");
}
void ParentProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf("This line is from parent, value = %d\n", i);
printf("*** Parent is done ***\n");
}
I have to modify it in a way that both the parent and the child print stored data from the shared memory in the following way:
Create and initialize the shared memory in the parent.
Fill the shared memory with 5 integer numbers. (I should allocate enough shared memory to store the 5 ints.)
Fork from the parent to the child.
If fork is successful, then the child process must print the values stored in the shared memory as shown in the expected output where N1, N2, N3, N4, N5 are the numbers found in the shared memory.
Expected output
What I did in the ParentProcess function is the following:
void ParentProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf("This line is from parent, value = %d\n", i);
printf("*** Parent is done ***\n");
int localVar = 0;
int* p = (int*) malloc(2);
pid_t childPID = fork();
*p = 0;
if (childPID >= 0)
{
printf("\nChild process has started\n");
if (childPID == 0)
{
localVar++;
globalVar++;
printf("Child process has found the following data %d,", *p);
*p = 70;
printf( " %d,", *p);
*p = 66;
printf(" %d,", *p);
*p = 51;
printf(" %d,", *p);
*p = 90;
printf(" %d in shared memory\n",*p);
printf("Child is existing\n\n");
}
}
}
And now I realize that I did it completely wrong but I have no idea how to fix that. I suppose I have to use shmget to create the shared memory, but then what? How do I store values in it?
If you find that you cannot help me with this or it is too long, please share sources where I can learn more about C programming in Linux, particularly regarding the usage of shared memory. Thank you in advance
It may be better to make it clear what you want to do first because as far as I read your code you call fork() twice in your code (once in main() function and once in ParentProcess() function)
So I write general solution for parent/child shared memory. There are several ways to achieve shared memory but this is one example which is modified version of the code here
How to use shared memory with Linux in C
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
void *create_shared_memory(size_t size)
{
int protection = PROT_READ | PROT_WRITE;
int visibility = MAP_SHARED | MAP_ANONYMOUS;
return mmap(NULL, size, protection, visibility, -1, 0);
}
int main()
{
// Allocate 4 ints
void *shmem = create_shared_memory(sizeof(int)*4);
if( shmem == NULL ){
fprintf(stderr, "Failed to create shared memory\n");
return -1;
}
// Initialize 4 ints
((int*)shmem)[0] = 10;
((int*)shmem)[1] = 100;
((int*)shmem)[2] = 1000;
((int*)shmem)[3] = 10000;
int pid = fork();
if (pid == 0)
{
// Print 4 ints in child
printf("Child reading int 0: %d\n", ((int*)shmem)[0]);
printf("Child reading int 1: %d\n", ((int*)shmem)[1]);
printf("Child reading int 2: %d\n", ((int*)shmem)[2]);
printf("Child reading int 3: %d\n", ((int*)shmem)[3]);
printf("Child end\n");
}
else
{
printf("Parent waiting for child ends...\n");
waitpid(pid, NULL, 0);
printf("Parent ends\n");
}
int ret = munmap(shmem, sizeof(int)*4);
if( ret != 0 ){
fprintf(stderr, "Failed to unmap shared memory\n");
return -1;
}
return 0;
}
I've written a small piece of c code which you might find helpful:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define NUM_INTS 5
int main(int argc, char *argv[])
{
key_t key = (key_t) 123456;
int shmgetrc, semgetrc;
struct shmid_ds ds;
int *shared_values;
int i;
struct sembuf sops[2];
int semid;
sops[0].sem_num = 0; /* Operate on semaphore 0 */
sops[0].sem_op = 0; /* Wait for value to equal 0 */
sops[0].sem_flg = 0;
sops[1].sem_num = 0; /* Operate on semaphore 0 */
sops[1].sem_op = 1; /* Increment value by one */
sops[1].sem_flg = 0;
/* create SHM segment */
shmgetrc = shmget(key, NUM_INTS * sizeof(int), IPC_CREAT | IPC_EXCL | 0x180);
if (shmgetrc < 0) {
perror("shmget failed...");
exit(1);
}
/* retrieve the address of the segment */
shared_values = (int *) shmat(shmgetrc, NULL, 0);
/* create a semaphore */
semgetrc = semget(key, 1, IPC_CREAT | IPC_EXCL | 0x180);
if (semgetrc < 0) {
perror("semget failed...");
exit(1);
}
/* lock the semaphore */
if (semop(semgetrc, sops, 2) == -1) {
perror("semop lock failed ...");
exit(1);
}
/* fill it with values */
for (i = 0; i < NUM_INTS; ++i) {
shared_values[i] = i;
}
/* unlock the semaphore */
sops[0].sem_op = -1;
if (semop(semgetrc, sops, 1) == -1) {
perror("semop release failed ...");
exit(1);
}
/* here something else could happen */
sleep(60);
/* lock the semaphore */
sops[0].sem_op = 0;
if (semop(semgetrc, sops, 2) == -1) {
perror("semop lock failed ...");
exit(1);
}
/* print values */
for (i = 0; i < NUM_INTS; ++i) {
printf("%d ", shared_values[i]);
}
printf("\n");
/* unlock the semaphore */
sops[0].sem_op = -1;
if (semop(semgetrc, sops, 1) == -1) {
perror("semop release failed ...");
exit(1);
}
/* remove the semaphore */
if (semctl(semgetrc, semgetrc, IPC_RMID) < 0) {
perror("semctl failed ...");
exit(1);
}
/* remove shm segment again */
if (shmctl(shmgetrc, IPC_RMID, &ds) < 0) {
perror("shmctl failed ...");
exit(1);
}
exit(0);
}
It was not my intention to write the most beautiful code ever written, just an example that shows:
how to create a shm segment
how to retrieve the address and to use it
how to remove it
Additionally, I've used a semaphore to protect the access.
Contrary to the other answer, I've used the ipc interface, not mmap().
I have a parent program which will fork the following child program and increment, display, decrement and display the variable 'test' (initially 0) 15 times. I tried to run it a lot of times and see what output I get after every few lines, however I'm not able to know how my 'test' variable is showing only zero, 15 times.
//Include required preprocessors
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#define SHARED_MEM 1024 //shared memory size
int main(void)
{
/* The child process' new program. This program replaces the parent's */
/* program when 'fork()' is called */
printf("Process[%d]: child in execution ... \n",getpid());
int MAX = 15;
int shmID, shmID2;
key_t key = 1234, key2 = 2345;
int *test, *counter;
shmID = shmget(key, SHARED_MEM, 0666);
printf("\nShmID: %d", shmID);
shmID2 = shmget(key2, SHARED_MEM, 0666);
printf("\nshmID2: %d", shmID2);
test = (int *) shmat(shmID, 0, 0);
counter = (int *) shmat(shmID2, 0, 0);
printf("\ntEST before assignment: %d", *test);
printf("\nCounter: %d", *counter);
*test = 0;
*counter = 1;
printf("\ntest: %d", *test);
printf("\nCounter%d", *counter);
printf("\nAlmost there...");
if (*counter == 1){
for(int i=0; i < MAX; i++){
printf("\MAX: %d", MAX);
printf("%d", *test);
*test++;
}
*counter++; //to enter second condition of second child process
printf("\nCounter: %d", counter);
}
else if(*counter == 2){
for(int j = 0; j < MAX; j++){
printf("%d", *test);
*test++;
}
*counter--;
}
sleep(1);
printf("Process[%d]: child terminating ... \n", getpid());
shmdt(test);
shmdt(counter);
return 0;
}
I can see several things.
Independently of how is code structured, I'd check if there's an error in shmget and shmat:
I'd change
shmID = shmget(key, SHARED_MEM, 0666)
shmID2 = shmget(key2, SHARED_MEM, 0666);
by
if ( (shmID = shmget(key, SHARED_MEM, 0666)) < 0)
{
perror("shmget");
exit(1);
}
if ( (shmID2 = shmget(key2, SHARED_MEM, 0666) < 0)
{
perror("shmat");
exit(1);
}
Note that you're creating SHM with 0666 privileges but without IPC_CREAT | IPC_EXCL.
I recommend you create first time with IPC_CREAT | IPC_EXCL | 0666 flags.
In the same way that 1st point, I'll check also problems with shmat:
See example for test. Should be the same for counter.
if ((test = (int *) shmat(shmID, 0, 0)) == -1)
{
perror("shmat");
exit(1);
}
You can check in cli if there's something wrong with shm, for instance, is already created, using command ipcs to check or ipcrm shm to delete and re-initialize:
ipcs shm | grep [your_shm_key or shmid]
I am working on a program that stores the variable Bank in shared memory and causes a race condition. My code compiles but it only prints the initial balance statements and not the resulting balance. Essentially, the program should be printing a balance other than 200 with the race condition and when the condition is fixed using semaphores, it should use different numbers to always print a balance of 200. What am I missing that could cause my program to get caught up after the first printf?
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <string.h>
//sem_t mutex; // semaphore global variable
struct {
int balance[2];
}
Bank = {{100, 100}};
//struct Bank *bank;
// routine for thread execution
void* MakeTransactions() {
key_t shmkey;
int shmid, seqid;
int seqnum = 5858;
int i, j, tmp1, tmp2, rint;
int *shmint1, *shmint2;
double dummy;
if ((shmkey=ftok(getenv("HOME"), seqnum))==(key_t)-1) {
perror("ERROR: ftok");
}
else if ((shmid=shmget(shmkey,sizeof(int)*2,0600|IPC_CREAT))==-1) {
perror("ERROR: shmget");
}
if ((shmint1=(int *)shmat(shmid,NULL,0600))==(int*)-1) {
perror("ERROR: shmalloc");
}
shmint2 = shmint1 + 1;
// wait on semaphore
//sem_wait(&mutex);
for (i=0; i < 100; i++) {
rint = (rand()%30)-15;
if (((tmp1= *shmint1)+rint) >=0 &&
((tmp2= *shmint2)-rint)>=0) {
//sem_wait(&mutex);
//bank->balance[0] = tmp1 + rint;
*shmint1 = tmp1 + rint;
//sem_post(&mutex);
usleep(5000);
for (j=0; j < rint*100; j++) {
dummy=2.345*8.765/1.234; // spend time on purpose
}
//sem_wait(&mutex);
//bank->balance[1] = tmp2 - rint;
*shmint2 = tmp2 - rint;
//sem_post(&mutex);
}
}
Bank.balance[0]= *shmint1;
Bank.balance[1]= *shmint2;
// increment value of semaphore
//sem_post(&mutex);
return NULL;
}
vint main(int argc, char **argv) {
key_t shmkey;
int shmid, seqid, seqnum;
int *shmint1, *shmint2;
int i;
// initialize semaphore
//sem_init(&mutex, 0, 1);
// shared memory
//bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if ((shmkey=ftok(getenv("HOME"), seqnum))==(key_t)-1) {
perror("ERROR: ftok");
}
else if ((shmid=shmget(shmkey,sizeof(int)*2,0600|IPC_CREAT))==-1) {
perror("ERROR: shmget");
}
if ((shmint1=(int *)shmat(shmid,NULL,0600))==(int*)-1) {
perror("ERROR: shmalloc");
}
shmint2 = shmint1 + 1;
memset((int*)shmint1,0,sizeof(int));
memset((int*)shmint2,0,sizeof(int));
/*//check if bank is not NULL
Bank.balance[0] = 100;
Bank.balance[1] = 100;
*/
*shmint1 = Bank.balance[0];
*shmint2 = Bank.balance[1];
pid_t pid;
srand(getpid());
printf("\nInit balances A:%d + B:%d ==> %d!\n",*shmint1,*shmint2,*shmint1 + *shmint2);
pid=fork();
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid == 0) {
MakeTransactions();
return 0;
}
else {
MakeTransactions();
wait(NULL);
return 0;
}
printf("Let's check the balances A:%d + B:%d ==> %d ?= 200\n\n",*shmint1,*shmint2,*shmint1 + *shmint2);
//sem_destroy(&mutex);
// deattach shared memory pointer
shmdt(shmint1);
shmctl(shmid, IPC_RMID, NULL);
// memory unmap struct
//munmap(bank, sizeof(struct Bank));
return 0;
}
The wait() method you're using, as it is described here, looks like it may result in undefined behaviour when parsing NULL; it uses the integer pointer as an indicator of process completion.
A memory location is shared by three processes. Each process independently tries to increase the content of the shared memory location from 1 to a certain value by increments of one. Process 1 has target of 100000, Process 2’s target is 200000 and the goal of 3 is 300000. When the program terminates, therefore, the shared memory variable will have a total of 600000 (i.e. this value will be output by whichever of the three processes finishes last). I am to protect the critical section using semaphores.
My problem is that I am having issues with the SETVAL for each process when initializing the semaphore. It keeps printing "Error detected in SETVAL" even though I have it set to 1. Correct sample output as well as my code is shown below:
Sample output
From Process 1: counter = 100000.
From Process 2: counter = 300000.
From Process 3: counter = 600000.
Child with ID 2412 has just exited.
Child with ID 2411 has just exited.
Child with ID 2413 has just exited.
End of Simulation.
/*ass1*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#define SEMKEY ((key_t) 400L)
// number of semaphores being created
#define NSEMS 2
/* change the key number */
#define SHMKEY ((key_t) 7890)
typedef struct
{
int value;
} shared_mem;
shared_mem *total;
//structure
int sem_id, sem_id2;
typedef union{
int val;
struct semid_ds *buf;
ushort *array;
} semunion;
static struct sembuf OP = {0,-1,0};
static struct sembuf OV = {0,1,0};
struct sembuf *P =&OP;
struct sembuf *V =&OV;
//function
int Pop()
{
int status;
status = semop(sem_id, P,1);
return status;
}
int Vop()
{
int status;
status = semop(sem_id, V,1);
return status;
}
/*----------------------------------------------------------------------*
* This function increases the value of shared variable "total"
* by one with target of 100000
*----------------------------------------------------------------------*/
void process1 ()
{
int k = 0;
while (k < 100000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process1 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* This function increases the vlaue of shared memory variable "total"
* by one with a target 200000
*----------------------------------------------------------------------*/
void process2 ()
{
int k = 0;
while (k < 200000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process2 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* This function increases the vlaue of shared memory variable "total"
* by one with a target 300000
*----------------------------------------------------------------------*/
void process3 ()
{
int k = 0;
while (k < 300000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process3 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* MAIN()
*----------------------------------------------------------------------*/
int main()
{
int shmid;
int pid1;
int pid2;
int pid3;
int ID;
int status;
char *shmadd;
shmadd = (char *) 0;
//semaphores
int semnum = 0;
int value, value1;
semunion semctl_arg;
semctl_arg.val =1;
/* Create semaphores */
sem_id = semget(SEMKEY, NSEMS, IPC_CREAT | 0666);
if(sem_id < 0)
printf("creating semaphore");
sem_id2 = semget(SEMKEY, NSEMS, IPC_CREAT | 0666);
if(sem_id2 < 0)
printf("creating semaphore");
/* Initialize semaphore */
value1 =semctl(sem_id, semnum, SETVAL, semctl_arg);
value =semctl(sem_id, semnum, GETVAL, semctl_arg);
if (value < 1)
printf("Eror detected in SETVAL");
/* 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();
waitpid(pid1, NULL, 0 );
waitpid(pid2, NULL, 0 );
waitpid(pid3, NULL, 0 );
if ((pid1 != 0) && (pid2 != 0) && (pid3 != 0))
{
waitpid(pid1);
printf("Child with ID %d has just exited.\n", pid1);
waitpid(pid2);
printf("Child with ID %d has just exited.\n", pid2);
waitpid(pid3);
printf("Child with ID %d has just exited.\n", pid3);
if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1)
{
perror ("shmctl");
exit (-1);
}
printf ("\t\t End of Program\n");
/* De-allocate semaphore */
semctl_arg.val = 0;
status =semctl(sem_id, 0, IPC_RMID, semctl_arg);
if( status < 0)
printf("Error in removing the semaphore.\n");
}
}
Some basics - IPCs last longer than the process so as has been mentioned use ipcs and ipcrm to delete pre-existing ipcs between runs. Make sure you delete the ipcs after execution
waitpid(pid1, NULL, 0 );
waitpid(pid2, NULL, 0 );
waitpid(pid3, NULL, 0 );
This section is going to be run for the children - they probably shouldn't.
total->value = total->value + 1;
Is not IPC safe, so different results may occur (proc1 may overwrite proc2's increment).