Ho un progetto che è una specie di sistema operativo virtuale.
In questo progetto, la classe Kernel
è responsabile della creazione delle classi Process
. La classe di processo è composta da% classi% co_de e la classe Thread
sarà composta da una classe Thread
. La classe CPU
è in realtà un emulatore CPU
e il CPU
è quindi un thread "emulato". Quindi, quando la classe Thread
incontra un'istruzione di interrupt, deve essere gestita dal kernel perché di solito è una chiamata di sistema. La classe CPU
non può visualizzare direttamente la classe Kernel
, è incorporata nella classe CPU
, che è incorporata nella classe Thread
.
L'approccio che sto utilizzando ora utilizza una classe Process
, che gestisce le chiamate di sistema e i breakpoint. Ecco come appare il codice.
class CPU final {
std::shared_ptr<MemoryBus> memoryBus;
std::shared_ptr<InterruptHandler> interruptHandler;
std::uint32_t regs[32];
public:
void Run(unsigned int steps) {
for (decltype(steps) i = 0; i < steps; i++)
RunInst();
}
protected:
// This function will call the interrupt
// handler if it encounters an interrupt instruction.
void RunInst();
};
class Thread final {
std::shared_ptr<CPU> cpu;
std::shared_ptr<InterruptHandler> interruptHandler;
public:
Thread() : cpu(new CPU) {
}
void Run(unsigned int steps) {
cpu->Run(steps);
}
};
class Process final {
std::vector<std::shared_ptr<Threads>> threads;
std::shared_ptr<MemoryMap> memoryMap;
std::shared_ptr<InterruptHandler> interruptHandler;
public:
void Run(unsigned int steps) {
for (auto &t : threads)
t->Run(steps);
}
};
class InterruptHandler {
std::shared_ptr<FS> fs;
public:
void HandleInterrupt(CPU &cpu, int interrupt_type);
void HandleSyscall(CPU &cpu, int syscall_type);
void HandleWrite(CPU &cpu, int fd, const void *buf, unsigned int len);
// More system calls follow
};
class Kernel final {
std::vector<std::shared_ptr<Process>> processes;
std::vector<InterruptHandler> interruptHandler;
public:
void Run(unsigned int steps) {
for (auto &p : processes)
p->Run(steps);
}
void AddProcess(const std::string &path) {
// opens process, assigns interrupt handler
processes.emplace_back(process);
}
};
Il problema qui è che la classe del gestore di interruzioni deve essere passata a quasi tutte le sottoclassi della classe InterruptHandler
, inclusa la classe Process
. Inoltre, Process
sembra che finirà per contenere molti degli stessi dati della classe InterruptClass
. Non mi piace perché sento che viola il principio di "non ripeterti".
So che c'è un modo migliore di progettarlo ma non l'ho ancora capito. Il modello di progettazione Proxy è applicabile a questo scenario? Per quanto riguarda l'utilizzo di segnali e slot, simile a Qt e anche descritto qui ?
Ho omesso l'URL di questo progetto, perché non voglio essere promosso da me stesso. Se il codice che ho fornito è troppo incompleto, farò riferimento ai file nel progetto per maggiori informazioni.