指向线程的指针数组中的 PCB 中的相同名称

Same names in PCBs in array of pointers to Thread

本文关键字:PCB 数组 线程 指针      更新时间:2023-10-16

我正在用C++编写线程处理代码。线程的一个实例有一个指向PCB结构的指针,在线程的构造函数中,我称之为myPCB = new PCB(name, stackSize, timeSlice, this)。一切都很好,直到我尝试制作一系列指向 Thread 的指针。

当我只是制作一个指向线程的指针并使用新的线程(名称、堆栈大小、时间切片)初始化它时,该线程在 PCB 中的名称被正确指定。

但是当我尝试使用指针数组时,所有 PCB 都具有相同的名称变量值。

我已经检查过了,它们都是不同的 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列表

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

"线程"是一个字符*,向其添加一个数字将为您提供指针+偏移量。

在创建新堆栈之前,您不希望切换到新堆栈。不要使用推送存储,只需使用这样的东西:

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);

[当然,首先使 stackpointer 成为指向 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.
}

代码是

name = namee

this->name = namee

我刚刚成功

strcpy(name, namee)

它现在有效。