본문내용
-switch_to 매크로 함수
#define switch_to(prev,next,last) do
-> prev : 바뀌는 process
next : 새로 실행할 process
last : 이전에 실행했던 process
{\
unsigned long esi,edi;\
asm volatile("pushfl\n\t"
->esi레지스터를 stack에 push\
"pushl %%ebp\n\t"
->edi레지스터를 stack에 push\
"movl %%esp,%0\n\t"
-> esp포인터를prev->thread.esp에저장
"movl %5,%%esp\n\t"
-> next->thread.esp에저장
"movl $1f,%1\n\t"
-> label ip를 prev->thread.eip에 저장
"pushl %6\n\t"
-> next->thread.eip를 스택에 저장
"jmp __switch_to\n"
-> label switch_to로 점프\
"1:\t"\
"popl %%ebp\n\t"//레지스터 ebp값을 push\
"popfl"
\
:"=m" (prev->thread.esp),"=m" (prev->thread.eip),
-> 해당메모리내용출력\
"=a" (last),"=S" (esi),"=D" (edi)\
:"m" (next->thread.esp),"m" (next->thread.eip),\
"2" (prev), "d" (next));
-> prev는 eax레지스터에 저장, next는 edx레지스터에 저장\
} while (0)
=> switch_to 매크로는 prev로 표시될 프로세스의 ESP레지스터에 백업을 해두고 next로 표시될 프로세스의 ESP 레지스터를 설정하게 된다. 이 처리 후에 프로세스의 스택영역이 바뀌게 된다. 프로세스 prev가 다음 동작을 재게 하게 되면 EIP 레지스터의 저장에 주소를 백업해두게 된다. 다음에 동작할 프로세스 next의 실행 재개 장소를 프로세스 next의 백업해 둔 저장소에서 커내 EIP 레지스터 값을 스택에 넣어 둡니다. _switch_to 함수를 호출한 후에 _switch_to 함수로 돌아오게 될 때 스택에 저장해둔 EIP레지스터 값이 자동적으로 CPU 에 읽혀지게 된다. 그때 프로세스 next 의 중단 지점부터 CPU는 실행을 재게 하게 됩니다. 그리고 잠시 후 prev가 다시 선택되고 실행 권한이 주어집니다. 그러면 방금 전의 프로세스 prev 의 복귀주소인 thread.eip에 저장된 주소부터 실행하게 되는 것이다.
예외가 있다면 fork 시스템 콜에 의해 생겨난 지 얼마 안된 자식 프로세스는 fork 시스템 콜의 후반 처리부터 동작되기 시작한다. _switch_to 함수의 리턴 주소를 fork 시스템 콜 후반 처리의 시작 주소로 하기 위해 EIP레지스터의 저장소에 등록해 둔다. 자식 프로세스는 switch_to 함수의
"pushfl\n\t" \
"pushl %%ebp\n\t"\
"movl %%esp,%0\n\t"장
은 생략하게 되고 _switch_to 함수중간에 끼어든거처럼 동작된다. 또 생성된지 얼마 안된 스레드도 같은 방법으로 EIP레지스터의 저장소 thread.eip 에 설정하고 있습니다.
switch_to 매크로의 전반에 있는 prev는 실행 권한이 없어진 프로세스를 가리키고 있습니다. 한편 프로세스는 prev가 _switch_to 함수에서 리턴되어 재스케줄링 되었을때 prev와 next는 프로세스 전환 상태로 돌아가 버리기 때문에 last가 없을 경우 프로세스로부터 전환되었는지에 대한 정보를 잃어버리게 된다. 이런과정에 의해 switch_to 매크로를 이용하고 있는 스케쥴 함수가 동작하게 된다.
#define switch_to(prev,next,last) do
-> prev : 바뀌는 process
next : 새로 실행할 process
last : 이전에 실행했던 process
{\
unsigned long esi,edi;\
asm volatile("pushfl\n\t"
->esi레지스터를 stack에 push\
"pushl %%ebp\n\t"
->edi레지스터를 stack에 push\
"movl %%esp,%0\n\t"
-> esp포인터를prev->thread.esp에저장
"movl %5,%%esp\n\t"
-> next->thread.esp에저장
"movl $1f,%1\n\t"
-> label ip를 prev->thread.eip에 저장
"pushl %6\n\t"
-> next->thread.eip를 스택에 저장
"jmp __switch_to\n"
-> label switch_to로 점프\
"1:\t"\
"popl %%ebp\n\t"//레지스터 ebp값을 push\
"popfl"
\
:"=m" (prev->thread.esp),"=m" (prev->thread.eip),
-> 해당메모리내용출력\
"=a" (last),"=S" (esi),"=D" (edi)\
:"m" (next->thread.esp),"m" (next->thread.eip),\
"2" (prev), "d" (next));
-> prev는 eax레지스터에 저장, next는 edx레지스터에 저장\
} while (0)
=> switch_to 매크로는 prev로 표시될 프로세스의 ESP레지스터에 백업을 해두고 next로 표시될 프로세스의 ESP 레지스터를 설정하게 된다. 이 처리 후에 프로세스의 스택영역이 바뀌게 된다. 프로세스 prev가 다음 동작을 재게 하게 되면 EIP 레지스터의 저장에 주소를 백업해두게 된다. 다음에 동작할 프로세스 next의 실행 재개 장소를 프로세스 next의 백업해 둔 저장소에서 커내 EIP 레지스터 값을 스택에 넣어 둡니다. _switch_to 함수를 호출한 후에 _switch_to 함수로 돌아오게 될 때 스택에 저장해둔 EIP레지스터 값이 자동적으로 CPU 에 읽혀지게 된다. 그때 프로세스 next 의 중단 지점부터 CPU는 실행을 재게 하게 됩니다. 그리고 잠시 후 prev가 다시 선택되고 실행 권한이 주어집니다. 그러면 방금 전의 프로세스 prev 의 복귀주소인 thread.eip에 저장된 주소부터 실행하게 되는 것이다.
예외가 있다면 fork 시스템 콜에 의해 생겨난 지 얼마 안된 자식 프로세스는 fork 시스템 콜의 후반 처리부터 동작되기 시작한다. _switch_to 함수의 리턴 주소를 fork 시스템 콜 후반 처리의 시작 주소로 하기 위해 EIP레지스터의 저장소에 등록해 둔다. 자식 프로세스는 switch_to 함수의
"pushfl\n\t" \
"pushl %%ebp\n\t"\
"movl %%esp,%0\n\t"장
은 생략하게 되고 _switch_to 함수중간에 끼어든거처럼 동작된다. 또 생성된지 얼마 안된 스레드도 같은 방법으로 EIP레지스터의 저장소 thread.eip 에 설정하고 있습니다.
switch_to 매크로의 전반에 있는 prev는 실행 권한이 없어진 프로세스를 가리키고 있습니다. 한편 프로세스는 prev가 _switch_to 함수에서 리턴되어 재스케줄링 되었을때 prev와 next는 프로세스 전환 상태로 돌아가 버리기 때문에 last가 없을 경우 프로세스로부터 전환되었는지에 대한 정보를 잃어버리게 된다. 이런과정에 의해 switch_to 매크로를 이용하고 있는 스케쥴 함수가 동작하게 된다.
키워드
추천자료
운영체제(OS) 리눅스 프로세스 관련 커널 소스 분석
리눅스용 피코커널 소스 v1
[리눅스커널] Linux Kernel Interrupt Architecture 1.0 (Ver.2.6.24.7)
[리눅스커널] Linux Kernel Open Architecture 1.0 (Ver.2.6.24.7)
[리눅스커널] Linux Kernel Read, Write Architecture 1.0 (Ver.2.6.24.7)
[리눅스커널] 문자 디바이스 드라이버 흐름분석
마이크로 커널의 내부구조와 동작과정 및 리눅스 OS 스케줄링 알고리즘의 구조
커널 모듈, 미니쉘을 이용하여 만든 리눅스 윈도우
오퍼레이팅시스템 프로젝트 - 리눅스 커널과 시스템 콜