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

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

04.06.2018, 21:02. Показов 2421. Ответов 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
533 / 274 / 220
Регистрация: 14.11.2016
Сообщений: 1,054
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
Ответ Создать тему
Новые блоги и статьи
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
Контроль уникальности заводского номера - вариант №2
Maks 24.03.2026
В отличие от предыдущего варианта добавлено прерывание циклов, также добавлены новые переменные для сохранения контекста ошибки перед прерыванием цикла: Процедура ПередЗаписью(Отказ, РежимЗаписи,. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера - вариант №1
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере нетипового документа выдачи шин для спецтехники с табличной частью, разработанного в конфигурации КА2. Данные берутся из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru