У меня есть тестер, который вызывает fork
в al oop, чтобы убедиться, что fork
выживает. Но после создания только 5 дочерних процессов мы получаем эту ошибку:
Fatal user mode trap 2 (TLB miss on load, epc 0x400464, vaddr 0x400464)
Вот код для sys_fork
:
pid_t sys_fork(struct trapframe tf,int retval){
//disable interrupts (not sure if i need this line)
//int s=splhigh();
//the pid of the current thread (each process only has one thread so this pid belongs to both curthread and curprocess)
parent_pid=curthread->t_pid;
//a global variable for the newly generated pid (for the child process)
child3_pid=pid_generator(parent_pid);
//if the pid is 0 that means we are out of the PIDs
if(child3_pid==0){
//return the error (too many PIDs)
*retval=-1;
return EAGAIN;
}
int result;
//create a new process
struct process* child_process=create_process("Child Process",child3_pid);
//if the new process is NULL retrun the error
if(child_process==NULL){
*retval=-1;
return ENOMEM;
}
//create a new address space for the child (which is a copy of the parent's trapframe)
struct trapframe* parent_tf=kmalloc(sizeof(struct trapframe));
if(parent_tf==NULL){
*retval=-1;
return ENOMEM;
}
memcpy(parent_tf,tf,sizeof(struct trapframe));
//create a new thread for the child process and pass it to thread fork
struct thread* child_thread;
result=thread_fork("Child Process",parent_tf,0,&md_forkentry,&child_thread);
//if thread fork fails
if (result) {
//free the new address space
kfree(parent_tf);
//destroy the new process
process_destroy(child_process);
//remove the process from the proces table
process_pid_table[child3_pid]=NULL;
*retval=-1;
return result;
}
//if thread fork does not fail, we can setup the parent PID and child PID to the new process
child_process->pid=child3_pid;
child_process->ppid=parent_pid;
*retval=child_process->pid;
//splx(s);
return 0;
}
Это код для md_forkentry
:
void md_forkentry(void *tf,unsigned long n)
{
(void) n;
/*
* This function is provided as a reminder. You need to write
* both it and the code that calls it.
*
* Thus, you can trash it and do things another way if you prefer.
*/
/*
* before returning to user mode, we need to copy the modified trapframe
* from kernel heap to stack, then use its address as parameter to call
* mips_usermode,
*/
int s;
s = splhigh();
//the new address space
struct trapframe trap;
//copy the address space from the parent address space
memcpy(&trap,tf,sizeof(struct trapframe));
/*
* We need to set our return value in the copied trapframe to 0 since
* we are the child which is done by modifying the v0 register. Also
* increment program counter to stop reentry of the same system call
*/
trap.tf_v0 = 0;
trap.tf_epc += 4;
trap.tf_a3 = 0;
//switch to user mode
splx(s);
mips_usermode(&trap);
//kprintf("fork_entry child %l: returning to user mode\n", parent_addr_space);
}
По сути, мы должны иметь возможность создать больше дочерних процессов, чем 5. Поскольку ошибка кажется ошибкой пользовательского режима (в зависимости от адреса), я понятия не имел, где происходит сбой даже при использовании GDB (может ' дайте мне, где это не удается на основе адреса). Кто-нибудь знает, что может быть не так?