Pintos project2 keywords

혀누·2021년 12월 31일
0

Pintos

목록 보기
6/11

User mode vs. Kernel mode?

kernel mode

  • 시스템의 모든 메모리에 접근 할 수 있고 모든 CPU명령을 실행할수 있다.
  • 운형체제 코드나 디바이스 드라이버같은 커널 모드 코드를 실행한다.
  • cpu는 커널 모드 특권 수준에서 코드를 실행한다. (privileged)

User mode

  • 사용자 애플리케이션 코드를 실행한다.
  • 시스템 데이터에 제한된 접근만이 허용되며 하드웨어에 직접 접근 할 수 없다.
  • 유저 애플리케이션은 시스템 서비스 호출을 하면 유저모드에서 커널모드로 전환된다. (system call)
  • cpu는 유저모드 특권 수준으로 코드를 실행한다.
  • 유저모드에서 실행하는 스레드는 자신만의 유저모드 스택을 가진다.

=> 기본적인 I/O protection을 하기 위함. 악의적 사용자가 input으로 특정 하드웨어 메모리에 명령을 내리는 assembly어를 썼더라도 이를 user mode에서 읽게되면 cpu가 해당 명령을 수행하지 않음.

Process Environment Block(PEB)

PEB 는 프로세스 정보를 담고있는 구조체 입니다.

PEB구조체는 아래와 같이 정의되어 있다.

typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged;
  BYTE                          Reserved2[1];
  PVOID                         Reserved3[2];
  PPEB_LDR_DATA                 Ldr;
  PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  PVOID                         Reserved4[3];
  PVOID                         AtlThunkSListPtr;
  PVOID                         Reserved5;
  ULONG                         Reserved6;
  PVOID                         Reserved7;
  ULONG                         Reserved8;
  ULONG                         AtlThunkSListPtr32;
  PVOID                         Reserved9[45];
  BYTE                          Reserved10[96];
  PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  BYTE                          Reserved11[128];
  PVOID                         Reserved12[1];
  ULONG                         SessionId;
} PEB, *PPEB;

Process Identifier(PID)

PID는 운영체제에서 프로세스를 식별하기위해 프로세스에 부여하는 번호를 의미한다.

PPID는 부모의 프로세스를 의미한다.

User stack?

User mode에서 실행되는 user process의 stack 데이터 영역.

일반적으로 user mode에서의 함수 콜은 user stack에 모두 쌓인다.

하지만 system call 의 경우는 kernel 함수이긴 하지만 user memory의 stack 에 쌓지 않고 Kernel memory 있는 stack에 쌓이게 된다.

즉, process 가 User mode에서 실행될때는 User mode Stack을 사용하게 되고

Kernel mode에서 실행 될때는 Kernel mode stack에 쌓이게 된다.

Calling Convention

원론적인 의미의 calling convention이란 호출자caller와 피호출자 callee간의 함수의 인자를 전달하는 방식에 대한 규약을 정의한 것. 이러한 호출규약은 architecture 마다 다를 수 있음.

x86_64 calling convention

  • cdecl
    - c및 c++프로그램에 대한 기본 호출규약. 스택이 호출자에의해 지워지기 때문에, 가변인자를 가지는 함수를 정의할 수 있다.

Register vs. Memory

메모리 계층구조는 다음과 같다.

이중 레지스터는 cpu와 딱붙어있어 가장 빠르지만 메모리 중엔 가장 작은 용량을 가진다.

레지스터는 맡은 역할에 따라 담은 데이터가 다르다.

-> bRd3D CPU는 어떻게 작동할까?

메모리가 슈퍼마켓이라면 레지스터는 냉장고!
요리(연산)하는데 필요한 재료는 슈퍼마켓(메모리)에서 사와서 냉장고(레지스터)에 넣어놓는다. 그리고 필요할때마다 그때 그때 꺼내서 쓴다.

범용 CPU레지스터의 종류는 다음과 같다.

Argument Vector

프로그램에 인자값, 즉 main()에 인자값을 전달해야할때 써먹을 수 있는 요소다.

main함수의 원형은 다음과 같다.

#include <stdlib.h>  
#include <stdio.h>  
   
int main(int argc, char *argv[])  
{  
        int i;  
  
        for (i = 0; i < argc; i++)  
                printf("argv[%d]: %s\n", i, argv[i]);  
        exit(0);  
}  


출처: https://gday2code.tistory.com/72 [우리들의 지식저장소]

argc 는 argument count로 int형으로 정의하며, 인수들의 개수이다.
argv 는 argument vector이며 char형 더블포인터이다. 인수들 자체를 나타내는 문자열들의 배열이다. (문자열의배열이니 더블포인터겠지요?)

즉, argv는 입력하는 문자열의 전체를 나타내고 argc는 해당 문자열의 요소 개수 정도로 생각하면 될듯 하다.

ELF(Excutable and Linkable Format)

단순하게 말하면 그냥 리눅스/유닉스의 파일 실행에서 디스크에 저장되어있던 프로그램이 메모리 영역에 올라가서 컴퓨팅 자원을 사용하여 서비스 제공해주는 것.

