YJcode :: YJcode

라이브러리 함수는 표준 C 라이브러리를 구성하는 수많은 함수 가운데 하나일 뿐이다. 라이브러리 함수의 목적은 매우 다양해서, 파일을 연다든지, 시간을 사람이 읽을 수 있는 형태로 바꾼다든지, 문자열 2개를 서로 비교한다든지 하는 것들이 모두 포함된다.

상당수의 라이브러리 함수는 시스템 호출을 전혀 사용하지 않는다. 반면에 시스템 호출을 써서 구현된 라이브러리 함수도 있따. 예를 들어, fopen() 라이브러리 함수는 실제로 파일을 열기 위해 open() 시스템 호출을 사용한다. 라이브러리 함수는 종종 하부의 시스템 호출보다 사용하기 편리한 인터페이스를 제공하도록 설계됐다. 예를 들어 printf() 함수는 출력 서식과 데이터 버퍼링을 제공하지만, write() 시스템 호출은 단지 한 블록의 바이트를 출력할 뿐이다. 마찬가지로 malloc() 과 free() 함수는 다양한 관리 작업을 수행해서 이를 이용하면 하부의 brk() 시스템 호출보다 훨씬 쉽게 메모리를 할당하고 해제할 수 있다.

 

시스템 호출은 커널로의 관리된 진입점으로서, 이를 통해 프로세스가 커널에게 프로세스 대신 어떤 동작을 수행하도록 요청할 수 있다. 커널은 시스템 호출 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를 그 값으로 설정한다. 래퍼 함수는 그 다음에 시스템 호출의 성공 여부를 나타내는 정수 리턴값을 제공하면서 호출 함수로 리턴한다.

 

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

리눅스는 유닉스와 마찬가지로 /proc 파일 시스템을 제공한다. /proc 파일 시스템은 /proc 디렉토리에 마운트된 디렉토리와 파일로 이뤄져있다.

/proc 파일 시스템은 엄연히 따지면 실제로 존재하는 파일은 아니고, 커널 데이터 구조를 파일 시스템상의 파일과 디렉토리 형태에 대응하여 가상으로 파일화 한 인터페이스이다. 많은 이들이 이를 리눅스의 대표적인 특징으로 들고 있다.

/proc 파일 시스템은 다양한 시스템 시스템 속성을 보고 변경할 수 있는 손쉬운 방법을 제공한다. 또한 /proc/PID라는 디렉토리를 통해 커널위에서 운영중인 모든 프로세스에 대한 정보를 확인할 수 있다.

/proc 파일의 내용은 일반적으로 사람이 읽을 수 있는 텍스트 형태이고, 쉘 스크립트로 파싱할 수 있다. 프로그램에서 원하는 파일을 쉽게 열고, 읽거나 쓸 수 있다. 대부분의 경우 /proc 디렉토리의 파일을 수정하기 위해서는 프로세스가 권한 을 가지고 있어야 한다.

+ Recent posts