시스템 호출의 목적은 시스템 서비스를 요청하는 것입니다. 운영체제에서는 사용자가 다양한 하드웨어 자원을 직접 조작하는 것을 허용하지 않기 때문에 사용자 프로그램은 시스템 호출을 통해서만 커널에 서비스를 요청하고 다양한 자원을 간접적으로 사용할 수 있다.
일반적으로 애플리케이션 자체에서는 불가능하지만 운영 체제에서 제공하는 기능입니다. 예를 들어, 파일을 조작하려면 애플리케이션이 시스템 호출을 해야 합니다. 운영체제에만 주변 장치를 직접 관리할 수 있는 권한이 있기 때문입니다. 또 다른 예는 커널 변수를 유지하기 위해 운영 체제에서 완료해야 하는 프로세스 또는 스레드 간의 동기식 상호 배제 작업입니다.
전체 컴퓨터 시스템을 아래에서 위로 살펴보세요. 물리적 하드웨어->OS 커널->OS 서비스->응용 프로그램. 여기서 OS 커널은 "이전과 다음을 연결"하는 데 핵심적인 역할을 하며, 아래쪽으로는 물리적 하드웨어를 관리하고 위쪽으로는 운영 체제 서비스 및 애플리케이션에 대한 인터페이스를 제공합니다.
응용 프로그램 프로세스는 일반적으로 시스템 호출을 호출하면 커널 모드로 들어가 커널 내부의 코드를 실행하므로 권한 있는 명령을 실행하고 특정 기능을 완료할 수 있는 권한을 갖습니다. 즉, 시스템 호출은 애플리케이션이 운영 체제 커널에 적극적으로 진입하는 입구입니다.
이름에서 알 수 있듯이 함수를 라이브러리에 넣는 것입니다. 일반적으로 사용되는 함수 몇 가지를 컴파일하여 파일에 넣는 것입니다. 다른 사람들이 사용할 수 있도록. 다른 사람들이 이를 사용할 때 일반적으로 lib 파일에 #include를 사용하여 파일 이름을 추가하기만 하면 됩니다.
라이브러리 기능은 주로 두 당사자에 의해 제공됩니다. 하나는 운영 체제에서 제공하고 다른 하나는 제3자에서 제공합니다.
시스템에서 제공하는 이러한 함수는 더 많은 기능을 달성하기 위해 시스템 호출을 캡슐화하거나 결합합니다. 이러한 라이브러리 함수는 커널에 대해 더 복잡한 일부 작업을 구현할 수 있습니다. 예를 들어 읽기 기능은 매개변수를 기반으로 파일을 직접 읽을 수 있지만, 어떤 트랙, 어떤 섹터, 어떤 메모리가 로드되는지 등 그 뒤에 숨겨진 파일은 프로그래머가 걱정할 필요가 없는 문제입니다. 이러한 작업에는 시스템 호출도 포함됩니다. 예를 들어, write() 시스템 함수는 쓰기 작업을 완료하기 위해 동일한 이름의 시스템 호출을 호출합니다.
타사 라이브러리의 경우 시스템 호출을 직접 사용할 가능성이 적지만 시스템에서 제공하는 API 인터페이스를 통해 구현된다는 점을 제외하면 실제로 시스템 라이브러리와 동일합니다. 예를 들어 printf는 실제로 write() 시스템 함수를 호출합니다. 대부분의 타사 라이브러리 기능은 시스템 기능을 캡슐화합니다.
시스템 호출과 라이브러리 기능의 연결:
실제로 시스템 호출은 사용자에게 보다 인간적이고 특정 상황에 더 적합한 서비스를 제공합니다. 함수는 사용자가 정의해야 하므로 일부 시스템 호출을 래핑하는 라이브러리 함수가 파생됩니다. 예를 들어, C 언어로 문장을 인쇄하려는 경우 라이브러리 함수 printf가 사용되지 않으면 이를 직접 구현하고 putc() 및 write()와 같은 일부 시스템 함수를 호출해야 합니다. 더 귀찮은 것 같아서 시스템콜은 운영체제 인터페이스 사용의 편의를 위한 것이고, 라이브러리 함수는 사람들의 프로그래밍 편의를 위한 것입니다.
예를 들어 Linux 운영 체제에서 C 언어 라이브러리 함수 printf는 실제로 쓰기 시스템 호출을 사용하는 반면 라이브러리 함수 strcpy(문자열 복사)는 시스템 호출을 사용하지 않습니다. 또한 시스템의 시스템 호출 인터페이스는 일반적으로 필요한 모든 기능을 완료할 수 있는 가장 작은 집합입니다. 동일한 시스템 호출을 캡슐화하는 여러 라이브러리 함수가 있을 수 있습니다. 예를 들어 Linux에서는 세 가지 라이브러리 함수 malloc, calloc 및 free가 모두 brk 시스템 호출을 호출하여 완료됩니다.
애플리케이션, 라이브러리 기능 및 시스템 호출 간의 관계는 아래 그림에 표시됩니다.
시스템 호출과 라이브러리 기능의 차이점:
라이브러리 기능에 대한 호출은 언어 또는 애플리케이션의 일부입니다. , 시스템 호출은 운영 체제의 일부입니다.
시스템 호출은 애플리케이션이 커널과 상호 작용하기 위한 인터페이스입니다. 장기 프로그래밍에서 사람들은 시스템 기능을 사용하면 프로그램의 이식성이라는 큰 단점이 있다는 것을 발견했습니다. 예를 들어 Linux에서 제공하는 시스템 호출 기능은 Windows의 시스템 호출 기능과 다릅니다.
라이브러리 함수 호출은 응용 프로그램의 API와 동일한 응용 프로그램 개발을 위한 것입니다. 이 접근 방식을 채택하는 데는 여러 가지 이유가 있습니다.
모드 및 사용자 모드
일반적으로 프로세서에는 "사용자 모드"와 "커널 모드"의 두 가지 모드가 있습니다. 태그 비트는 현재 어떤 모드에 있는지 식별하는 데 사용됩니다. 커널 모드는 특권 명령어(주로 기본 주소 레지스터의 내용을 수정하는 명령어와 같은 일부 하드웨어 관리 명령어)를 포함한 모든 명령어를 실행할 수 있는 반면, 사용자 모드는 특권 명령어를 실행할 수 없습니다. 이 설계는 주로 보안 문제를 위한 것입니다. 즉, 운영 체제는 상위 계층 응용 프로그램의 잘못된 설계로 인해 발생하는 하드웨어 문제를 방지하기 위해 하드웨어를 관리하는 역할을 담당합니다.
운영 체제만이 하드웨어를 직접 작동할 수 있으므로, 운영 체제는 애플리케이션이 하드웨어 기능에 접근할 수 있도록 인터페이스를 제공해야 합니다. 이러한 인터페이스를 시스템 호출이라고 합니다.
운영 체제가 시스템 호출 요청을 받으면 프로세서는 커널 모드로 들어가 I/O 작업과 같은 명령을 수행하고 시스템 호출 내용을 처리한 후 기본 주소 레지스터의 내용을 수정합니다. 프로세서가 사용자 모드로 돌아가 사용자 코드를 실행하도록 합니다.
CPU의 커널 모드와 사용자 모드에 해당합니다. 프로세스의 실행 상태는 튜브 상태(코어 상태)와 아이 상태(사용자 상태)로 구분됩니다. 자세한 내용은 운영 체제 - 사용자 모드 및 커널 모드
인터럽트는 일반적으로 CPU 내부 또는 외부에서 발생하는 보류 중인 이벤트를 나타냅니다. CPU는 이러한 이벤트를 처리하기 위해 현재 명령어의 실행 순서를 변경해야 합니다. 인터럽트와 시스템 호출의 관계를 소개하기 전에 먼저 인터럽트를 분류해 보겠습니다.
인터럽트는 대략 두 가지 범주로 나눌 수 있습니다.
비동기 인터럽트(외부 인터럽트): 이러한 유형의 인터럽트는 비동기식이라고 하며, 이는 인터럽트 신호가 CPU 자체의 클럭 비트와는 아무 관련이 없습니다. 시계 중단, 하드 디스크 읽기 및 쓰기 서비스 요청 중단 등
동기 인터럽트(내부 인터럽트/예외): CPU 내부에서 생성됩니다. 이러한 유형의 인터럽트는 동기식이라고 합니다. 즉, 인터럽트 신호의 방출 시간은 현재 명령어 실행 이후여야 합니다. 완료되었습니다. 일반적으로 이러한 오류는 CPU 내부 이벤트나 프로그램 실행 중 잘못된 opcode, 범위를 벗어난 주소, 부동 소수점 오버플로 등의 이벤트에서 발생합니다.
동기 인터럽트(예외)는 다음 범주로 나뉩니다.
프로세서 감지 예외: 0으로 나누기 작업과 같은 명령어를 실행할 때 프로세서가 감지한 인터럽트입니다.
Faults: 비정상적인 조건이 발생했지만 비정상적인 조건이 제거된 후 페이지 누락 예외와 같은 영향 없이 원래 프로그램 흐름이 계속 실행될 수 있습니다. 인터럽트를 트리거한 명령이 다시 실행된다는 점에 유의하세요.
Traps: 트랩된 명령어로 인한 인터럽트로, 일반적으로 프로그램 디버깅에 사용됩니다.
Aborts: 하드웨어 오류나 시스템 테이블 값 오류 등 CPU 내부에서 중요한 오류가 발생합니다. 이러한 중단이 발생하면 오류는 복구할 수 없으며 현재 프로세스는 종료만 가능합니다.
프로그램된 예외: 소프트웨어 인터럽트(소프트 인터럽트)라고도 알려져 있으며, 시스템 호출을 구현하기 위해 프로그래머의 코드에 의해 적극적으로 시작된 인터럽트입니다. 예를 들어 Linux에서는 int 0x80
명령이 시스템 호출을 구현하는 데 사용됩니다. int 0x80
指令实现系统调用。
至此,我们发现了中断与系统调用的关系:系统调用是一种特殊的中断类型(软中断)。
五、内核对于系统调用的处理
在x86的机器中,用一个8bit的数字(0~255)来区分各种中断,这个数字被称为中断向量(vector)。其中一个中断向量,即128 (0x80),专门被用于执行系统调用。
在Linux系统中,存有一个系统表,叫做Interrupt DescriptorTable,简称IDT。IDT表共有256项,存放了从中断向量到相应处理例程(interrupt or exceptionhandler)的映射关系。当某个中断发生时,CPU从IDT表中查找到相应的处理例程的地址来执行。
系统调用的处理例程在IDT表中占有一项。这一项是在trap_init函数中被初始化的,如下:set_system_gate(SYSCALL_VECTOR,&system_call);
시스템 호출은 특별한 유형의 인터럽트(소프트 인터럽트)
입니다.5. 시스템 호출의 커널 처리
🎜🎜🎜x86 시스템에서는 8비트 숫자(0~255)를 사용하여 다양한 인터럽트를 구분합니다. 인터럽트 벡터라고 합니다. 인터럽트 벡터 중 하나인 128(0x80)은 특히 시스템 호출을 실행하는 데 사용됩니다. 🎜🎜리눅스 시스템에는 Interrupt DescriptorTable, 줄여서 IDT라는 시스템 테이블이 있습니다. IDT 테이블에는 256개의 항목이 있으며, 여기에는 인터럽트 벡터에서 해당 처리 루틴(인터럽트 또는 예외 처리기)으로의 매핑 관계가 저장됩니다. 인터럽트가 발생하면 CPU는 IDT 테이블에서 해당 처리 루틴의 주소를 찾아 실행한다. 🎜🎜시스템 호출 처리 루틴은 IDT 테이블의 항목을 차지합니다. 이 항목은set_system_gate(SYSCALL_VECTOR,&system_call);
과 같이 Trap_init 함수에서 초기화됩니다. 앞서 언급했듯이 위 코드에서 SYSCALL_VECTOR의 값은 128이다. 🎜🎜시스템 호출이 발생하면 인터럽트 메커니즘을 통해 시스템 호출 루틴 system_call이 호출됩니다. 실행 프로세스는 대략 4단계로 나뉩니다. 🎜🎜1. 레지스터에서 시스템 호출 번호와 입력 매개변수를 가져온 다음 이 레지스터의 값을 커널 스택에 푸시합니다. 시스템 콜 번호에 따라 시스템 콜 디스패치 테이블을 검색하여 시스템 콜 서비스 루틴(커널 함수)을 찾는다. 🎜🎜2. 발견된 시스템 호출 서비스 루틴을 호출합니다. 🎜🎜3. 시스템 호출 서비스 루틴의 반환 값을 스택에서 꺼내어 레지스터에 다시 저장합니다. 🎜위에서 설명한 시스템 호출 루틴 system_call은 커널 공간에서 실행됩니다. 실행 전 시스템 호출 번호와 입력 매개변수는 레지스터에 저장되며 이 저장 과정은 사용자 공간 코드에 의해 완료된다. 실제로 첫 번째 섹션에서 언급했듯이 모든 실제 시스템 호출에는 기본적으로 이를 캡슐화하는 라이브러리 함수가 있습니다. 일반적으로 이 라이브러리 함수에는 시스템 호출 번호와 입력 매개변수가 저장됩니다. 시스템 호출 루틴 system_call이 실행되면 반환 값은 레지스터를 통해 사용자 공간 라이브러리 함수로 다시 전달됩니다.
위 내용은 시스템 호출의 목적은 무엇입니까의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!