Вот подтверждение концепции того, как это можно сделать:
#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;
}
Вышеупомянутая программа на самом деле две программы, потребитель и производитель,
в зависимости от того, как вы его скомпилируете.
Вы компилируете производителя, убедившись, что макрос PRODUCER_MODE
определяется:
# gcc -Wall -DPRODUCER_MODE -o producer test_concur.c
Потребитель компилируется без определения макроса PRODUCER_MODE:
# gcc -Wall -o consumer test_concur.c
Потребитель и производитель имеют общую глобальную память (8 байтов, на которые указывают данные); роль продюсера состоит в том, чтобы прочитать два 32-битных целых числа из стандартного ввода и записать их в общий
объем памяти. Потребитель читает целые числа из общей памяти и
вычисляет их сумму.
После записи данных в общую память, производитель подает сигнал
потребителю (через SIGUSR1), чтобы он мог начать вычисления. После
вычисление сделано, потребитель сигнализирует производителю (через SIGUSR1
еще раз), что это может продолжаться.
Оба процесса останавливаются, когда сумма равна 0.
В настоящее время каждая программа начинает с вывода pid и чтения из
стандартный пид другой программы. Это должно быть вероятно: D быть заменено на
что-то умнее, в зависимости от того, что именно вы делаете.
Кроме того, на практике петли типа while (! Cancontinue);) должны быть
заменено на что-то еще: D, как семафоры. По крайней мере, вы должны сделать
маленький сон внутри каждой петли. Кроме того, я думаю, что для решения этой проблемы вам на самом деле не нужна общая память, это можно сделать с помощью методов передачи сообщений.
Вот пример сеанса, показанного параллельно:
# ./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...
Надеюсь, это поможет. (при запуске программ убедитесь, что существует файл test_concur.c (он используется для установки ключа общей памяти (вызов функции ftok)))