Имеется следующая задача: Один процесс записывает случайные числа через случайные промежутки времени в разделяемый сегмент памяти , а вторая программа их оттуда считывает , тоже через случ. промежутки времени. Всё работает, за исключением того что вторая программа выводит одни нули вместо чисел...
Вот код:
HEADER.H
| Код | #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <signal.h>
/* Операция инициализации семафора. Все sembuf'ы имеют следующую структуру: номер семафора, значение, флаги
Номер семафора у нас всегда 0, т. к. наш набор семафоров состоит только из одного семафора
Второй параметр интерпретируется слудющим образом: 1. Если он меньше нуля, то процесс, вызововший функцию semop ожидает, пока значение семафора не станет большим или равным абсолютной величине параметра. Затем аб-солютная величина параметра вычитается из значения семафора. 2. Если он равен нулю, процесс ожидает, пока семафор не обнулится. 3. Если он больше нуля, то то текущее значение семафора увеличивается на згачение параметра.
В конкретной задаче семафор будет хранить количество занятых ячеек памяти. */
// Текущее значения семафора делаем равным нулю. Т. е. изначально у нас пустой буфер. static struct sembuf sem_init = {0, 0, 0};
// Вызывается при записи в буфер. Т. е. кол-во занятых ячеек увеличивается на 1. static struct sembuf sem_write = {0, 1, 0};
// Вызывается при чтении из буфера. Т. е. ждём, пока в буфере не будет > 1 элемента, // А затем уменьшаем кол-во на 1. static struct sembuf sem_read = {0, -1, 0};
static int g_sem = -1; static int g_shm = -1; static int* g_mem = 0;
int get_state() // Получаем текущее значение семафора { return semctl(g_sem, 0, GETVAL, 0); }
void init_rand() { long t; time(&t); srand(t); // Установка начального значения генератора случайных чисел в текущее системное время }
int get_rand(int max) // генерирует случайные числа от 0 до max включительно { return rand() % (max + 1); }
void pr_end() { semctl(g_sem, 0, IPC_RMID, 0); // Удаление семафора if (g_mem > 0) shmdt(g_mem); // Если разделяемый сегмент памяти открыт, то удаляем также exit(0); }
int sig_handler() { printf("Ctrl+C: Terminate\n"); pr_end(); }
|
WRITER.C
| Код | #include "header.h"
// Программа пишет числа в разделяемую память. int main() { key_t key; unsigned short v; // Перехватываем нажатие Ctrl+C, чтобы при нажати закрывать декскрипторы семафоров и разделяемой памяти, // иначе семафоры будут сохранятьсяс при выключении проги и всё будет глючить. // signal(SIGINT, &sig_handler);
init_rand(); // Инициализация rand текущим временем key = ftok(".", 'L'); // Создаём уникальный ключ с именем сессии 'L' if (key < 0) { printf("Can not create key!\n"); return 0; } // Создаём набор семафоров из одного семафора g_sem = semget(key, 1, 0666 | IPC_CREAT); if (g_sem < 0) { printf("Can not create semaphore (%d)!\n", g_sem); return 0; } // Задаём значение семафора (см. описание sem_init) /* Функция semop принимает 3 параметра: 1. Дескриптор набора семафоров 2. Указатель на массив sembuf - это действия, которые мы хотим совершить над семафором. 3. Количество элементов в массиве sembuf */ if (semop(g_sem, &sem_init, 1) < 0) { printf("Bad semop action!\n"); pr_end(); }
printf("Creation completed. Semaphore free number: %d\n", get_state()); // Создаём дескриптор разделяемой памяти. размером 2048 байт g_shm = shmget(key, sizeof(unsigned short) * 1024, 0666 | IPC_CREAT); if (g_shm < 0) { printf("Share memory: error!\n"); pr_end(); } // Подключаем к сегмену раздяляемой памяти виртуальную память /* Функция принимает 3 параметра: 1. Дескриптор разделяемой памяти 2. Адрес, который желательно получить. В случае 0 - автоматический 3. Права доступа (типа чтение, запись, выполнение) */ g_mem = (int*) shmat(g_shm, 0, 0); if (g_mem <= 0) { printf("Can not attach memory to virtual space\n"); pr_end(); } printf("Memory allocated\n"); /***********************************************************************************************************/
// См. описание sem_write while(semop(g_sem, &sem_write, 1) >= 0) { while (get_state() > 10) sleep(1);// пока в буфере больше 10 эл-ов ничего ни пишем. sleep(get_rand(1)); // это 'запись через случайные интервалы времени' v = g_mem[1024-get_state()-1] = get_rand(65535); // Записываем случайное значение в буфер printf("g_mem[%d] = %u\n", get_state() - 1, v); }
/***********************************************************************************************************/ semctl(g_sem, 0, IPC_RMID, 0); // закрытие семафора shmdt(g_mem); // отделение виртуальной памяти printf("Program END\n"); return 0; }
|
reader.c
| Код | #include "header.h"
// Программа, считывающая из буфера int main() { key_t key; unsigned short v; int g_sem; printf("Program started\n"); signal(SIGINT, &sig_handler); init_rand(); key = ftok("/key", 'L'); if (key < 0) { printf("Can not create key!\n"); return 0; } printf("Key %d created\n",key); g_sem = semget(key, 1, 0666 | IPC_CREAT); if (g_sem < 0) { printf("Can not create semaphore (%d)!\n", g_sem); return 0; } printf("Semaphore created\n"); /* if (semop(g_sem, &sem_init, 1) < 0) { printf("Bad semop action!\n"); pr_end(); } */ printf("Semaphore initiated\n");
printf("Creation completed. Semaphore free number: %d\n", get_state()); g_shm = shmget(key, sizeof(unsigned short) * 1024, 0666 | IPC_CREAT); if (g_shm < 0) { printf("Share memory: error!\n"); pr_end(); } printf("Memory descriptor selected\n"); g_mem = (int*) shmat(g_shm, 0, 0); if (g_mem <= 0) { printf("Can not attach memory to virtual space\n"); pr_end(); } printf("Memory attached to virtual space\n");
// В тексте, программы который, выше делается абсолютно тоже, что и в 6.c /* Сначала запускается программа 6, а потом 6.2 В результате 6.2 и 6 владеют одними и теми же семафором и разделяемой памятью, так как уникальный ключ создавался с одинаковыми параметрами (т. е. в одной папке и содним и тем же именем сессии). */
/***********************************************************************************************************/
while(semop(g_sem, &sem_read, 1) >= 0) { printf("Readed: %u\n", g_mem[get_state() - 1]); // Считываем значение из буфера. sleep(get_rand(1)); }
/***********************************************************************************************************/ semctl(g_sem, 0, IPC_RMID, 0); // закрытие семафора shmdt(g_mem); // отделение виртуальной памяти printf("Program END\n"); return 0; }
|
помогите найти ошибку!!! |