繁体   English   中英

在C中将全局结构与pthread一起使用

[英]Using a global struct with pthreads in C

我正在尝试模拟一段时间内进入银行并由出纳员服务的客户。 我正在使用一个线程来确定客户是否通过到达率进入银行,并正在使用多个线程来代表服务费率的柜员。 我正在使用一个结构来保存时间,到达率,服务率,出纳员人数和客户等待队列。 我试图在所有线程之间共享该结构,但出现“解引用指针”错误和“在某种非结构中请求成员x”错误。

//Used to store information input by user and the customer queue
struct shiftInfo {
    int tellers;
    int serviceTime;
    int simTime;
    int sampleInterval;
    int threadID;
    float arrivalRate;
    int Q[]; //Customer Queue
};

信息通过命令行从命令行传递到结构中

    struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
    struct shiftInfo info;
    info.simTime = atoi(argv[1]);
    info.arrivalRate = atof(argv[2]);
    info.tellers = atoi(argv[3]);
    info.serviceTime = atoi(argv[4]);
    info.sampleInterval = atoi(argv[5]);
    //Initiates Q to 0
    for (int i = 0; i < maxCust; i++)
        info.Q[i] = 0;

柜员,计时器和客户线程由主线程创建和终止

  //Manager thread is main thread
  pthread_t manager;
  iret = pthread_create(&manager, NULL, mainThread, (void *)&info);
  if (iret){
    printf("ERROR: return code %d\n", iret);
    exit(-1);
    }

为了简短起见,我将只询问定时器线程,并希望将答案应用于其他线程。 计时器线程是通过以下方式在主线程中创建的:

  int status;
  struct shiftInfo *I = info; 
  pthread_t time;
      status = pthread_create(&time, NULL, timer, (void *)info);
      if (status){
        printf("ERROR CODE: %d\n", status);
        exit(-1);
    }

计时器线程函数是:

void *timer(void *info){
    int timeRemaining = info -> simTime;
    while(timeRemaining){
        sleep(1);
        timeRemaining--;
        }
}

对于“ int timeRemaining =信息-> simTime;” 我收到警告“取消引用空指针”,并且在不是结构或联合的情况下对成员âsimTime发出了错误请求。 任何建议,将不胜感激。

另外,我创建客户线程的方式与创建计时器线程的方式相同,但是会收到一条警告(警告:传递“ pthread_create”的参数3使指针从整数开始而没有强制转换[默认启用])在创建任何其他线程时不会收到线程,是什么原因造成的?

pthread_t customer;
    status = pthread_create(&customer, NULL, customer, (void *)info);
        if (status){
            printf("ERROR CODE: %d\n", status);
            exit(-1);
        }

您犯了很多错误和错别字。 第一个错误是在这里:

struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
    info.Q[i] = 0;

您在Q分配了适当的空间量,但从未在任何地方使用过。 而是使用info ,它没有为info.Q分配任何空间。 因此, info.Q[i] = 0写入info的边界。 建议的解决方法:

struct shiftInfo *info = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
info->simTime = atoi(argv[1]);
info->arrivalRate = atof(argv[2]);
info->tellers = atoi(argv[3]);
info->serviceTime = atoi(argv[4]);
info->sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
    info->Q[i] = 0;

下一个错误是:

status = pthread_create(&time, NULL, timer, (void *)info);

在您的代码中, info是一个结构。 但是您正在尝试将其强制转换为指针。 如果您使用上面建议的修复程序,则info将是一个指针,您可以将此代码保持不变。 您将需要确保对pthread_create所有调用都传递(void *)info而不是(void *)&info

最后一个错误是在这里:

void *timer(void *info){
    int timeRemaining = info -> simTime;

尝试以下方法:

void *timer(void *arg){
    struct shiftInfo *info = (struct shiftInfo *) arg;
    int timeRemaining = info -> simTime;

这个片段是有问题的:

struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
    info.Q[i] = 0;

内存分配很好,但是其他所有东西确实都是可疑的。 您的局部变量infoQ成员中有零个元素,因此您无法使用for循环可靠地对其for初始化。 还不清楚您打算如何处理info ; 您为什么不初始化Q (指针,如果我可以这么说的话,是一个错误选择的名称)。 您应该使用:

struct shiftInfo *shift = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
shift->simTime = atoi(argv[1]);
shift->arrivalRate = atof(argv[2]);
shift->tellers = atoi(argv[3]);
shift->serviceTime = atoi(argv[4]);
shift->sampleInterval = atoi(argv[5]);
for (int i = 0; i < maxCust; i++)
    shift->Q[i] = 0;

现在,您可以使用shift (或任何您选择的调用方式)来设置全局指针。 请注意,您不能有效地将具有灵活数组成员的结构用作全局变量(指向它们的全局指针-是;全局变量-否),也不能将它们作为自动变量。 问题是您不能像这样为弹性数组成员分配任何空间。

您将需要考虑如何使用多个线程来控制对全局结构的访问,以及对全局结构的序列化访问是否将成为严重的瓶颈。 您可能需要互斥体,并且可能需要某些条件。

关于您的timer代码:您需要将传递给struct ShiftInfo *void *转换为struct ShiftInfo *

void *timer(void *vp)
{
    struct ShiftInfo *info = vp;
    int timeRemaining = info->simTime;
    while(timeRemaining){
        sleep(1);
        timeRemaining--;
        }
    return 0;
}

请注意,您确实需要从函数中返回一个值。 另外,您需要考虑这是否会做您想要的事情。 它具有一个已更改的局部变量。 您可能希望将info的值设置为剩余时间。 这就需要在每个操作中进行互斥访问。 我将假设您添加并初始化一个额外的成员:

pthread_t mutex;

到您的struct shifInfo

void *timer(void *vp)
{
    struct shiftInfo *info = vp;
    if (pthread_mutex_lock(&info->mutex) != 0)
        return 0;  // Report error before returning?
    int *timeRemaining = &info->simTime;
    while (*timeRemaining > 0)
    {
        if (pthread_mutex_unlock(&info->mutex) != 0)
            return 0;  // Report error before returning?
        sleep(1);
        if (pthread_mutex_lock(&info->mutex) != 0)
            return 0;  // Report error before returning?
        (*timeRemaining)--;
    }
    if (pthread_mutex_unlock(&info->mutex) != 0)
        return 0;  // Report error before returning?
    return 0;
}

在timer()函数中,您必须将info参数从(void *)强制转换为(struct shiftInfo *)

int timeRemaining = ((struct shiftInfo *)info) -> simTime;

另外,在创建客户时,应该像这样

status = pthread_create(&customer, NULL, customer, (void *)&info);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM