시스템프로그래밍

시스템프로그래밍(11) - ecf-procs

gilola 2024. 12. 14. 03:02

Exceptional Control Flow

-> process: 실행되고 있는 프로그램

-> 예외적인 제어 흐름이 필요

    -> 디스크나 네트워크로부터 데이터 도착

    -> 명렁어가 0으로 나눔

    -> 사용자가 Ctrl-C 입력

 

1, Execption (interrupt)

-> system event에 응답하여 flow 변경

2. Process context switch

-> Os & timer

3. Signal

-> Os

 

Exception

-> 특정 이벤트에 응답하여 kernel 로 제어가 전송

-> ex) 0으로 나누기, 산술 overflow, page fault, I/O 요청 완료...

-> exception handler는 SW에 의해 구현

 

Asynchronous Exception (외부 event)

-> interrupt pin이 설정됨

-> next 명령어로 제어가 반환

 

Synchronous Exception (명령어)

1.Trap

-> 의도적 변경

-> ex) system call

-> next 명령어로 제어 반환

2. Fault

-> 복구 가능할 수도 있음

-> ex) page fault

-> current 명령어 다시 실행하거나 프로그램 종료

3. Abort

-> 회복 불가능

-> ex) 잘못된 명령어

-> 프로그램 중단

 

System call

-> rax에 반환 값 저장

-> rax 값이 음수면 오류, errno

 

Page fault

-> 사용자가 메모리 위치에 data를 쓰려고 시도

-> 해당 영역은 실제 mem에 존재 x, disk에 저장

-> os가 mem에 옮겨 놔야 함

-> 사용자 process에 SIGSEGV 신호 보냄

-> segmentation fault를 출력하며 종료

 

Process

1. Logical contorl flow

-> 각 프로그램은 CPU 를 독점하는 것 처럼 보임

-> context switch

2. Private Address Space

-> 각 프로그램은 mem을 독점하는 것 처럼 보임

-> vm

 

단일 processor에서 다중 process 실행

-> multitasking (번갈아 가며 수행)

-> 비활성 reg의 값은 mem에 저장

 

Multicore processor

-> main mem과 일부 cache 공유

-> 각 코어가 별도의 process  실행

 

Context Switching

-> kernel에서 관리

-> tiner interrupt 발생

    1. backup

    2. schedule

    3. restore

 

System call error

-> 오류시 -1 반환

-> errno를 설정하여 원인 나타냄

 

Process 상태

1. Running 

-> 실행중 or 실행 대기

-> schedule의 대상

2. Stopped

-> 실행이 suspend

3.Terminated

-> 영구 중단

-> ppid에서 pid가 정상종료인지 error인지 확인

 

Process 종료

1. main에서 반환

2. exit 함수 호출

3. 종료 signal 수신

 

Exit 함수

-> void exit (int status)

-> status 값을 반환하며 종료

-> 정상 종료 = 0, 오류 != 0

-> exit 호출시 절대 반환되지 않음

 

Fork 함수

-> 부모가 fork 호출하여 자식 process 생성

-> 부모 process는 자식 PID 반환

-> 자식 process는 0 반환

-> 자식 process는 부모와 동일한 virtual address space, open file 지만 PID가 다름

-> 한 번 호출되지만, 두번 반환

-> 부모와 자식 실행 순서는 예츨 불가

-> 변경은 서로 독립적

 

Reaping Child Process

-> process 종료되면 여전히 리소스 낭비

-> 이러한 process를 zombie

-> wait 또는 waitpid 사용하여 부모가 종료된 자식을 처리

-> kernel은 이후 zombie 삭제

-> init에 의해 종료된 자식이 reap 될 수도있음

-> 부모 종료후에 자식이 계속 실행 중이라면 무기한 실행 상태 유지될 수 있음

 

 Wait (int * child_status)

-> child_staus 가 null 이 아니라면 자식 종료 이유와 상태를 나타냄

-> 부모가 자식을 수거하기 위해 호출

-> 자식 프로세스 중 하나가 종료될 때까지 기다림

-> return value는 종료된 자식 PID

 

Waitpid (pid_t pid, int* status, int options)

-> 특정 자식 프로세스 종료될 때까지 기다림

 

Execve (char *filename, char *argv[], char *envp[])

-> 현재 프로세스에서 새로운 실행 파일을 load 하고 exec

-> argv[0] = filename

-> envp는 환경 변수

-> code, data, stack 덮어씀

-> PID, open file, signal은 그대로 유지

-> 한 번 실행, 절대 반환되지 않음 (error시에는 반환)