어떻게 운영 시스템이 작동
이 장의 목표는 MYKERNEL에 기초하여 간단한 커널을 작성하는 것입니다
첫째, 연구 노트
1. 세 마법 컴퓨터 : 저장된 컴퓨터 프로그램, B 함수 호출 스택; C 인터럽트.
- 저장 프로그램 컴퓨터 (모든 근본적인위한 컴퓨터 로직 프레임 워크);
- 함수 호출 스택 (C 언어 런타임 함수 호출 경로와 기록 파라미터 기억 공간을 사용한다);
- 특정 역할을 스택 :
- 기록 함수 호출 프레임
- 인수 전달
- 반환 값의 주소를 저장
- 함수 내 로컬 변수의 저장을 제공한다
- 관련 레지스터를 스택 :
- ESP : 스택 포인터
- EBP :베이스 포인터
- 스택 작업 :
- 푸시 4 바이트의 스택 주소를 줄이고, 오퍼랜드가 저장 부에 스택
- 팝 : 스택 주소가 4 바이트 증가하고 스택 피연산자 저장 부 상단에
- 다른 주요 레지스터 :
- CS : EIP는 : 항상 계속해서 다음 명령 주소를 가리키는
- 점프 / 지사 :이 명령이 실행되고, CS는 : EIP의 값은 절차에 따라 수정해야 할 수도 있습니다
- 전화 : 현재 CS를 : EIP 의 스택에 값이 CS : EIP는 호출 된 함수의 엔트리 주소를 가리키는
- RET : 이전에 여기에 저장된 스택에서 팝 EIP의 : CS 값을의에 CS : EIP는 에
- 스택은 함수 호출 스택 프레임에서 특히 중요하다
- 특정 역할을 스택 :
둘째, 실험
- QEMU 창을 볼 수 있습니다 MYKERNEL에서 리눅스 커널은 / 리눅스 3.9.4 / 디렉토리
- 코드
cd LinuxKernel/linux-3.9.4 qemu -kernel arch/x86/boot/bzImage
QEMU 창
보기 mymain.c
사이클 당 1 만 시간은, 단어를 인쇄 할 수 있습니다.myinterrupt.c보기
때마다, 그것은 클럭 인터럽트를 수행합니다.
다음은 간단한 라운드 로빈 메커니즘 커널 코드입니다 :
mypcb.h
#define MAX_TASK_NUM 4
#define KERNEL_STACK_SIZE 1024*8
/* CPU-specific state of this task */
struct Thread {
unsigned long ip;
unsigned long sp;
};
typedef struct PCB{
int pid;
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
char stack[KERNEL_STACK_SIZE];
/* CPU-specific state of this task */
struct Thread thread;
unsigned long task_entry;
struct PCB *next;
}tPCB;
void my_schedule(void);
- 定义一个进程控制块pcb结构体
- task_entry:进程入口函数
- thread:保存eip和esp
- state:进程状态,用于判断是否调度
mymain.c
주요 기능은 프로그램이 프로세스 번호 0의 시작 부분에서 실행할 수 있도록하는 것입니다 만 다음 코드는 핵심입니다 나열된.
asm volatile(
//%0表示参数thread.ip,%1表示参数thread.sp。
"movl %1,%%esp\n\t" /* set task[pid].thread.sp to esp 把参数thread.sp放到esp中*/
"pushl %1\n\t" /* push ebp 由于当前栈是空的,esp与ebp指向相同,所以等价于push ebp*/
"pushl %0\n\t" /* push task[pid].thread.ip */
"ret\n\t" /* pop task[pid].thread.ip to eip */
"popl %%ebp\n\t"
:
: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/
);
myinterrupt.c
주된 기능은 클록 인터럽트 처리 공정 스케줄링 알고리즘에 사용된다.
asm volatile(
"pushl %%ebp\n\t" /* save ebp 保存当前进程的ebp*/
"movl %%esp,%0\n\t" /* save esp 把当前进程的esp赋给%0(指的是thread.sp),即保存当前进程的esp*/
"movl %2,%%esp\n\t" /* restore esp 把%2(指下一个进程的sp)放入esp中*/
"movl $1f,%1\n\t" /* save eip $1f是接下来的标号“1:”的位置,把eip保存下来*/
"pushl %3\n\t" /*把下一个进程eip压栈*/
"ret\n\t" /* restore eip 下一个进程开始执行*/
"1:\t" /* next process start here */
"popl %%ebp\n\t"
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
);
셋째, 요약
(1) 공정과 우리가 마스터해야, 운영 체제가 매우 중요한 부분이 있습니다 방해.
(2) 코드의 실행을 현재 저장 EIP 레지스터는 코드하여 전환하는 과정을 실현할 현재 실행 EIP 레지스터의 값을 변경함으로써 변경 될 수있다. 보안상의 이유로 EIP 레지스터의 값을 직접 변경할 수 없지만, 간접적으로 RET 명령은 푸시 +에 의해 변경 될 수 있습니다.
핸드 오버 프로세스는 현재 실행 컨텍스트, 다음 예약 시간을 절약해야 후에 타임 슬라이스가 만료되면 (3)의 실행시의 처리는, 처리 상황에 응답 할 필요가있다.
운영 체제가 작동하는 방법?
차례에 저장된 프로그램 컴퓨터 프로그램 명령어 메커니즘에 의해 실행 시스템을 운영, 프로그램, 예외 처리 및 프로세스 스케줄링에 대한 인터럽트를 실행하는 스택을위한 공간을 제공하기 위해 호출 경로 및 매개 변수를 기록했다.