프로그래밍 언어로 구현되지 않은 경우 "시스템 호출"이란 무엇입니까?


14

"시스템 호출"이라는 용어를 이해하고 싶습니다. 시스템 호출은 사용자 공간 응용 프로그램에서 커널 서비스를 얻는 데 사용됩니다.

내가 명확히해야 할 부분은 "시스템 호출"과 "시스템 호출의 C 구현"의 차이점입니다.

나를 혼동하는 인용문은 다음과 같습니다.

유닉스 계열 시스템에서 해당 API는 일반적으로 glibc와 같은 C 라이브러리 (libc) 구현의 일부로, 시스템 호출에 랩퍼 기능을 제공하며, 종종 호출하는 시스템 호출과 동일

"시스템 호출"이란 무엇입니까? 그들의 출처는 어디입니까? 내 코드에 직접 포함시킬 수 있습니까?

일반적인 의미에서 "시스템 호출"은 POSIX 정의 인터페이스 일 뿐이지 만 실제로 구현을보기 위해 C 소스를 검사 할 수 있고 실제 사용자 공간에서 커널 통신까지 어떻게 진행되는지 볼 수 있습니까?

배경 참고 : 결국 각 c 함수가에서 장치와 상호 작용하는지 이해하려고합니다 /dev.

답변:


21

시스템 호출 자체 는 개념입니다. 프로세스가 커널에게 수행을 요청할 수있는 조치를 나타냅니다.

이러한 시스템 호출은 UNIX 계열 시스템의 커널에서 구현됩니다. 이 구현 (C로 작성되고 작은 부분에 대해서는 asm으로 작성 됨)은 실제로 시스템에서 조치를 수행합니다.

그런 다음 프로세스는 인터페이스를 사용하여 시스템에 시스템 호출의 실행을 요청합니다. 이 인터페이스는 POSIX에 의해 지정됩니다. 이것은 C 표준 라이브러리의 기능 세트입니다. 그것들은 실제로 래퍼 (wrapper)이며, 검사를 수행 한 다음 시스템 호출에 필요한 조치를 수행하도록 알려주는 커널의 시스템 특정 기능을 호출 할 수 있습니다. 트릭은 인터페이스 인 기능이 시스템 호출 자체와 동일하게 이름이 지정되며 종종 "시스템 호출"이라고도합니다.

시스템 별 메커니즘을 통해 시스템 호출을 직접 수행하는 커널에서 함수를 호출 할 수 있습니다. 문제는 코드가 이식성이 없다는 것입니다.

따라서 시스템 호출은 다음과 같습니다.

  • 개념, 커널이 사용자 프로세스에 서비스를 제공하기 위해 수행하는 일련의 동작
  • 커널에서이 서비스를 얻기 위해 코드에서 사용해야하는 C 표준 라이브러리의 기능

1
"래퍼 함수"의 예와 실제 시스템 호출이 있습니까? (리눅스의 파일 경로 또는 소스 링크)
TheMeaningfulEngineer

3
예를 들어, 이것은 getpidLinux 커널에서 시스템 호출을 구현 한 것입니다 : lxr.free-electrons.com/source/kernel/timer.c?v=2.6.35#L1337 . 그리고 이것은 GNU C 표준 라이브러리의 래퍼 함수는 glibc에-2.19 : fossies.org/dox/glibc-2.19/... .
lgeorget

@Igeorget : 더 이상 링크가 작동하지 않습니다. 커널 구현을위한 업데이트 링크 : github.com/torvalds/linux/blob/... . 요즘 glibc가 무엇을하는지 찾을 수 없었습니다.
rchard2scout

6

시스템 호출은 프로그램이 자체적으로 할 수 없어, 프로그램을 대신하여 몇 가지 작업을 수행하는 운영 체제 (커널)를 요청하는 방법입니다 (또는 불편). 일부 작업을 수행 할 수없는 이유는 일반적으로 임의의 프로그램이 작업을 수행하도록 허용하면 I / O 수행 (RAM에 직접, 모든 항목 덮어 쓰기)과 같이 시스템의 무결성을 손상시킬 수 있기 때문입니다.

POSIX는 프로그램을위한 인터페이스, 프로그램이 호출 할 수있는 특정 기능을 정의합니다. 그중 일부는 시스템 호출로 거의 또는 거의 직접적으로 번역되고 다른 일부는 더 정교화해야합니다. POSIX 인터페이스를 제공하고 인수를 패키지하고 호출자에게 직접 결과를받는 C 라이브러리와 같은 사용자 언어의 런타임입니다.

Unixy 시스템은 POSIX 인터페이스를 시스템 호출로 거의 직접 제공합니다. 일반적으로 시스템 호출을 직접 호출 syscall(2)하는 방법이 있습니다. Linux에서이 기능을 사용하는 방법에 대한 세부 사항을 찾으십시오 .


1
당신은 다른 답변이 막 칠하는 중요한 점을 만집니다. 합리적으로 할 수있는 프로그래머가 자신을 위해 쓸 수있는 기능 (예 : strlen, strcpy, sqrt,과 qsort) 될 수 있습니다 아마도 라이브러리에서로드, 사용자 공간입니다. (대부분 libc; sqrt삼각법 및 쌍곡선 함수와 같은 수학 함수 는 아마도 수학 라이브러리 인 libm에있을 것입니다.) ... (계속)
Scott

