0

C++ でスレッド処理のコードを書いています。Thread の 1 つのインスタンスには、PCB 構造へのポインターがあり、Thread のコンストラクターでmyPCB = new PCB(name, stackSize, timeSlice, this). スレッドへのポインターの配列を作成しようとするまで、すべて正常に機能していました。

スレッドへのポインタを作成し、それを new Thread(name, stackSize, timeSlice) で初期化すると、そのスレッドの PCB 内の名前が正しく指定されます。

しかし、ポインターの配列で試してみると、すべての PCB で name 変数の値が同じになります。

確認したところ、それらはすべて異なる PCB です (ID が異なります)。それらの名前はコンストラクターで適切に初期化されますが、N 番目のコンストラクターの終わりと (N+1) 番目の終わりの間のどこかで、すべての名前が N+1 の値と同じ値になります。

PCB コンストラクター:

PCB::PCB(TName namee, StackSize stackSizee, Time timeSlicee,Thread *threadd){
    status = begging;

    id = genID++;
    if(namee) name = namee;
    else name = "Thread"+id;

    createStack(stackSizee);

    thread = threadd;

    timeSlice = timeSlicee;

    System::numberOfThreads++;
    System::allPCBQueue.add(this);

    waitingMe = new Queue();
    waitingFor = 0;

    semaphore = 0;

    sleepTime = -1;
    }

void PCB::createStack(StackSize stackSize){
    intOff;
    if(stackSize > maxStack) stack = new char[maxStack];
     else stack = new char[stackSize];

    newSS = FP_SEG(stack + stackSize);
    newSP = FP_OFF(stack + stackSize);
    asm{
      mov oldSS, ss
      mov oldSP, sp
      mov ss, newSS
      mov sp, newSP

      push ax; push bx; push cx; push dx; push es; push ds; push si; push di; push bp

      mov newSP, sp
      mov newSS, ss
      mov sp, oldSP
      mov ss, oldSS
    }

    stackPointer = MK_FP(newSS, newSP);
    intOn;
}

私は createStack() で何かを理解していますが、何がわかりません。すべての助けに感謝します。

*注: 現在、インターネットに常時アクセスできないため、返信が遅くても怒らないでください。この質問については、できる限り調べてみます。

編集済み: PCB クラス定義:

class PCB
{
    static ID genID;

    char *stack;
    void *stackPointer;
    Thread *thread;

    TName name;
    ID id;

    Time timeSlice, sleepTime;
    Status status;

    Queue *waitingMe;
    PCB* waitingFor;

    KernelSem* semaphore;

    friend class Thread;

//  static unsigned newSS, newSP, oldSS, oldSP;

public:
    static StackSize maxStack;

    PCB(TName name, StackSize stackSize, Time timeSlice,Thread *thread);
    ~PCB(void);

    void runThread();

    ID getID(){
        return id;
    }
    TName getName(){
        return name;
    }

    void setStatus(Status status){
        this->status = status;
    }
    Status getStatus(){
        return status;
    }
    int getEnding(){
        if(status == ending) return 1;
        return 0;
    }
    int getBegging(){
        if(status == begging) return 1;
        return 0;
    }

    void createStack(StackSize stackSize);
    void* getStackPointer(){
        return stackPointer;
    }
    void setStack(void *newStackPointer){
        stackPointer = newStackPointer;
    }

    Time getTimeSlice(){return timeSlice;}

    Time getSleepTime(){return sleepTime;}
    void decrementSleepTime(){sleepTime--;}

    void setSemaphore(KernelSem* kersem){this->semaphore = kersem;}
    void resetSemphore(){this->semaphore = 0;}

    Thread* getThread(){return thread;}
};

これが発生するコード:

Producer **pro = new Producer*[N];

for (i=0; i<N; i++){
    producerName[8]='0'+i;
    pro[i] = new Producer(buff, producerName ,'0'+i, TIME_SLICE);
    pro[i]->start();
}

これは、この割り当てで取得したテスト ファイルの一部です。変更してはいけません。しかし、それは定期的です。私は置きました

allPCBQueue->listAll()

pro[i] = new Producer(buff, producerName ,'0'+i, TIME_SLICE);

すべての名前が同じであることが常にわかります。allPCBQueue は、PCB の単純なリストです。

4

2 に答える 2

3
if(namee) name = namee;
else name = "Thread"+id;    <<< Doesn't do what you think it does. 

「スレッド」は char * です。それに数値を追加すると、ポインター + オフセットが得られます。

新しいスタックを作成するまで、新しいスタックに切り替えたくありません。push to store を使用する代わりに、次のようなものを使用してください。

stackPointer = MK_FP(newSS, newSP);

unsigned *sp = reinterpret_cast<unsigned *>(stackPointer);

*--sp = 0;   // AX
*--sp = 0;   // BX
*--sp = 0;   // CX
*--sp = 0;   // DX
*--sp = default_ds;   // You'll have to dig this out with some inline assembler
*--sp = default_es;   // You'll have to dig this out with some inline assembler
*--sp = 0;   // SI
*--sp = 0;   // DI
*--sp = 0;   // BP

stackPointer = reinterpret_cast<void *>(sp);

[もちろん、最初からスタックポインタを int へのポインタにするほうが簡単です]。

スレッドはゼロから開始されるため、AX、BX などの値は関係ありません。ES/DS は、使用しているメモリ モデルによっては問題になる場合があります。スタックにプッシュしないということは、この部分の割り込みを無効にする必要がないことも意味します-常にボーナスです。

残念ながら、あなたのコードは「PCB の配列」で何をしているのかを示していないので、何が悪いのかはわかりません。そして、実際にはあなたの質問に答えないので、これは答えではなくコメントであるべきだと誰かが言うと確信していますが、コメント内のコードのフォーマットはほとんど絶望的です...

編集:

「プロデューサー名」は、スレッドを作成するコード内のローカル変数だと思います。これは機能しませんが、呼び出し元が名前が永久に残ることを保証する必要があることを指示するのは少し難しいと思います。そのため、次のことを行う必要があると思います。

if(namee)
{
    size_t len = strlen(namee);
    char *name_buf = new char[len+1];
    strcpy(name_buf, namee);
    name = name_buf;
}
else
{
   // Make up some random name here.
}
于 2013-01-30T13:27:31.133 に答える
0

コードは

name = namee

また

this->name = namee

作ったばかり

strcpy(name, namee)

そしてそれは今動作します。

于 2013-01-31T00:43:13.677 に答える