Producer-Consumer реализован с помощью clone2 и семафоров в c ++

0

Я реализую потребитель-производитель с помощью c++ с использованием clone2() и семафоров, но он имеет неожиданное поведение.

Вот код:

#include <iostream>
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <mutex>
#include <sys/wait.h>

using namespace std;

sem_t empty, full;
mutex mutexSem;

int var = 1;
int items[10];
int in = 0;
int out = 0;

static int produce(void * arg) {

  while (true) {
      sem_wait(&empty);
      mutexSem.lock();
      cout << "produce position: " << in << endl;
      items[in] = var++;
      in = (in+1) % 10;
      mutexSem.unlock();
      sem_post(&full);
    }

  }

  static int consume(void *arg) {

    while (true) {
      sem_wait(&full);
      mutexSem.lock();
      cout << "consume position: " << out << endl;
      items[out] = 0;
      out = (out + 1 ) % 10;
      mutexSem.unlock();
      sem_post(&empty);
    }

  }

int
main(int argc, char *argv[]) {

  int emptyResponse = sem_init(&empty, 0, 10);
  int fullResponse = sem_init(&full, 0, 0);
  void ** child_stack;

  child_stack = (void **) malloc(16384) + 16384 / sizeof(*child_stack);

  if (errno != 0 || emptyResponse != 0
     || fullResponse != 0) {
    cout << "errNo->" << errno << endl;
  }

  clone(produce, child_stack, CLONE_VM | CLONE_FILES , NULL);
  sleep(4);
  clone(consume, child_stack, CLONE_VM | CLONE_FILES, NULL);

  return 0;

}

Я компилирую код как

g++ -std = c++ 11 clone2.cpp -o clone2 -lpthread

И каждый раз, когда я запускаю код, он производит другой результат. Я хочу создать бесконечного производителя/потребителя, который каждый раз, когда будет создан элемент, тогда я буду потребляться. Я не знаю, почему после производства 10 предметов, тогда он потребляет 10 предметов и процесс заканчивается. Я также не знаю, почему я должен использовать сон (anyNumber) между двумя потоками, хотя он ничего не сделает. Кто-то может сказать мне pleae, если FLAGS, которые я устанавливаю, в порядке, и как работает этот клон.

Это пример вывода:

производить: 0

производить: 1

производить: 2

производить: 3

производить: 4

производить: 5

производить: 6

производить: 7

производить: 8

производить: 9

употреблять: 0

потреблять: 1

потреблять: 2

потреблять: 3

потреблять: 1515067019

потреблять: 5

потреблять: 6

потреблять: 7

потреблять: 8

потреблять: 9

Иногда это похоже на то, что иногда возникает ошибка сегментации, иногда просто не печатается ни один номер, поэтому он будет выглядеть как

потребляют:

потреблять: 5

И так далее...

ПРИМЕЧАНИЕ. ОБЯЗАТЕЛЬНО использовать clone2(), и я использую ubuntu 14.04 LTS, Intel i7 64 бит ядра

Благодарю!

  • 0
    Несвязанный совет: не проверяйте errno если предыдущая функция фактически не завершилась, если только ошибка действительно не произошла, состояние errno не определено. Также, если произошла ошибка, вам нужно немедленно проверить errno , вызов другой функции может изменить значение.
Теги:
multithreading
mutex
clone
producer-consumer

1 ответ

0
Лучший ответ

Когда вы создаете свои новые "потоки", вы говорите им, чтобы они делили память с родительским процессом. Однако есть две большие проблемы:

  1. Стек, который вы создаете для детей, также используется совместно, так что обе "потоки" будут иметь один и тот же стек.
  2. Родительский процесс завершает работу, и я не уверен, что происходит с выделенной разделяемой памятью, но может быть выпущен.

Обе эти вещи приводят к неопределенному поведению.

Первая проблема может быть решена с помощью двух стеков, по одному для каждого потока. Вторая проблема может быть решена родительским процессом, ожидающим выхода детей.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню