1.시스템 호출 :: YJcode

시스템 호출은 커널로의 관리된 진입점으로서, 이를 통해 프로세스가 커널에게 프로세스 대신 어떤 동작을 수행하도록 요청할 수 있다. 커널은 시스템 호출 API를 통해 광범위한 서비스를 제공한다. 이 서비스에는, 예를 들어 새로운 프로세스 생성, 프로세스간 통신용 파이프 생성 등이 있다.

시스템 호출이 동작하는데 있어 일반적이 사항은 다음과 같다.

 

  • 시스템 호출은 프로세서의 상태를 사용자 모드에서 커널 모드로 변경해서 CPU가 보호된 커널 메모리에 접근할 수 있게 한다.
  • 시스템 호출 목록은 고정되어 있다. 각 시스템 호출에는 고유한 숫자가 붙어있다.
  • 각 시스템 호출은 사용자 공간에서 커널공간으로 가져올 정보를 나타내는 인자를 포함할 수 있다.

 

프로그래밍 관점에서 시스템 호출은 C 함수 호출과 매우 비슷하다. 하지만 막후에서는 시스템 호출을 실행하는 동안 여러 단계를 거치게 된다. 이를 보여주기 위해, 여기서는 특정 하드웨어(x86-32)상에서의 발생 순서를 따라가 보겠다.

 

  1. 응용 프로그램이 C 라이브러리의 래퍼 함수를 호출해서 시스템 호출을 한다.
  2. 래퍼 함수는 시스템 호출의 모든 인자를 시스템 호출 트랩 처리 루틴에게 전달해야 한다. 이 인자는 스택을 통해 래퍼에게 전달되지만, 커널에게 전달하려면 특정 레지스터에 넣어야 한다. 래퍼 함수는 인자를 이 레지스터로 복사한다.
  3. 모든 시스템 호출이 같은 방법으로 커널에 진입하므로, 커널은 시스템 호출을 식별하는 방법이 필요하다. 이를 위해 래퍼 함수는 시스템 호출 번호를 특정 CPU 레지스터에 복사해넣는다.
  4. 래퍼 함수는 트랩 기계어 명령을 실행하고, 이는 프로세서를 사용자 모드에서 커널 모드로 전환해 시스템의 트랩 벡터 0x80 이 가리키는 코드를 실행한다.
  5. 0x80 트랩을 처리하기 위해, 커널은 system_call() 루틴을 호출한다. 이 핸들러는

    a) 레지스터 값들을 커널 스택에 저장한다.
    b) 시스템 호출 번호가 유요한지 확인한다.
    c)적절한 시스템 호출 서비스 루틴을 호출한다. 시스템 호출 서비스 루틴은 시스템 호출 번호를 시스템 호출 서비스 루틴 테이블에 대한 인덱스로 삼아서 찾는다.시스템 호출 서비스 루틴이 인자가 있으면 먼저 유효성을 확인한다. 예를 들어, 해당 주소가 사용자 메모리의 유효한 위치를 가리키는지 확인한다. 그 다음에 서비스 루틴이 필요한 작업을 수행하는데, 이 과정에서 인자가 가리키는 주소의 값을 변경하거나 사용자 메모리와 커널 메모리 사이에 데이터를 전송할 수도 있다. 마지막으로 서비스 루틴은 결과 샅애를 system_call() 루틴에게 리턴한다.
    d) 커널 스택에서 레지스터 값들을 복원하고 시스템 호출 리턴값을 스택에 넣는다.
    e) 래퍼 함수로 돌아오면서, 동시에 프로세서도 사용자 모드로 되돌린다.

  6. 시스템 호출 서비스 루틴의 리턴값이 에러를 나타내면, 래퍼 함수는 전역 변수 errno를 그 값으로 설정한다. 래퍼 함수는 그 다음에 시스템 호출의 성공 여부를 나타내는 정수 리턴값을 제공하면서 호출 함수로 리턴한다.

 

위의 내용을 모두 이해해야 시스템 프로그램이 가능한 것은 아니다. 하지만 매우 간단한 시스템 호출이다로 상당량의 작업이 필요하므로, 시스템 호출에는 작지만 주목할 만한 오버헤드가 있다는 점을 유의해야 한다.

+ Recent posts