Here is a proof-of-concept of how it can be done:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <assert.h>
typedef void (*sighandler_t)(int);
#define SHM_SIZE 8 /* size of shared memory: enough for two 32 bit integers */
volatile int cancontinue = 0;
void halt(char *err) { perror(err); exit(1); }
void handler(int signum) { assert(signum == SIGUSR1); cancontinue = 1; }
int main(void)
{
key_t key;
int id;
int *data;
pid_t otherpid;
printf("Hi, I am the %s process and my pid is %d\n",
#ifdef PRODUCER_MODE
"writer"
#else
"reader"
#endif
, getpid());
printf("Please give me the pid of the other process: ");
scanf("%d", &otherpid);
// get a pointer to the shared memory
if ((key = ftok("test_concur.c", 'R')) == -1) halt("ftok");
if ((id = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) halt("shmget");
if ((data = shmat(id, (void *)0, 0)) == (int *)(-1)) halt("shmat");
sighandler_t oldhandler = signal(SIGUSR1, handler);
while (1) {
#ifdef PRODUCER_MODE
printf("Enter two integers: ");
scanf("%d %d", data, data + 1);
printf("Sending signal to consumer process\n");
kill(otherpid, SIGUSR1);
printf("Waiting for consumer to allow me to continue\n");
while (!cancontinue);
cancontinue = 0;
if (*data + *(data + 1) == 0) { printf("Sum was 0, exiting...\n"); break; }
#else
printf("Waiting for producer to signal me to do my work\n");
while (!cancontinue);
cancontinue = 0;
printf("Received signal\n");
printf("Pretending to do a long calculation\n");
sleep(1);
int sum = *data + *(data + 1);
printf("The sum of the ints in the shared memory is %d\n", sum);
printf("Signaling producer I'm done\n");
kill(otherpid, SIGUSR1);
if (sum == 0) break;
#endif
}
signal(SIGUSR1, oldhandler);
/* detach from the segment: */
if (shmdt(data) == -1) {
perror("shmdt");
exit(1);
}
// don't forget to remove the shared segment from the command line with
// #sudo ipcs
// ... and look for the key of the shared memory segment
// #ipcrm -m <key>
return 0;
}
The above program is actually two programs, a consumer and a producer,
depending on how you compile it.
You compile the producer by making sure that the PRODUCER_MODE macro
is defined:
# gcc -Wall -DPRODUCER_MODE -o producer test_concur.c
The consumer is compiled without defining the PRODUCER_MODE macro:
# gcc -Wall -o consumer test_concur.c
The consumer and producer share some global memory (8 bytes pointed to by data); the producer's role is to read two 32-bit integers from stdin and write them to the shared
memory. The consumer reads integers from the shared memory and
computes their sum.
After writing the data to shared memory, the producer signals to the
consumer (via SIGUSR1) that it may begin the computation. After the
computation is done, the consumer signals to the producer (via SIGUSR1
again) that it may continue.
Both processes stop when the sum is 0.
Currently, each program begins by outputing its pid and reading from
stdin the other program's pid. This should probably :D be replaced by
something smarter, depending on exactly what you are doing.
Also, in practice, the "while (!cancontinue);"-like loops should be
replaced by something else :D, like semaphores. At least you should do
a small sleep inside each loop. Also, I think you do not truly need shared memory to solve this problem, it should be doable using message-passing techniques.
Here is an example session, showed in parallel:
# ./producer # ./consumer
Hi, I am the writer process and my pid is 11357 Hi, I am the reader process and my pid is 11358
Please give me the pid of the other process: 11358 Please give me the pid of the other process: 11357
Enter two integers: 2 Waiting for producer to signal me to do my work
3
Sending signal to consumer process Received signal
Waiting for consumer to allow me to continue Pretending to do a long calculation
... some times passes ...
The sum of the ints in the shared memory is 5
Signaling producer I'm done
Enter two integers: 0 Waiting for producer to signal me to do my work
0
Sending signal to consumer process Received signal
Waiting for consumer to allow me to continue Pretending to do a long calculation
... some times passes ...
The sum of the ints in the shared memory is 0
Signaling producer I'm done
Sum was 0, exiting...
I hope this helps. (when you run the programs, make sure the file test_concur.c exists (it's used to establish the shared memory key (ftok function call)))