簡體   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