Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
 Аватар для anapshy
531 / 272 / 220
Регистрация: 14.11.2016
Сообщений: 1,052

Семафоры (как заставить клиента ждать?)

04.06.2018, 21:02. Показов 2371. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
1 программа (сервер): создаем разделяемую память и записываем 12345.6789
2 программа (клиент): подключается к разделяемой памяти, выводит число, отключается от разделяемой памяти.

Без семафоров всё работает отлично (запускам программу #1 потом #2 и всё ОК), но теперь нужно добавить ещё пару условий:
1) Программа #1 помещает число в раздел. память и устанавливает семафор
2) Программа #2 ждёт когда установится семафор и потом выводит число записанное сервером в разделяемую память.
Прог-а должна находится в режиме ожидания пока не изменится значение семафора.

Когда идет гонка между процессами созданными fork'ами в одной программе за разделяемыми данными - там всё понятно и легко организуется.
Но когда процессы запускаются в ручную, то как-то уже трудновато. Пытался организовать подобное с клиентом, что он не может прочитать пока сервер записывает данные, но безуспешно.

Правильно ли сделан первый пункт?
Как заставить клиента ждать (нужно допилить код), ибо даже не понятно как присоединиться к семафору и вообще возможно ли?!

СЕРВЕР
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <stdio.h>
#include <unistd.h>
#include "interproccomm.h" // Межпроцессорное взаимодействие (shm.h, sem.h и ф-и SharedMemory...)
 
#define SHM_KEY 3333
#define SEM_KEY 4444
 
union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};
 
int main(int argc, char const *argv[])
{
    union semun arg;
    struct sembuf lockRes = {0, -1, 0}; // блокировка ресурка
    struct sembuf relRes = {0, 1, 0}; // освобождение ресурса
    // Создаем семафор для синхронизации работы с разделяемой памятью
    int semid = semget(SEM_KEY, 1, IPC_CREAT | 0666);
    // Устанавливается в семафоре #0 (Контроллер ресурса) значение "1"
    arg.val = 1;
    semctl(semid, 0, SETVAL, arg);
 
    int shmid = SharedMemoryCreate(SHM_KEY, sizeof(long double));
    long double *shm = SharedMemoryAttach(shmid);
 
    // Заблокируем разделяемую память
    if ((semop(semid, &lockRes, 1)) == -1)
    {
        error_msg("Lock failed!", 555); // error_msg(сообщение_об_ошибке, код_ошибки);
    }
 
    *shm = 12345.6789;
    
    // Освободим разделяемую память
    if ((semop(semid, &relRes, 1)) == -1)
    {
        error_msg("Unlock failed!", 666);
    }
 
    // Даем клиенту время воспользоваться данными из разделяемой памяти до их удаления
    fgetc(stdin);
    SharedMemoryDisconnect(shm);
    SharedMemoryDelete(shmid);
    
    // Удалим семафор
    if (semctl(semid, 0, IPC_RMID) < 0)
    {
        error_msg("Can't delete semaphore!", 777);
    }
    return 0;
}
КЛИЕНТ (без семафоров)
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <unistd.h>
#include "interproccomm.h"
 
#define SHM_KEY 3333
#define SEM_KEY 4444
 
int main(int argc, char const *argv[])
{
    int shmid = SharedMemoryConnect(SHM_KEY, sizeof(long double));
    long double *shm = SharedMemoryAttach(shmid);
 
    fprintf(stdout, "Resutl: %.11Lf\n", *shm);
 
    SharedMemoryDisconnect(shm);
    fgetc(stdin);
    return 0;
}


Добавлено через 3 минуты
P.s. На ф-и SharedMemory... не обращайте внимание. Внутри них обычное создание, удаление, присоединение к сущ-ей SM, отсоединение и "атач". Они работают правильно.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.06.2018, 21:02
Ответы с готовыми решениями:

Как заставить цикл ждать ?
Есть массив времён которые обрабатываются в цикле. В теле цикла запускается таймер который по окончании работы вызывает прерывание....

Как заставить поток ждать
Есть программа, в которую пользователь может залогиниться, за залогинивание отвечает отдельный поток, который обращается к серверу и...

