처리 도중 타임슬라이스가 끝나거나, 다른 이유로 context switch가 일어나야할 때, 디스패처를 호출한다.
system call | Interrupt | |
---|---|---|
처리 도중 context switch | O | X (반드시 단기간에 완료해야 함) |
context switch가 일어나는 위치
- 시스템 콜 실행 중
- 시스템 콜 완료 후
- 인터럽트 완료 후
인터럽트 처리 중에는 절대 context switch가 일어나지 않는다 !!
context switch는 반드시 커널 모드 수행 시에 이루어지므로 프로세스는 반드시 커널 안에서 죽고 커널 안에서 살아난다.
프로세스 리스트
를 형성함.프로세스 컨텍스트는 크게 세 부분으로 구성된다.
컨텍스트 세이브란, 현재 프로세스를 실행하는 과정에서 생겨난 프로세서 레지스터들의 값(eip, eflags, eax, ...)을 PCB에 저장하는 일을 말한다.
컨텍스트 리스토어란, 프로세스의 수행 정보를 프로세서 레지스터에 복원하는 과정이다.
context switch를 하는 과정 중에 컨텍스트 세이브와 컨텍스트 리스토어가 일어나야 한다.
프로세스 컨텍스트 = 유저 컨텍스트(user context) + 시스템 컨텍스트(system context)
유저 스택과 커널 스택에 저장되는 정보와 용도는 동일하다.
fork() 시스템 콜을 호출하면, 해당 프로세스와 동일한 유저 컨텍스트를 갖는 새로운 프로세스를 생성한다. - 공유하지 않는다.
실행가능 파일인 a.out을 실행시키면, a.out의 구성 요소인 텍스트, 데이터, 스택 영역 정보를 복사해서 프로세스가 만들어 진다. 따라서, 프로세스도 텍스트, 데이터, 스택 영역으로 이루어지며 이들을 프로세스의 유저 컨텍스트라고 한다.
각 프로세스는 버추얼 어드레스 스페이스(virtual address space)라고 불리는 가상의 4GB 주소공간이 보조기억장치에 만들어진다.
보조기억장치에 실제 4GB를 할당하는 것이 아니라, 데이터나 스택 과같은 일부만 보조기억장치에 할당하고 다른 영역은 정보만 유지한다. 코드는 이미 있는 코드 부분을 공유하고, 커널은 RAM에 있는 것을 매핑함으로써 있는척한다. 또한, 각 영역의 시작과 끝 주소를 PCB에 저장하여 있는 척을 하는 것이다.
즉, 실제로 디스크에는 코드, 데이터, 스택 만이 있고 커널은 메모리에 있다.
여기서 0~3GB는 유저 컨텍스트, 나머지 3~4GB는 커널. 이 커널 부분 또한 프로세스 주소공간의 일부이므로 사용자 프로세스가 접근할 수 있다. 해당 커널 부분을 실행하는 동안은 커널 모드 또는 시스템 모드에서 실행한다고 부른다. 커널 모드로 변경하는 것을 모드 체인지라고 부르는데, 커널 역할을 하는 별도의 프로세스가 있는 것이 아니라 사용자 프로세스가 필요시 커널로 변신해 운영체제를 실행하기 때문에 커널이 프로세스 공간의 일부로 간주하는 것이다. 커널 자체는 메모리에 하나 밖에 없고, 이 커널 하나가 각 프로세스의 3G~4G 영역에 매핑되는 것이다.
프로세스 A 가 User 모드에서 작동하다가 시스템콜이나 인터럽트에 의해 커널모드로 진입시에는 유저모드에서의 레지스터 컨텍스트가 프로세스 A 의 커널스택에 저장되고, 커널스택에 저장되어있던 프로세스 A 의 커널모드 레지스터 컨텍스트가 복원된다.
프로세스 A 가 Context Switching 을 할때는 이미 프로세스 A 가 반드시 커널모드인 상태이다. 이 경우는 프로세스 A 의 커널모드 레지스터 컨텍스트가 메모리에 저장되면서 다음번 스케줄될 프로세스 B 의 레지스터 컨텍스트(커널모드의) 가 복원된다
유저 프로세스가 돌다가 갑자기 한번에 스케줄이되서 프로세스 B 로 넘어가는것 같지만 정확한 순서는
- 유저프로세스 A 가 커널모드로 진입하면서 유저모드 레지스터 컨텍스트를 A 의 커널스택에 저장
- 프로세스 A 는 커널컨텍스트를 가진상태로 Schedule 을 호출
- A 의 커널컨텍스트가 메모리에 저장되고 프로세스 B 의 저장된 커널컨텍스트를 레지스터에 복원
- B 의 커널컨텍스트가 메모리에 저장되면서 B 의 유저컨텍스트를 레지스터에 복원하면서 유저모드로 리턴
프로세스에 대한 정보를 담는 자료구조 PCB 만들기.
지금 만들어지는 PCB를 기존 프로세스들의 PCB와 연결. (프로세스 리스트)
pstree
로 init 프로세스(1번) 밑의 프로세스들을 확인할 수 있다.유저 컨텍스트 생성.
구성된 프로세스를 레디 큐에 넣는다. (레디 큐에 들어간 PCB와 자식 프로세스의 PCB를 연결)
부모 프로세스에게 fork()의 실행 결과로서 자식 프로세스의 프로세스 아이디 값을 리턴해준다.
COW(Copy On Write)
자식 프로세스용 데이터 영역과 스택 영역을 복사하는 일을 최대한 뒤로 미룬다. 데이터, 스택까지 공유하다가 값을 바꾸게될 때, 복사하여 쓴다.
death-of-child
시그널을 보낸다wait()
시스템 콜을 부르면 없어진다. (좀비는 init이 없애준다)메세지를 보내거나 받을 때 모드 체인지를 해야하기 때문에 시간이 오래 걸린다.
fork
함으로써 프로세스를 만든다.메세지 패싱 | 쉐어드 메모리 | |
---|---|---|
장점 | 편리 | 빠르다 (각 프로세스의 가상주소공간 유저 영역에 있음) |
단점 | 오래 걸린다 (커널에 있어 모드체인지 많이 필요) | 프로세스간 동기화(시그널, 세마포어, 락)가 필요하여 프로그래밍하기 어렵다 (충돌 방지) |
이벤트가 발생했을 때 프로세스에게 알리는 방법.
I/O 인터럽트는 HW장치에서 이벤트가 발생하면 OS에게 알리는 것
인터럽트나 트랩은 커널(OS)에게 알리는데, 시그널은 일반 프로세스에게도 알릴 수 있다. 물론 커널을 통해서.
쓰레드는 프로세스 내부 실행단위이다.
쓰레드가 실행되는데 직접적으로 필요한 것은 스택과 CPU 레지스터 값들을 저장하기 위한 메모리 공간이다.
3 개의 프로세스로 구현할 경우 IPC를 해야하므로 오래 걸리고, 자원도 많이 낭비한다. (code, data, files 중복)
쓰레드가 생성될 때 레지스터 값이 저장되는 공간과 스택을 만들어야 한다.
유저 레벨 쓰레드
커널 레벨 쓰레드
유저 레벨 쓰레드 | 커널 레벨 쓰레드 | |
---|---|---|
장점 | 커널 레벨 쓰레드 기능을 제공하지 않는 OS에서도 사용 가능 빠르다 사용자가 스케줄링을 제어 가능 - 유저모드 이므로 | 동시수행성 GOOD |
단점 | 동시수행성이 크게 제약됨 - 커널 입장에선 그냥 프로세스 하나일 뿐 | 느리다 |
출처 : https://daehee87.tistory.com/473
Context 스위칭과 kernel-user 모드체인지는 다르다. 두가지 경우 모두 현재 레지스터 컨텍스트를 메모리에 저장함과동시에 기존에 저장해놨던 레지스터 컨텍스트를 메모리로부터 복원한다는 점이 동일해서 햇갈리기가 쉬운데, 둘을 잘 구분할 필요가 있다.
Context 스위치는 프로세스간 실행. 모드 체인지는 하나의 프로세스 안에서 쓰레드간 실행.
프로세스 A 가 User 모드에서 작동하다가 시스템콜이나 인터럽트에 의해 커널모드로 진입시에는 유저모드에서의 레지스터 컨텍스트가 프로세스 A 의 커널스택에 저장되고, 커널스택에 저장되어있던 프로세스 A 의 커널모드 레지스터 컨텍스트가 복원된다.
프로세스 A 가 Context Switching 을 할때는 이미 프로세스 A 가 반드시 커널모드인 상태이다. 이 경우는 프로세스 A 의 커널모드 레지스터 컨텍스트가 메모리에 저장되면서 다음번 스케줄될 프로세스 B 의 레지스터 컨텍스트(커널모드의) 가 복원된다.
즉 유저 프로세스가 돌다가 갑자기 한번에 스케줄이되서 프로세스 B 로 넘어가는것 같지만 정확한 순서는
유저프로세스 A 가 커널모드로 진입하면서 유저모드 레지스터 컨텍스트를 A 의 커널스택에 저장
프로세스 A 는 커널컨텍스트를 가진상태로 Schedule 을 호출
A 의 커널컨텍스트가 메모리에 저장되고 프로세스 B 의 저장된 커널컨텍스트를 레지스터에 복원
B 의 커널컨텍스트가 메모리에 저장되면서 B 의 유저컨텍스트를 레지스터에 복원하면서 유저모드로 리턴