1
(계속)… 그러나 사용자가 자신의 fork, kill또는 open함수를 작성할 수있는 방법은 없습니다 . 왜냐하면 운영 체제 커널 메모리 공간 (예 : 프로세스 테이블) 또는 권한있는 명령 (예 : I / O)에 액세스해야하기 때문입니다. 따라서 이러한 기능을 수행하는 코드는 운영 체제 커널에 있어야합니다. 따라서 시스템 기능 또는 시스템 호출.
Scott

5

물론, 어떻게 많은 방향에서 우리가이 코끼리를 볼 수 있을까요? 의회.

실제 시스템 호출은 빌드 된 프로그램에서 권한을 에스컬레이션을 커널 모드로 트리거하는 기계 명령어이며, 커널 자체에서는 명령어가 호출하는 코드입니다. libc 코드 (및 모든 언어 런타임)는 커널 코드에서 찾을 수있는 머신 레지스터 및 스토리지 내 파라미터를 설정합니다.이 파라미터는 해당 머신 명령어의 제약으로 인해 결정적으로 홀수 일 수 있습니다.

OS 코드 자체에 들어가면, 유저 랜드 런타임이 수행 한 머신 고유의 것들에 대한 약간의 미러 이미지 풀림과 완벽하게 일반적인 서브 루틴 호출이 있습니다.
풀 스케일 OS에서 이것이 어떻게 작동하는지 정확히 보려면 ​​커널 소스 ( git clone https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/)를 당기고 예를 들어하십시오 git grep -i system\ call. glibc 소스를 당기고 마찬가지로 수행하십시오.


사실, 그러나 리눅스 나 glibc에서
엉망

3

리눅스에서 최소한 시스템 호출 메커니즘은 일부 레지스터 나 미리 정의 된 메모리 주소에 특정 형식의 데이터 (보통 어떤 종류의 c 구조체)를 배치함으로써 대부분의 아키텍처에서 작동합니다.

그러나 문제는 실제로 CPU가 커널 공간으로 전환하도록하여 권한있는 커널 코드를 실행하여 호출을 처리 할 수있게하는 것입니다. 이것은 일종의 결함 (0으로 나누는 결함, 정의되지 않은 오버플로 또는 segfault 등)을 강제로 수행하여 커널이 결함을 처리하기 위해 실행을 강제로 수행하도록합니다.

일반적으로 커널은 원인 프로세스를 종료하거나 사용자 제공 처리기를 실행하여 결함을 처리합니다. 그러나 syscall의 경우 사전 정의 된 레지스터와 메모리 위치를 대신 확인하고 syscall 요청이 포함 된 경우 메모리 내 구조체의 사용자 프로세스에서 제공 한 데이터를 사용하여 실행합니다. 이 작업은 일반적으로 특수하게 수작업으로 조립해야하며 시스템의 C 라이브러리가 함수로 래핑해야하는 사용자를 위해 syscall을 쉽게 사용할 수 있도록해야합니다. 낮은 수준의 인터페이스는 syscall의 작동 방식과 C 래퍼없이 호출 할 수있는 방법에 대한 정보는 http://man7.org/linux/man-pages/man2/syscall.2.html 을 참조 하십시오 .

이것은 지나치게 단순화 된 것으로 모든 아키텍처에서 적용되는 것은 아니며 (mips에는 특별한 syscall 명령어가 있음) 모든 OS에서 동일하게 작동하지는 않습니다. 그래도 의견이나 질문이 있으면 물어보십시오.

수정 : 참고 : / dev /의 것들에 대한 귀하의 의견과 관련하여 이것은 실제로 커널에 대한 상위 인터페이스가 아니라 하위 인터페이스입니다. 이 장치는 실제로 (약) 4 개의 시스템 콜을 사용합니다. 그들에게 쓰는 것은 쓰기 syscall, 읽기 syscall 읽기, 열기 및 닫기 syscall과 동등한 열림 / 닫기 및 ioctl을 실행하는 것 자체가 시스템의 많은 ioctl 중 하나에 액세스하기위한 인터페이스 인 특별한 ioctl syscall을 발생시킵니다. 호출 (일반적으로 사용량이 너무 좁은 장치 별 호출은 전체 시스템 호출을 작성하기에 너무 좁습니다).


1

모든 시스템 호출에는 연관된 정수가 있습니다. 이 정수는 시스템 호출의 반환 값, 시스템 호출에 대한 인수 수 및 인수 유형의 함수입니다. 이 시스템 호출 번호는 전역 시스템 호출 벡터에 대한 오프셋 일 뿐이며 권한 모드에서만 액세스 할 수있는이 벡터에는 적절한 처리기에 대한 포인터가 포함되어 있습니다. 시스템 호출을 호출 할 때 소프트웨어 인터럽트 (트랩 인터럽트)가 생성되므로 호출 할 시스템 호출을 결정하는 트랩 핸들러가 실행됩니다. 그런 다음 커널은 스택에있는 사용자가 전달한 시스템 호출의 인수를 프로세서 레지스터에 복사하고 요청 된 서비스를 완료하면 데이터가 프로세서 레지스터에서 스택으로 다시 복사됩니다. 이것이 시스템 호출에 대한 인수가 제한되는 이유 중 하나입니다.


각 호출 (작업)은 내부적으로 숫자 true로 식별됩니다. 그러나 숫자는 반환 값이나 인수 수가 아닌 연산 에 따라 다릅니다 . x86에서 userland에서 어떻게 작동했는지에 대한 설명이 여기 있습니다
vonbrand
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.