Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите найти ошибку в программе 
:(
    Опции темы
Flashdown
Дата 6.6.2006, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 85
Регистрация: 27.5.2006
Где: Москва

Репутация: нет
Всего: нет



Имеется следующая задача:
Один процесс записывает случайные числа через случайные промежутки времени в разделяемый сегмент памяти , а вторая программа их оттуда считывает , тоже через случ. промежутки времени.
Всё работает, за исключением того что вторая программа выводит одни нули вместо чисел...

Вот код:


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;  
}



помогите найти ошибку!!! 
PM MAIL ICQ   Вверх
GrayCardinal
Дата 7.6.2006, 04:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


Профиль
Группа: Завсегдатай
Сообщений: 3039
Регистрация: 9.11.2003

Репутация: 8
Всего: 58



М-дя. И как тут ошибку искать. Сделай, плиз, вот что :
1. Удали нафиг все комментарии. Их лучше отдельным постом запость.
2. K&R рулит ! Т.е. "{" и if (else if) в _одной строчке_ :
if (true) {
 printf ("OK");
}
Я так привык что не на K&R уже смотреть не могу.
 


--------------------
PM MAIL WWW   Вверх
GrayCardinal
Дата 7.6.2006, 04:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


Профиль
Группа: Завсегдатай
Сообщений: 3039
Регистрация: 9.11.2003

Репутация: 8
Всего: 58



Угу. Так вот. С ftok лично у меня просто сообщает что не может создать ключ. И еще

reader.c
Цитата

printf("Readed: %u\n", g_mem[get_state() - 1]); // Считываем значение из буфера.


writer.c
Цитата

v = g_mem[1024-get_state()-1] = get_rand(65535); 

Там в квадратных скобках смещения просто разные. И даже если хочется пользовать семафор как счетчик, то только не так. Ибо get_state () при первом запуске есть -1. Результат сам посчитай.

Цитата

 while (get_state() > 10) sleep(1)

И (get_state () > 10) не лучший способ проверять количество данных в буфере. Наверно стоит отделить кусок области общей памяти и добавить туда все необохдимые переменные. Пускай даже в данном случае она одна.
 


--------------------
PM MAIL WWW   Вверх
Flashdown
Дата 7.6.2006, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 85
Регистрация: 27.5.2006
Где: Москва

Репутация: нет
Всего: нет



ну с ftok это понятно что там долны быть одинаковые значения первого параметра...
попробую проверить что Вы посоветовали... 
PM MAIL ICQ   Вверх
GrayCardinal
Дата 7.6.2006, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


Профиль
Группа: Завсегдатай
Сообщений: 3039
Регистрация: 9.11.2003

Репутация: 8
Всего: 58



Цитата

 Вы

Я пацан. Мне 0x14 лет. Просьба учитывать это smile 


--------------------
PM MAIL WWW   Вверх
bilbobagginz
Дата 8.6.2006, 07:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Naughtius Maximus
****


Профиль
Группа: Экс. модератор
Сообщений: 8813
Регистрация: 2.3.2004
Где: Israel

Репутация: 4
Всего: 317



Кстати, об К & R, можно пропустить весь этот код через:
indent -kr *.c

и узришь, как код Си должен выглядеть с точки зрения индентации.

 


--------------------
Я ещё не демон. Я только учусь.
PM WWW   Вверх
GrayCardinal
Дата 8.6.2006, 07:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


Профиль
Группа: Завсегдатай
Сообщений: 3039
Регистрация: 9.11.2003

Репутация: 8
Всего: 58



bilbobagginz
Не поможет. Меня проняло только когда в реадмешке по стилю ядра прочитал
1. K&R is good
2. K&R is good
А когда через indent только иллюзия создается правильно написанного кода. А чужие программы прогонять так не помогает - проверено. Если у человека 
#ifdef
через строчку да комментарии после каждого слова, это все равно попа smile 


--------------------
PM MAIL WWW   Вверх
bilbobagginz
Дата 8.6.2006, 08:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Naughtius Maximus
****


Профиль
Группа: Экс. модератор
Сообщений: 8813
Регистрация: 2.3.2004
Где: Israel

Репутация: 4
Всего: 317



Кстати, об К & R, можно пропустить весь этот код через: indent -kr пропустить.

 


--------------------
Я ещё не демон. Я только учусь.
PM WWW   Вверх
Pete
Дата 11.6.2006, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 318
Регистрация: 5.1.2006
Где: Москва

Репутация: нет
Всего: 12



Цитата(GrayCardinal @  7.6.2006,  05:57 Найти цитируемый пост)
С ftok лично у меня просто сообщает что не может создать ключ.

Хм.. С чего бы это? Может, на /key прав нет (или его вообще нет)? smile  


--------------------
Совет учиться на ошибках других бесполезен; научиться чему-либо можно только на собственных ошибках. (Бернард Шоу)
Не откладывай на завтра то, что можешь сделать сегодня. (Пословица)
А теперь выпишем точное значение числа пи... (Препод)
Жахни, Пендальф! © Гоблин
PM   Вверх
sikroz
Дата 20.6.2006, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 7.12.2005

Репутация: нет
Всего: нет



20d лет пацану - учтите 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0801 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.