0

我正在为 C++ 中的线程处理编写代码。Thread 的一个实例有一个指向 PCB 结构的指针,并且在我刚刚调用的 Thread 的构造函数中myPCB = new PCB(name, stackSize, timeSlice, this)。在我尝试创建一个指向 Thread 的指针数组之前,这一切都很好。

当我只是创建一个指向线程的指针并使用 new Thread(name, stackSize, timeSlice) 对其进行初始化时,该线程在 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 列表

4

2 回答 2

3
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.
}
于 2013-01-30T13:27:31.133 回答
0

代码是

name = namee

或者

this->name = namee

我刚成功

strcpy(name, namee)

现在可以了。

于 2013-01-31T00:43:13.677 回答