ELF에서는 프로그램이 실행될때 메모리에 올라가야 할 각각의 부분들을 미리 정리하여 관리하다가 실행을 하게되면 정리된 부분들(code, data, bss)을 메모리에 올리게 된다.

이렇게 메모리에 올라온 주소공간의 code 영역의 instruction을 한라인씩 실행하며 프로세스가 진행된다.

ELF 파일 형식

1) ET_NONE (ELF type none) (0x 0000)

: 알 수 없는 형식 -> 아직 정의되지 않았거나 알 수 없다는 의미

2) ET_REL (ELF type relocatable) (0x 0001) - 링킹 가능한 포맷

: 재배열이 가능한 파일 형식 -> 아직 실행파일에 링킹되지 않은 상태

(*.o 파일로 컴파일만 진행된 상태)

  • relocatable symbol들을 symbol resolving reference 해야하는 바이너리

3) ET_EXEC (ELF type executable) (0x0002) - 실행 가능한 포맷

: 실행 파일 형식(= 프로그램) -> 프로세스의 시작 지점인 엔트리 포인트가 존재

  • relocatable symbol들을 모두 symbol resolving reference 해서 실행 가능한 바이너리

4) ET_DYN (ELF type dynamic) (0x0003) - 실행 가능하면서 링킹 가능한 포맷

: 공유 오브젝트 파일 형식 -> 동적 링킹이 가능한 오브젝트 파일 (= 공유 라이브러리)

(런타임 중에 프로그램의 프로세스 이미지로 로드되고 링크 됨)

  • relocatable symbol들을 symbol resolving reference 해서 실행 가능하지만, 공유 혹은 동적 라이브러리를 실행 시에 혹은 런타임에 링킹시켜야 하는 바이너리

5) ET_CORE (ELF type core) (0x0004)

: 코어 파일 형식 -> 프로세스 이미지의 전체 덤프

주로 프로그램이 비정상 종료되거나 SIGSEGV 시그널(세그멘테이션 폴트)로 인해 프로세스가 종료된 경우 생성

GDB로 코어파일을 읽어 분석해 비정상 종료된 시점의 원인 분석이 가능

ELF는 2가지 View 를 가진다

Linking View , Execution View.

  • Linking View is like object file(.o) which made before Link.
  • After Link, Execution View is fully executable form of ELF.

Linker & Loader

what is Linking?

Linking is the process that make codes and data to combine one object(file.o).

In combining process, 2 process will event.
1. Relocation.
-> This is allocating memory address of each part of program when they're loading.
2. Symbol Resolution.
-> This step helps caller who call function of another programs to call easily without knowing exact address of functions.

what is Loader?

Loader is the process which loading files saved in disks to the memory.

정확하게는 메모리에 로드 될 수 있는 포맷의 code와 data들을 메모리에 로딩하고, program의 시작주소로 이동하는 프로그램이다.

loader는 execve 함수로 호출되는 프로그램이다.

File Descriptor Table

프로세스가 현재 사용중인 파일을 관리하기 위한 테이블이며, 프로세스마다 하나씩 가지고 있다. File Table을 가리키는 포인터를 담고있는 배열이고, 이 배열의 index 가 fd이다.

이런식의 도식화 또는

table 만으로 표현하면 이렇다.

system call

잘 정리해주신 블로그가 있어 링크 붙인다.

showerbugs 리눅스 시스템프로그래밍

Pintos page table

Pintos 의 Table 구조

  • pintos 는 4KB 크기의 page directory를 하나 가지고 있다.
  • 32 bit 아키텍처에서 하나의 주소값은 4B를 차지하므로 4KB의 page directory 는 1024(4KB/4B = 1024)개의 PDE를 가진다.
  • 하나의 page table은 4KB의 크기를 가지고 Page directory 와 마찬가지로 1024개의 PTE를 가진다.
  • 각 Page는 4KB의 크기를 가진다.
  • 이를 통해 pintos가 32bit의 linear address로 표현할수 있는 Virtual Memory 의 크기는 1024(PDE) 1024(PTE) 4KB(Page) = 2^20 4KB = 1MB 4KB = 4GB 라는 것을 알 수 있다. 즉, pintos 의 각 process 는 4GB 의 virtual memory 공간을 갖는다.

Basic Page Table Mapping

  • 보호모드로 전환된 후의 접근가능한 virtual memory의 크기는 4GB이고, pintos는 이중에서 0xc0000000-0xffffffff(3GB-4GB) 의 1GB 공간을 커널 영역으로 사용한다. (이 커널의 시작 위치는 LOADER_PHYS_BASE(0xc0000000) 라는 값으로 <thread/loader.h> 에 정의되어 있다.)

  • 기본적인 Page Table 을 만들어, 현재 Physical Memory address 를 Virtual Memory 의 0-64MB 에 그대로 mapping한다.

  • 동일한 Physical Memory address를 Virtual Memory의 LOADER_PHYS_BASE에 mapping한다.
    - 보호모드로 바뀐 후에는 Physical Memory 의 0-64MB 의 공간에 직접 접근해서 사용하는 것이 불가하므로 LOADER_PHYS_BASE 를 더한 커널 영역의 Virtual address 에 접근하여 사용하게 하기 위함이다.

profile
개발자(물리)

0개의 댓글