2016-11-02 9 views
1

Я хочу создать поток в xv6 с помощью системного вызова «clone()», но я запутался в создании стека, поскольку, если я хочу создать поток, мне нужно создайте соответствующий регистр регистров, такой как ebp, esp, eip. Но я не знаю, как установить значение этого регистра указателя.Регистрация указателя при создании потоков в xv6

Вот код клона() в xv6, я не знаю, почему мы должны установить значение указателя регистра, как это .......

int clone(void(*fcn)(void*), void *arg, void*stack){ 

    int i, pid; 
    struct proc *np; 
    int *ustack = stack + PGSIZE - sizeof(void*); 
    //allocate process. 
    if((np=allocproc()) == 0) 
    return -1; 

    //copy process state from p 
    np->pgdir = proc->pgdir; 
    np->sz = proc->sz; 
    np->parent = 0; 
    np->pthread = proc; 
    *np->tf = *proc->tf; 
    np->ustack = stack; 

    //initialize stack variables 
    //void *stackArg, *stackRet; 
    //stackRet = stack + PGSIZE -2*sizeof(void*); 
    //*(uint *)stackRet = 0xffffffff; 

    //stackArg = stack + PGSIZE -sizeof(void*); 
    //*(uint *)stackArg = (uint)arg; 
    *ustack = (int) arg; 
    *(ustack - 1) = 0xffffffff; 
    *(ustack - 2) = 0xffffffff; 


    //Set stack pinter register 
    np->tf->eax = 0; 
    np->tf->esp = (int) ustack - sizeof(void*); 
    np->tf->ebp = np->tf->esp; 
    np->tf->eip = (int)fcn; 

    for(i = 0; i < NOFILE; i++) { 
    if(proc->ofile[i]) 
     np->ofile[i] = filedup(proc->ofile[i]); 
    } 

    np->cwd = idup(proc->cwd); 
    np->state = RUNNABLE; 
    safestrcpy(np->name, proc->name, sizeof(proc->name)); 
    pid = np->pid; 
    return pid; 

} 
+0

'клон()' является Linux- (и, видимо, xv6-) специфичны. Если xv6 имеет pthreads, тогда я настоятельно рекомендую использовать этот интерфейс. –

ответ

1

Вы надеваете» t установить эти регистры - клон устанавливает их для вас. Вам необходимо предоставить функцию (клон которой используется для инициализации ip) и стек (клон использует для инициализации sp).

Указатель функций довольно прямолинейный (его просто указатель функции C), но стек сложнее. Для реализации clone вы показываете, вам нужно выделить некоторую память и указать указатель PGSIZE ниже конец этого блока. Вызов клона Linux аналогичен, но немного отличается (вам нужно указать указатель на конец блока). Если вы хотите поймать переполнение стека, вам нужно будет сделать больше работы (возможно, выделение защищенной страницы чтения/записи под стеком).

+0

Я знаю, как использовать этот системный вызов clone(), но я смущен указателем регистра в этой функции, и я хочу знать, почему они могут быть установлены следующим образом: – zyz

+0

Я не понимаю ваш вопрос, тогда - создание клонов регистры потока для нового потока на основе аргументов, которые вы ему даете.Он должен настроить регистры потока, чтобы ваша функция вызывается, когда планировщик переключается на новый поток. –

+0

Например, я не знаю, почему np-> tf-> eax равно 0, я думаю, что он должен быть равен ebb – zyz

1

Из всех значений регистров вы установили, единственные полезные из них является:

EIP - Сообщает нить, где начать выполнение с моментом, когда он возвращается в пользовательского приложение

Esp - это точки вверху стека. Это означает, что если вы сделали это правильно, 4 байта, сохраненный на вершине стеки должен содержать ваш обратный адрес


е это не очень полезно здесь видеть, как поток переходит к новому контексту и не где он был создан. В противном случае eax сохранит возвращаемое значение последнего системного вызова. См. Реализацию fork, если вы все еще запутались в этом вопросе.

EBP не манипулирует вами, а условностями вызов функции x86 и обычно устанавливается на значение особ когда функция вызывается. Таким образом вы будете обычно видеть такого рода вещи в разборках большинства вызовов функций

push ebp  ; Preserve current frame pointer 
mov ebp, esp ; Create new frame pointer pointing to current stack top 

EBP также полезен для стека трассировки, поскольку он сохраняет вершину стеки предыдущей функции, прежде чем она затем изменяется в точку к текущей вершине стека


Вам не нужен этот *(ustack - 2) = 0xffffffff;