Как заставить браузер не ждать ответа?
Суть такова... Принимаю POST, а теперь браузер надо послать на три веселые буквы и выполнять дальше код! В данный момент у меня принимается...

2
923 / 639 / 198
Регистрация: 08.09.2013
Сообщений: 1,693
05.06.2018, 12:51
Цитата Сообщение от anapshy Посмотреть сообщение
Как заставить клиента ждать
Сервер
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <semaphore.h>
 
#define SHM_NAME  "/shm_name_"
#define SEM_NAME  "/sem_name_"
 
int main (int ac, char *av[])
{
  sem_t *sem = sem_open (SEM_NAME, O_CREAT | O_RDWR, 0660, 0);
  if (sem == SEM_FAILED) err (1, "Create Semaphore.");
 
  int shm = shm_open (SHM_NAME, O_CREAT | O_RDWR, 0660);
  if (shm == -1) err (1, "Create Share Memory Object.");
  ftruncate(shm, sizeof (double));
 
  double *value = mmap (0, sizeof (double), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
  if (value == MAP_FAILED) err (1, "Memory Mapping.");
 
  *value = 12345.6789;
  sem_post (sem);
  getchar();
 
  munmap (value, sizeof (double));
  close (shm);
  shm_unlink (SHM_NAME);
  sem_close (sem);
  sem_unlink (SEM_NAME);
  return 0;
}
Клиент
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <semaphore.h>
 
#define SHM_NAME  "/shm_name_"
#define SEM_NAME  "/sem_name_"
 
 
int main (int ac, char *av[])
{
  sem_t *sem = sem_open (SEM_NAME, O_RDWR);
  if (sem == SEM_FAILED) err (1, "Open Semaphore.");
 
  int shm = shm_open (SHM_NAME, O_RDONLY, 0);
  if (shm == -1) err (1, "Open Share Memory Object.");
 
  double *value = mmap (0, sizeof (double), PROT_READ, MAP_SHARED, shm, 0);
  if (value == MAP_FAILED) err (1, "Memory Mapping.");
 
  sem_wait (sem);
  printf ("%lf\n", *value);
  sem_post (sem);
 
  munmap (value, sizeof (double));
  close (shm);
  sem_close (sem);
 
  return 0;
}
Добавлено через 11 минут
PS. Чтобы убедиться, что клиент ждет, в сервере перед поднятием семафора sem_post() можно прописать ождание sleep().
1
 Аватар для anapshy
531 / 272 / 220
Регистрация: 14.11.2016
Сообщений: 1,052
05.06.2018, 13:27  [ТС]
gng, спасибо, но я уже разобрался вчера.
Просто подключался уже к существующему
C
1
int semid = semget(SEM_KEY, 0, 0666);
И не удалял его по завершению работы с ним. А Lock и Unlock делал подобно серверному.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include "interproccomm.h" // Межпроцессорное взаимодействие (shm.h, sem.h и ф-и SharedMemory...)
 
#define VAR_T long double // тип переменной
#define SHM_KEY 3333
#define SEM_KEY 4444
#define SIZE 1
 
union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};
 
struct sembuf lockRes = {0, -1, 0}; // блокировка ресурка
struct sembuf relRes = {0, 1, 0}; // освобождение ресурса
 
