2019-2020-1 20199301 작업의 세 번째 주에 "리눅스 커널 원리 및 분석"

어떻게 운영 시스템이 작동

이 장의 목표는 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)의 실행시의 처리는, 처리 상황에 응답 할 필요가있다.

운영 체제가 작동하는 방법?

차례에 저장된 프로그램 컴퓨터 프로그램 명령어 메커니즘에 의해 실행 시스템을 운영, 프로그램, 예외 처리 및 프로세스 스케줄링에 대한 인터럽트를 실행하는 스택을위한 공간을 제공하기 위해 호출 경로 및 매개 변수를 기록했다.

추천

출처www.cnblogs.com/lsqz/p/11601160.html