Я реализую потребитель-производитель с помощью 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 бит ядра
Благодарю!
Когда вы создаете свои новые "потоки", вы говорите им, чтобы они делили память с родительским процессом. Однако есть две большие проблемы:
Обе эти вещи приводят к неопределенному поведению.
Первая проблема может быть решена с помощью двух стеков, по одному для каждого потока. Вторая проблема может быть решена родительским процессом, ожидающим выхода детей.
errno
если предыдущая функция фактически не завершилась, если только ошибка действительно не произошла, состояниеerrno
не определено. Также, если произошла ошибка, вам нужно немедленно проверитьerrno
, вызов другой функции может изменить значение.