본문 바로가기
cs/Operating System

System Call과 커널

by 펀구구 2023. 4. 21.

System Call

정의

  • 응용 프로그램의 요청에 따라 커널에 접근하기 위한 call이다. 일반 응용 프로그램은 직접적으로 커널에 접근할 수 없다.

필요한 이유

  • 특정한 작업은 해커가 시스템에 피해를 입힐 수도 있고 초보 프로그래머가 실수로 잘못 사용해서 시스템을 망가뜨릴 수 있다. 이를 예방하기 위해서 커널에서만 실행할 수 있는 작업을 따로 두고 있다.
  • System Call을 통해서 응용 프로그램은 하드웨어 장치를 사용할 수 있고 각종 자원을 할당 받을 수 있고 각종 작업을 할 수 있다.
  • 해당 system call이 적절한 system call인지 판단하고 적절한 system call이라고 판단되면 커널 모드로 진입한 후 필요한 작업을 한다.

사용되는 곳

  • 프로세스 제어
    • 프로세스 생성(create process)
    • 메모리 할당 및 해제 : malloc, free
  • 파일 조작
    • 파일 생성, 파일 삭제
    • 열기, 닫기
    • 읽기 쓰기
  • 장치 관리
    • 장치를 요구, 장치 방출
    • 읽기, 쓰기, 위치 변경
  • 정보 유지
    • 시간과 날짜의 설정과 획득
    • 시스템 데이터의 설정과 획득
  1. 응용 프로그램이 사용자 모드(user mode)에서 실행중이다.
  2. 응용 프로그램이 하드디스크, 입출력 장치 등 자원이 필요해지면 system call을 호출한다.
  3. 커널 모드로 전환되고 필요 자원이 반환 된다.
  4. 다시 사용자 모드로 전환되고 응용 프로그램이 계속 실행된다.

여러 system call

fork

  • 프로세스를 생성하고자 할 때 fork 함수를 사용하면 된다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(){
    
    pid_t pid;
    int x = 1;
 
    pid = fork();
    if(pid == 0){ /*Child*/
        printf("child: x=%d\\n", ++x);
        exit(0);
    }
 
    /*Parent*/
    printf("parent: x=%d\\n", --x);
    exit(0)

  • 자식 프로세스는 fork값을 0으로 받는다. 반면 부모 프로세스는 fork값으로 자식 프로세스의 pid를 받는다.
  • os는 똑같은 2개의 프로그램이 동작한다고 생각하고 fork()가 return될 차례라고 생각한다. 그래서 자식 프로세스도 if문으로 바로 들어간다.
  • print되는 순서는 cpu 스케줄링 순서에 따라서 다르다. 즉 실행마다 print순서가 다르다.

wait

  • child 프로세스가 종료될 때까지 기다리는 작업
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
    printf("pid : %d", (int) getpid()); // pid : 29146
    
    int rc = fork();					// 주목
    
    if (rc < 0) {
        exit(1);
    }									// (1) fork 실패
    else if (rc == 0) {					// (2) child 인 경우 (fork 값이 0)
        printf("child (pid : %d)", (int) getpid());
    }
    else {								// (3) parent case
        int wc = wait(NULL)				// 추가된 부분
        printf("parent of %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
    }
}
  • wait를 통해서 child 프로세스의 실행이 끝날 때까지 기다린다. 즉 출력 순서가 항상 동일하다.

exec

  • 단순 fork는 동일한 프로세스의 내용을 여러 번 동작할 때 사용한다.
  • child에서는 parent와 다른 동작을 하고 싶을 때 exec를 사용한다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
    printf("pid : %d", (int) getpid()); // pid : 29146
    
    int rc = fork();					// 주목
    
    if (rc < 0) {
        exit(1);
    }									// (1) fork 실패
    else if (rc == 0) {					// (2) child 인 경우 (fork 값이 0)
        printf("child (pid : %d)", (int) getpid());
        char *myargs[3];
        myargs[0] = strdup("wc");		// 내가 실행할 파일 이름
        myargs[1] = strdup("p3.c");		// 실행할 파일에 넘겨줄 argument
        myargs[2] = NULL;				// end of array
        execvp(myarges[0], myargs);		// wc 파일 실행.
        printf("this shouldn't print out") // 실행되지 않음.
    }
    else {								// (3) parent case
        int wc = wait(NULL)				// 추가된 부분
        printf("parent of %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
    }
}

  • execvp 이후 코드가 실행되지 않는다. 즉 print되지 않는다.
  • exec함수를 호출한 프로세스의 메모리 영역에 실행파일의 바이너리 이미지가 그대로 쓰여진다. 즉 기존 부모 프로세스는 소멸된 것으로 이해할 수 있다.

커널(kernel)

정의

  • 운영체제에서 프로세스에 자원 할당, 프로세스 제어, 메모리 제어, 시스템 콜 등을 다루는 부분
  • 커널은 운영체제에서 중요한 부분이므로 메모리에 올라가서 상주하게 된다.
  • 보안, 자원관리, 추상화

cpu 모드

  • 커널모드, 사용자모드 구분은 cpu 내부의 mode bit를 사용한다.

사용자 모드

  • 애플리케이션 코드가 실행되는데 이때 하드웨어에 접근할 수 없다. system call을 통해서 커널 모드로 전환돼야 하드웨어 자원을 사용할 수 있다.

커널 모드

  • 하드웨어 등 각종 자원을 접근할 수 있게 된다.

참고 - https://hongong.hanbit.co.kr/운영체제란-커널의-개념-응용-프로그램-실행을-위한/

https://code-lab1.tistory.com/39

'cs > Operating System' 카테고리의 다른 글

프로세스와 스레드(process and thread)  (0) 2023.04.18