함수

2010-02-07 3 views
7

외부에서 레이블을 액세스 코드 :함수

/* ctsw.c : context switcher 
*/ 

#include <kernel.h> 

static void *kstack; 
extern int set_evec(int, long); 

/* contextswitch - saves kernel context, switches to proc */ 
enum proc_req contextswitch(struct proc_ctrl_blk *proc) { 
    enum proc_req call; 

    kprintf("switching to %d\n", getpid(proc)); 

    asm volatile("pushf\n"   // save kernel flags 
       "pusha\n"   // save kernel regs 
       "movl %%esp, %0\n" // save kernel %esp 
       "movl %1, %%esp\n" // load proc %esp 
       "popa\n"   // load proc regs (from proc stack) 
       "iret"    // switch to proc 
       : "=g" (kstack) 
       : "g" (proc->esp) 
       ); 

_entry_point: 
    asm volatile("pusha\n"   // save proc regs 
       "movl %%esp, %0\n" // save proc %esp 
       "movl %2, %%esp\n" // restore kernel %esp 
       "movl %%eax, %1\n" // grabs syscall from process 
       "popa\n"   // restore kernel regs (from kstack) 
       "popf"    // restore kernel flags 
       : "=g" (proc->esp), "=g" (call) 
       : "g" (kstack) 
       ); 
    kprintf("back to the kernel!\n"); 

    return call; 
} 

void contextinit() { 
    set_evec(49, (long)&&_entry_point); 
} 

그것은 작은, 협력, 비 선점 형 커널에 대한 컨텍스트 스위처입니다. contextswitch()은로드 할 프로세스의 스택 포인터와 함께 dispatcher()에 의해 호출됩니다. % esp 및 기타 범용 레지스터가로드되면 iret이 호출되고 사용자 프로세스가 실행되기 시작합니다.

나는 그래서 커널 컨텍스트를 복원하고 dispatcher()에 콜의 값을 반환 할 수 iretcontextswitch()에서 지점으로 돌아갑니다 설정에 인터럽트가 필요합니다.

가 어떻게이 함수 외부에서 _entry_point의 메모리 주소를 액세스 할 수 있습니다

?

답변

3

GCC로 놀면서 잠시 후, 나는 대답을 얻었다. 어셈블리에 아래로 삭제

사용되지 않는 라벨에 대한 GCC 경고를 침묵.

_entry_point: 

asm volatile("_entry_point:"); 

void contextinit() { 
    set_evec_(49, &&_entry_point); 
} 

로 대체

따라서는,

void contextinit() { 
    long x; 
    asm("movl $_entry_point, %%eax\n" 
     "movl %%eax, %0": "=g" (x) : : "%eax"); 
    set_evec(49, x); 
} 
4

스위치 주변 기능의 구현 :이처럼 보이게 : 커널 사용자의

  • 컨텍스트 스위치;
  • 커널 루틴 호출;
  • 커널에서 사용자로 컨텍스트 전환.

그럼 그냥 처음부터 기능을 실행할 수있는 인터럽트를 설정할 수 있습니다. "현재 사용자 프로세스"를위한 전역 포인터가 필요할 것입니다. 프로세스간에 전환하려면 "커널 루틴 호출"에 의해 실행되는 커널 코드가 변수를 다른 프로세스를 가리 키도록 변경합니다.

당신은 하나의 특별한 경우 필요합니다 - 사용자 모드로 커널에서 초기 스위치, 부팅 후 실행의 초기 프로세스. 그 후, 위의 함수는 그것을 처리 할 수 ​​있어야합니다.

+0

이 좋은 생각, 내가 이미하지 않은 경우 디스패처 및 프로세스 제어 코드가 이미 가정 작성 다른 모델, 나는 그것을 사용할지도 모른다. –

1
로 대체

_entry_point에 액세스하는 인라인 어셈블리를 사용하는 외에, 당신은 또한 같은 함수로 정의 할 수 있습니다 :

asm volatile("_entry_point:"); 

void contextinit() { 
    extern void _entry_point(); 
    set_evec(49, (long)&_entry_point); 
}