mint64os icon indicating copy to clipboard operation
mint64os copied to clipboard

kernel process의 stChildThreadList를 초기화 하지 않음으로써 실제 컴퓨터에서 구동이 안되는 문제와 그에 대한 해결방안

Open ybjeon01 opened this issue 3 years ago • 2 comments

안녕하세요. Ch21를 코드 작성을 마치고 실제 컴퓨터에서 구동하는 테스트중에 General Protection Exception이 발생하게 됐습니다. 그리고 이 문제가 이 GitHub 코드에도 똑같이 발생할 문제인 것 같아 글을 올립니다.

Ch21의 kCreateTask 함수를 보면 모든 process의 멤버중 하나인 stChildThreadList를 초기화합니다. 하지만 딱 하나 초기화가 되지 않은채 실행되는 task가 하나 있는데요. 바로 kernel process입니다. 단순히 이 커널 프로세스의 thread를 생성하지 않으면 아무 문제없이 운영체제가 잘 작동합니다. 하지만 문제는 kIdleTask 함수가 이 커널 프로세스의 thread로 작동하면서 발생합니다.

이 커널 process는 kInitializeSchedule 함수안에서 생성되는데 stChildThreadList가 초기화 되지가 않습니다. 초기화가 안된 stChildThreadList 안의 멤버들은 의도되지 않는 숫자가 들어가 있는 상태에서 kCreateTask 함수가 kIdleTask의 qwID를 부모 process (kernel process)의 list에 연결할 떄 존재하지 않는 메모리 참조가 일어나면서 general protection exception이 발생되는걸 확인했습니다.

좀 더 쉽게 눈으로 확인하기 위해서 비디오를 남깁니다. 그리고 원래 코드와 바뀐 코드도 함께 올렸습니다. 수고하세요.

Original Code (02.Kernel64/Source/Task.c)

void kInitializeScheduler( void )
{
    // 함수의 윗부분을 생략했습니다.
    
    pstTask->qwParentProcessID = pstTask->stLink.qwID;
    pstTask->pvMemoryAddress = ( void* ) 0x100000;
    pstTask->qwMemorySize = 0x500000;
    pstTask->pvStackAddress = ( void* ) 0x600000;
    pstTask->qwStackSize = 0x100000;
    
    // 프로세서 사용률을 계산하는데 사용하는 자료구조 초기화
    gs_vstScheduler[ bCurrentAPICID ].qwSpendProcessorTimeInIdleTask = 0;
    gs_vstScheduler[ bCurrentAPICID ].qwProcessorLoad = 0;
    
    // FPU를 사용한 태스크 ID를 유효하지 않은 값으로 초기화
    gs_vstScheduler[ bCurrentAPICID ].qwLastFPUUsedTaskID = TASK_INVALIDID;
}

Modified Code

void kInitializeScheduler(void) {
    // 이 함수의 윗부분을 생략했습니다.

    pstTask->qwParentProcessID = pstTask->stLink.qwID;
    pstTask->pvMemoryAddress = (void *) 0x100000;
    pstTask->qwMemorySize = 0x500000;
    
    pstTask->pvStackAddress = (void *) 0x600000;
    pstTask->qwStackSize = 0x100000;

    // 바뀐 부분
    kInitializeList(&(pstTask->stChildThreadList));
    

    // initialize variables that help to calculate processor load
    gs_stScheduler.qwSpendProcessorTimeinIdleTask = 0;
    gs_stScheduler.qwProcessorLoad = 0;
}

(근데 시간 나시면 mint64OS 사이트에 올린 제 질문들 좀 확인해줄 수 있나요? linuxer라는 닉네임으로 활동하고 있습니다. FreeBoard와 QnA 게시판에 한 4개정도 올렸습니다. 바쁘지 않을 때 천천히 확인해주세요.)

ybjeon01 avatar Jul 04 '21 10:07 ybjeon01

안녕하세요, @ybjeon01 님!

앗, 감사합니다. 초기화되지 않은 필드가 있었군요! 제가 보고 시간날 때 반영하겠습니다.

그런데 혹시 시험은 어디서 하셨는지 알 수 있을까요? 운영체제 환경이랑 시험용 가상머신 환경 등을 알려주실 수 있을까요?

감사합니다.

ps) 사이트에 남기신 질문도 제가 확인하겠습니다. ^^)-b

kkamagui avatar Jul 05 '21 01:07 kkamagui

그럼요. 알려줄 수 있죠.

개발 환경

  1. CPU: Intel Core i5-7200U Dual-Core (x86_64)

  2. OS: Windows 10 (x64)

  3. Docker: v20.10.7 with WSL2

  4. Container: Ubuntu 20.04.2 LTS (Focal Fossa)

  5. Tools installed in container:

    • NASM version 2.14.02
    • GCC (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 # 추후 cross compiler로 바꿀 예정입니다.
    • GNU ld (GNU Binutils for Ubuntu) 2.34
    • GNU Make 4.2.1
  6. IDE: Visual Studio Code # Linux container에 Visual Studio Code 서버 설치하고 Windows에서 Client 실행하는 게 가능합니다)

  7. Image Writer: Rufus version 3.0.1304

테스트 환경

  1. 가상 환경: QEMU emulator version 6.0.0 (v6.0.0-11869-g800a25ea45-dirty) for Windows

  2. 실제 PC: Samsung Series 5 NP530U3B

    • 1.6GHz Intel Core i5-2467M Dual-Core (x86_64)

부가 설명

  1. Windows와 Docker Container사이에 공유되는 volume을 하나 추가해서 사용하고 있습니다. 모든 활동을 이 volume안에서 하고 있어서 컴파일이 끝나면 바로 Windows 환경에서 사용할 수 있게끔 했습니다.

  2. Windows환경에서 작동하는 QEMU emulator에 kernel 파일을 실행했습니다.

  3. Rufus image writer는 Windows 환경에서만 작동합니다.

ybjeon01 avatar Jul 05 '21 03:07 ybjeon01