int main(int argc, char const *argv[])
{
    fputs("=====[ Server's try creating ]=====\n", stdout);
    union semun arg;
    // Создаем семафор для синхронизации работы с разделяемой памятью
    int semid = SemaphoreCreate(SEM_KEY, 1);
    // Устанавливается в семафоре #0 (Контроллер ресурса) значение "1"
    arg.val = 1;
    semctl(semid, 0, SETVAL, arg);
    fputs(" > Semaphore created.\n", stdout);
    // Создадим разделяемую память
    int shmid = SharedMemoryCreate(SHM_KEY, SIZE * sizeof(VAR_T));
    VAR_T *shm = SharedMemoryAttach(shmid);
    fputs(" > Shared Memory created.\n", stdout);
    fputs("=====[ Server created ]=====\n\n", stdout);
    fputs("Enter any key for start...\n", stdout);
    fgetc(stdin);
 
    // Заблокируем разделяемую память
    if ((semop(semid, &lockRes, 1)) == -1)
        error_msg("Lock failed!", 555);
    else
        fputs("> Semaphore lock\n", stdout);
    sleep(10);
    // Запишем данные в разделяемую память
    *shm = 666.666;
    // Освободим разделяемую память
    if ((semop(semid, &relRes, 1)) == -1)
        error_msg("Unlock failed!", 666);
    else 
        fputs("> Semaphore unlock\n", stdout);
    
    fputs("\n=====[ Server try delete ]=====\n", stdout);
    fputs("Enter any key for delete...\n", stdout);
    fgetc(stdin);
    SharedMemoryDisconnect(shm);
    fputs(" > Shared Memory disconnected.\n", stdout);
    SharedMemoryDelete(shmid);
    fputs(" > Shared Memory deleted.\n", stdout);
    SemaphoreDelete(semid);
    fputs(" > Semaphore deleted.\n", stdout);
    fputs("=====[ Server deleted ]=====\n", stdout);
    return 0;
}
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include "interproccomm.h"
 
#define VAR_T long double // Your type varivable
#define SHM_KEY 3333
#define SEM_KEY 4444
#define SIZE 1
 
union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};
 
struct sembuf lockRes = {0, -1, 0}; // блокировка ресурка
struct sembuf relRes = {0, 1, 0}; // освобождение ресурса
 
int main(int argc, char const *argv[])
{
    fputs("=====[ Client try connect ]=====\n", stdout);
    // Подключаемся к существующему семафору для синхронизации работы с разделяемой памятью
    int semid = SemaphoreConnect(SEM_KEY);
    fputs(" > Semaphore connected.\n", stdout);
    int shmid = SharedMemoryConnect(SHM_KEY, SIZE * sizeof(VAR_T));
    VAR_T *shm = SharedMemoryAttach(shmid);
    fputs(" > Shared Memory connected.\n", stdout);
    fputs("=====[ Client connected ]=====\n\n", stdout);
    fputs("Enter any key for start...\n", stdout);
    fgetc(stdin);
 
    fputs(" Waiting for access to data...\n\n", stdout);
    // Заблокируем разделяемую память
    if ((semop(semid, &lockRes, 1)) == -1)
        error_msg("Lock failed!", 555);
    else
        fputs("-----( Lock )-----\n", stdout);
    // Выведем значение из разделяемого сегмента памяти
    fprintf(stdout, " Data from Shared Memory: %.11Lf\n", *shm);
    // Освободим разделяемую память
    if ((semop(semid, &relRes, 1)) == -1)
        error_msg("Unlock failed!", 666);
    else 
        fputs("-----( Unlock )-----\n", stdout);
    
    fputs("\n=====[ Client try disconnect ]=====\n", stdout);
    fputs("Enter any key for disconnect...\n", stdout);
    fgetc(stdin);
    SharedMemoryDisconnect(shm);
    fputs(" > Shared Memory disconnected.\n", stdout);
    fputs("=====[ Client disconnected ]=====\n", stdout);
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.06.2018, 13:27
Помогаю со студенческими работами здесь

Как заставить сервера ждать? Java Sockets
Как после отключение последнего клиента заставить сервера ждать новых подключений и не отключиться?

Как заставить программу не ждать завершения команды
У меня такая проблема: надо, чтобы MessageBox открывался, и через секунду закрывался. Если просто написать MessageBox(), то программа...

Как заставить поток ждать в некоторых ситуациях
Есть такой сценарий приложения: Приложение до запуска TCP кеширует данные из MySQL в std::vector, далее запускается TCP и ожидаются...

Как заставить прогу на с++ ждать новые записи из БД
Нужно чтобы прога на с++ ждала новых записей в БД и если они поступят производила с ними кое какие действия Вопрос в том как именно...

Как заставить машину ждать перед очередным выполнением цикла?
есть код#include &lt;stdio.h&gt; #include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; int main(int argc, char *argv) { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru