【问题标题】:Producer-Consumer implemented with clone2 and semaphores in c++生产者-消费者用 C++ 中的 clone2 和信号量实现
【发布时间】:2014-10-11 22:32:50
【问题描述】:

我正在使用 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 件商品,然后流程结束。我也不知道为什么我必须在两个线程之间使用 sleep(anyNumber),即使它不会做任何事情。 有人可以告诉我我设置的 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 core i7 64 bits

谢谢!

【问题讨论】:

  • 一个不相关的提示:不要检查errno,除非之前的函数确实失败了,除非确实发生了错误,errno 的状态是未定义的。另外,如果发生错误,需要立即检查errno,调用其他函数可能会改变值。

标签: c++ multithreading clone mutex producer-consumer


【解决方案1】:

当您创建新的“线程”时,您会告诉它们与父进程共享内存。然而,这样做有两个大问题:

  1. 您为子级创建的堆栈也是共享的,因此两个“线程”将具有相同的堆栈。
  2. 父进程退出,我不确定分配的共享内存会发生什么,但它可能会被释放。

这两件事都会导致undefined behavior

第一个问题可以通过有两个堆栈来解决,每个线程一个。第二个问题可以通过父进程waiting让子进程退出来解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多