언어는 어떻게 확장됩니까? [닫은]


208

C ++을 배우고 있으며 GUI 프로그램을 코딩 하는 Qt 의 기능 중 일부에 대해 배우기 시작했습니다 . 나는 나 자신에게 다음과 같은 질문을했다.

이전에 OS에 창을 요구하거나 네트워크를 통해 통신하는 방법을 요구할 수있는 구문이 없었던 C ++ (어떻게도 완전히 이해하지 못하는 API로) 은 C ++ 자체로 작성된 라이브러리를 통해 그러한 기능 갑자기 얻는가 ? 그것은 나에게 정말 원형 인 것 같습니다. 해당 라이브러리에서 어떤 C ++ 명령어를 만들 수 있습니까?

이 질문은 숙련 된 소프트웨어 개발자에게는 사소한 것처럼 보이지만 직접 응답을 찾지 않고 몇 시간 동안 연구 해 왔습니다. 라이브러리의 존재가 이해할 수 없기 때문에 Qt에 대한 자습서를 따를 수없는 시점에 도달했습니다.


27
std :: cout은 어떻게 모니터에 무언가를 그리나요? 아니면 하드웨어를 이해하는 컴파일러 위에 있습니까?
doctorlove

14
좋은 질문입니다. 궁극적으로 하드웨어를 공부하기 전까지는 대답하기가 어렵습니다.
user541686

17
Qt는 언어 의 확장이 아닙니다 (Qt 인식 컴파일러가 필요한). 단지 당신의 무기고에 추가 된 라이브러리 입니다. 결국 가장 낮은 수준에서 모든 라이브러리는 언어와는 독립적이지만 OS 및 CPU 아키텍처에 크게 의존하는 시스템 호출을 통해 OS와 통신합니다.
DevSolar

8
afaik, C ++에는 인라인 어셈블리가있어 거의 모든 작업을 수행 할 수 있습니다.
표시 이름

9
@DevSolar : 실제로 Qt는 자체 신호 슬롯 메커니즘, 리플렉션 및 기타 다양한 동적 기능으로 언어를 확장합니다. 그리고 그러한 것들에는 C ++ 코드로 컴파일하기 위해 컴파일러 (메타 객체 컴파일러)가 필요합니다.
Siyuan Ren

답변:


194

컴퓨터는 양파와 같습니다. 순수한 하드웨어의 내부 코어에서 가장 바깥 쪽의 응용 계층에 이르기까지 많은 계층이 있습니다. 각 층은 그 자체의 일부를 다음 외부 층에 노출 시키므로, 외부 층은 내부 층 기능 중 일부를 사용할 수있다.

예를 들어 Windows의 경우 운영 체제는 Windows에서 실행되는 응용 프로그램에 대해 WIN32 API를 노출합니다. Qt 라이브러리는 해당 API를 사용하여 Qt를 사용하는 애플리케이션을 자체 API에 제공합니다. Qt를 사용하고, Qt는 WIN32를 사용하고, WIN32는 하드웨어의 전기 신호가 될 때까지 낮은 수준의 Windows 운영 체제를 사용합니다.


56
참고 : Qt여기에 제공 추상화 때문에 리눅스에, 그 아래 층의은 Qt리눅스 API가 아닌 WIN32 API를 호출합니다.
Matthieu M.

5
나는 아마도 Qt의 예에 대해 조금 더 elaboarte 할 것입니다 .c ++ 기능을 쉽게 확장하는 것처럼 방금 나타납니다. 실제로는 공통 API를 만들기 위해 많은 다른 "양파 코어"에 많은 노력을 기울였습니다. 이식 불가능한 비표준 백엔드에서 이식성을 제공하는 것입니다.
luk32

81
컴퓨터는 양파와 같습니다. 컴퓨터를 자르면 울게되지만 나중에는 약간 맛있습니다.
alecov

3
@ChristopherPfohl 그래, 컴퓨터가 어떻게 초콜렛 상자와 같은지 알 수 없었기 때문에 그것을 사용해야했습니다. :)
일부 프로그래머 친구

1
@Celeritas 선생님은 아마 user32.dll, 또는 가능 하다고 말했다 gdi32.dll.
user253751

59

일반적으로 라이브러리는 아직 불가능한 것을 만들 수 없습니다.

그러나 C ++ 프로그램에서 사용할 수 있도록 라이브러리를 C ++로 작성할 필요는 없습니다. C ++로 작성 되었더라도 내부적으로 C ++로 작성되지 않은 다른 라이브러리를 사용할 수 있습니다. 따라서 C ++이 할 수있는 방법을 제공하지 않았다고해서 추가되는 것을 막을 수는 없습니다. 일부 ++ C 외부에서 작업을 수행하는 방법.

상당히 낮은 수준에서 C ++ (또는 C)에 의해 호출 된 일부 함수는 어셈블리로 작성되며, 어셈블리에는 C ++에서 불가능하거나 쉽지 않은 것을 수행하는 데 필요한 명령 (예 : 호출)이 포함됩니다. 시스템 기능. 이 시점에서 시스템 호출은 컴퓨터가 멈추는 것이 없기 때문에 컴퓨터가 할 수있는 모든 것을 할 수 있습니다.


다른 언어로 작성된 라이브러리가 이미 다른 컴파일러를 사용하여 컴파일 되었습니까? 그리고 라이브러리에 의해 C ++에 제공된 각 함수 호출을 미리 컴파일 된 버전의 라이브러리에 연결하는 일종의 인터페이스 파일이 있어야합니까? 따라서 C ++ 컴파일러가 이러한 호출을 무엇으로 변환해야하는지 알 수 있습니다.
Med Larbi Sentissi

2
@MedLarbiSentissi 1) 반드시 다른 컴파일러는 아닙니다. 하나의 단일 컴파일러가 어셈블리를 포함하여 여러 언어를 컴파일 할 수 있으며 인라인 어셈블리를 사용하여 C ++를 컴파일 할 수도 있습니다. 2) 특정 시스템 및 컴파일러에 따라 C ++에서 호출 가능한 함수를 실제로 일종의 인터페이스 파일로 수행 할 수 있지만 해당 인터페이스 파일은 이미 C ++에서 직접 사용할 수있는 C (또는 C ++) 헤더 일 수 있습니다.

1
@MedLarbiSentissi : 많은 Windows 라이브러리는 코드뿐만 아니라 자체 인터페이스를 포함하는 dll 파일로 컴파일됩니다. dll을 들여다 볼 수 있으며 사용할 수있는 기능 목록을 볼 수 있습니다. 그들은 종종 C 헤더 파일과 함께 제공됩니다. exe를 만들 때 실행해야하는 dll 목록이 포함됩니다. OS가 exe를로드하려고하면 실행을 시작하기 전에 해당 dll도 자동으로로드합니다.
Mooing Duck

8
이 답변은 "매직"이 다른 언어로 번역 된 것이지만 실제로 대부분의 최신 운영 체제를 구성하는 대부분 의 코드 는 C (어셈블리로 작성된 하드웨어 연결 또는 성능에 중요한 부분 만 있음)-및 C ++을 대신 사용할 있습니다. 요점은, "매직"이없고, 그러한 강력한 추상화를 구축하기 위해 언어가 생성되며, 일단 하드웨어와 상호 작용할 수있는 가능성은 거의 무한하다는 것입니다.
Matteo Italia

1
@ hvd이 토론의 모든 갈등은 당신 (및 다른 사람들)이 C를 지정된 기능으로 정의한다는 것입니다. 실제로 컴파일러는 지정된 것보다 훨씬 더 많은 것을 추가하여 C가 무엇인지에 대한 질문에 대답하기가 쉽지 않습니다. 나에게 언어에 대한 특별한 것은 (따라서) 그것은 프로그램 흐름을 표현하는 메타 웨이와 구조 가능성입니다. 그들이 원하는대로 컴파일러에 의해 추가 할 수 있습니다 단지 더 좋은 ASM-코드가 같이 구성하는 요소는, 그것은 중요하지 않습니다
LionC

43

C 및 C ++에는 OP가 말하는 모든 확장 성을 허용하는 2 가지 속성이 있습니다.

  1. C 및 C ++는 메모리에 액세스 할 수 있습니다
  2. C 및 C ++는 C 또는 C ++ 언어가 아닌 명령어에 대한 어셈블리 코드를 호출 할 수 있습니다.

커널 또는 기본 비보호 모드 플랫폼에서 직렬 포트 또는 디스크 드라이브와 같은 주변 장치는 RAM과 같은 방식으로 메모리 맵에 매핑됩니다. 메모리는 일련의 스위치이며 직렬 포트 나 디스크 드라이버와 같은 주변 장치의 스위치를 뒤집 으면 주변 장치가 유용한 작업을 수행 할 수 있습니다.

보호 모드 운영 체제에서 사용자 공간에서 커널에 액세스하려면 (예 : 파일 시스템에 쓰거나 화면에 픽셀을 그릴 때) 시스템 호출이 필요합니다. C에는 시스템 호출을 지시하는 명령이 없지만 C는 올바른 시스템 호출을 트리거 할 수있는 어셈블러 코드를 호출 할 수 있습니다. 이것이 C 코드가 커널과 통신 할 수있게하는 것입니다.

특정 플랫폼을 쉽게 프로그래밍 할 수 있도록 시스템 호출은보다 복잡한 기능으로 래핑되어 자체 프로그램 내에서 유용한 기능을 수행 할 수 있습니다. 하나는 시스템 호출을 직접 호출 할 수 있지만 (어셈블러 사용) 플랫폼이 제공하는 래퍼 함수 중 하나를 사용하는 것이 더 쉽습니다.

시스템 호출보다 훨씬 유용한 다른 수준의 API가 있습니다. 예를 들어 malloc을 보자. 이를 통해 시스템은 큰 메모리 블록을 확보하기 위해 시스템을 호출 할뿐만 아니라 발생하는 모든 작업을 수행하여이 메모리를 관리합니다.

Win32 API는 일부 그래픽 기능을 공통 플랫폼 위젯 세트로 래핑합니다. Qt는 Win32 (또는 X Windows) API를 크로스 플랫폼 방식으로 래핑하여 이것을 조금 더 발전시킵니다.

기본적으로 C 컴파일러는 C 코드를 기계 코드로 변환하지만 컴퓨터가 기계 코드를 사용하도록 설계되었으므로 C가 라이온스 공유 또는 컴퓨터가 수행 할 수있는 작업을 수행 할 수있을 것으로 기대해야합니다. 랩퍼 라이브러리가하는 모든 작업은 사용자를 위해 무거운 물건을 들기 만하면됩니다.


# 2에 대한주의 사항 : C와 C ++는 컴파일러가 이해하고 기대하는 "호출 규칙"을 준수하는 함수 만 실행할 수 있습니다. (어셈블리 코드는 좋아하는 규칙을 사용하거나 전혀 사용하지 않을 수 있으므로 코드를 직접 호출 할 수 없습니다.) 다행히도 모든 자체 존중 컴파일러는 플랫폼의 공통 규칙을 사용하는 기본 제공 방법을 제공합니다. (예를 들어, Windows C 컴파일러에서는 "cdecl", "stdcall"또는 "fastcall"규칙을 사용하는 함수를 사용 / 사용할 수 있습니다.) 그러나 어셈블리 코드는 컴파일러가 알고있는 규칙을 사용해야합니다. 직접 전화하지 마십시오.
cHao

2
또한 메모리 매핑 I / O는 일반적이지만 전체 스토리는 아닙니다. 예를 들어 PC는 일반적으로 완전히 다른 메커니즘 인 x86의 "I / O 포트"를 사용하여 직렬 포트, 디스크 드라이브 등을 처리합니다. (비디오 버퍼는 일반적으로 메모리 매핑되지만 비디오 모드 등은 일반적으로 I / O 포트를 통해 제어됩니다.)
cHao

@cHao : 물론 INP와 OUTP를 사용하는 고전적인 접근 방식은 DMA를 선호합니다. PCI 생성은 메모리 매핑 특수 기능 레지스터를 사용하여 더 많은 작업을 수행하는 것처럼 보입니다. 이제 장치를 겹치지 않는 영역에 자동으로 매핑하고 드라이버에서 장치를 검색하는 방법이 있으므로 I / O 포트가 적습니다.
벤 Voigt

최신 주변 장치는 대량 데이터 전송에 DMA를 사용하지만 여전히 주소 지정 가능한 메모리로 DMA 컨트롤러를 프로그래밍합니다
doron

@doron : 음, 적어도 제정신이라면 PC의 I / O 주소 공간 (메모리 공간이 아닌)을 통해 DMA 컨트롤러를 프로그래밍합니다. 최신 x86 CPU는 메모리 액세스를 재정렬하여 성능을 향상시킵니다. MMIO를 사용하면 재앙이 될 수 있습니다. 따라서 해당 주소를 캐시 해제 하고 올바른 위치에 직렬화 명령을 넣는 데주의를 기울여야 합니다. OTOH, x86 자체는 I / O 공간에 대한 읽기 및 쓰기가 프로그램 순서대로 수행되도록합니다. 그렇기 때문에 중요한 것들 중 많은 부분이 여전히 I / O 공간 (일반적으로 포인터를 통해 액세스 할 수 없음)을 통해 수행되며 아마도 항상 그렇게됩니다.
cHao

23

언어 (예 : C ++ 11 )는 일반적으로 영어로 작성된 용지의 사양 입니다. 최신 C ++ 11 초안을 살펴보십시오 (또는 ISO 공급 업체로부터 값 비싼 최종 사양 을 구매하십시오 ).

일반적으로 언어가 구현 된 컴퓨터를 사용합니다 (원칙적으로 컴퓨터를 해석하지 않고 C ++ 프로그램을 실행할 수 있습니다 (예 : 많은 인간 노예를 사용하여 해석하는 경우 비 윤리적이고 비효율적 임)).

C ++ 구현 일반은 일부 운영 체제에서 작동하며 ( 일부 시스템 라이브러리에서 구현 특정 코드를 사용하여) 운영 체제와 통신합니다 . 일반적으로 통신은 시스템 호출을 통해 수행됩니다 . 로 예를 들어 봐 콜 (2) 시스템의 목록은 볼 수 호출 리눅스 커널 .

적용 관점에서 syscall은 SYSENTER일부 규칙 ( ABI )이있는 x86-64와 같은 기본 기계 명령어입니다.

내 Linux 데스크톱에서 Qt 라이브러리는 X Windows 서버를 통해 X11 서버 Xorg 와 통신하는 X11 클라이언트 라이브러리 위에 있습니다 .

Linux에서 ldd실행 파일을 사용 하여 라이브러리에 대한 (긴) 종속성 목록을보십시오. 사용 pmap하여 실행중인 프로세스에이 사람이 런타임에 "로드"되는 볼 수 있습니다. BTW, Linux에서 응용 프로그램은 무료 소프트웨어 만 사용하고 있으며 소스 코드 (Qt에서 Xlib, libc, ... 커널로)를 연구하여 발생하는 일을 더 많이 이해할 수 있습니다.


2
참고로 ANSI는 C ++ 11 사양 을 약간 덜 비싼 60 달러에 판매합니다 . (이것은 절반이지만 인플레이션입니다. : P) INCITS / ISO / IEC 14882로 표시되어 있지만 적어도 ISO가 제공하는 기본 사양과 동일합니다. 정오표 / TR에 대해 잘 모르겠습니다.
cHao

19

당신이 빠진 개념은 시스템 호출 이라고 생각 합니다 . 각 운영 체제는 저수준 운영 체제 관련 작업을 수행하기 위해 활용할 수있는 엄청난 양의 리소스와 기능을 제공합니다. 일반 라이브러리 함수를 호출하더라도 장면 뒤에서 시스템 호출이 발생했을 수 있습니다.

시스템 호출은 운영 체제의 강력한 기능을 사용하는 저수준 방법이지만 사용하기가 복잡하고 번거로울 수 있으므로 API에서 "랩핑 (wrapped)"되므로 직접 처리 할 필요가 없습니다. 그러나 그 아래에는 O / S 관련 리소스와 관련된 모든 작업이 인쇄, 네트워킹 및 소켓 등 시스템 호출을 사용합니다.

Windows의 경우 Microsoft Windows에는 실제로 GUI에 커널이 작성되어 있으므로 창을 작성하거나 그래픽을 그리는 등의 시스템 호출이 있습니다. 다른 운영 체제에서는 GUI가 커널의 일부가 아닐 수 있습니다. 내가 아는 한 GUI 관련 사항에 대한 시스템 호출은 없으며, 낮은 수준의 그래픽 및 입력 관련 호출을 사용할 수 있으면 더 낮은 수준에서만 작업 할 수 있습니다.


3
빠진 중요한 점은 그러한 시스템 호출이 결코 마법이 아니라는 것입니다. 그것들은 일반적으로 C (++)로 작성된 커널에 의해 서비스됩니다. 또한 시스템 콜도 필요하지 않습니다. 메모리 보호 기능이없는 초보 OS에서는 픽셀을 하드웨어 프레임 버퍼에 직접 입력하여 창을 그릴 수 있습니다.
el.pescado

15

좋은 질문. 모든 새로운 C 또는 C ++ 개발자는이를 염두에두고 있습니다. 이 게시물의 나머지 부분에 대해 표준 x86 시스템을 가정합니다. Microsoft C ++ 컴파일러를 사용하는 경우 메모장을 열고 이것을 입력하십시오 (파일 이름은 Test.c).

int main(int argc, char **argv)
{
   return 0
}

이제이 파일을 컴파일하십시오 (개발자 명령 프롬프트 사용) cl Test.c /FaTest.asm

메모장에서 Test.asm을 엽니 다. 번역 된 코드는 C / C ++가 어셈블러로 변환 된 것입니다. 힌트가 있습니까?

_main   PROC
    push    ebp
    mov ebp, esp
    xor eax, eax
    pop ebp
    ret 0
_main   ENDP

C / C ++ 프로그램은 금속에서 실행되도록 설계되었습니다. 즉, 하위 수준의 하드웨어에 액세스 할 수 있으므로 하드웨어 기능을 쉽게 이용할 수 있습니다. x86 컴퓨터에서 C 라이브러리 getch ()를 작성한다고 가정 해보십시오.

어셈블러에 따라 다음과 같이 입력합니다.

_getch proc 
   xor AH, AH
   int 16h
   ;AL contains the keycode (AX is already there - so just return)
ret

어셈블러를 사용하여 실행하고 .OBJ-getch.obj라는 이름을 생성합니다.

그런 다음 C 프로그램을 작성합니다 (#include 아무것도 포함하지 않습니다)

extern char getch();

void main(int, char **)
{
  getch();
}

이제이 파일 이름을 GetChTest.c로 지정하십시오. getch.obj를 전달하여이 파일을 컴파일하십시오. 또는 개별적으로 .obj 및 LINK GetChTest.Obj 및 getch.Obj로 컴파일하여 GetChTest.exe를 생성합니다.

GetChTest.exe를 실행하면 키보드 입력을 기다립니다.

C / C ++ 프로그래밍은 언어에 관한 것이 아닙니다. 우수한 C / C ++ 프로그래머가 되려면 실행되는 머신 유형에 대해 잘 알고 있어야합니다. 메모리 관리가 어떻게 처리되는지, 레지스터가 어떻게 구성되는지 등을 알아야합니다. 정기적 인 프로그래밍을 위해 이러한 정보가 모두 필요한 것은 아닙니다. 기본 하드웨어 지식 외에도 컴파일러가 작동하는 방식 (예 : 변환 방법)을 이해하면 도움이되므로 필요한 경우 코드를 조정할 수 있습니다. 재미있는 패키지입니다!

두 언어 모두 __asm ​​키워드를 지원하므로 어셈블리 언어 코드도 혼합 할 수 있습니다. C와 C ++를 배우면 전반적으로 더 나은 프로그래머가 될 것입니다.

항상 어셈블러와 연결할 필요는 없습니다. 나는 그것이 당신이 더 잘 이해하는 데 도움이 될 것이라고 생각했기 때문에 언급했습니다. 대부분의 이러한 라이브러리 호출은 운영 체제에서 제공하는 시스템 호출 / API를 사용합니다 (OS는 하드웨어 상호 작용을 수행함).


10

C ++는 어떻게 C ++ 자체로 작성된 라이브러리를 통해 그러한 기능을 갑자기 얻습니까?

다른 라이브러리를 사용하는 것에 대한 마술은 없습니다. 라이브러리는 호출 할 수있는 단순한 기능의 큰 백입니다.

이와 같은 함수를 작성하는 것을 고려하십시오.

void addExclamation(std::string &str)
{
    str.push_back('!');
}

이제 그 파일을 포함 시키면 addExclamation(myVeryOwnString); . "여러분은 C ++에서 어떻게 문자열에 느낌표를 추가 할 수 있었습니까?" 답은 쉽다 : 당신은 그것을하기위한 함수를 작성한 다음 그것을 호출했다.

따라서 C ++에서 C ++로 작성된 라이브러리를 통해 창을 그리는 기능을 얻는 방법에 대한 질문에 대답하려면 대답은 동일합니다. 다른 누군가가 그렇게하기 위해 함수를 작성한 다음 컴파일하여 라이브러리 형태로 당신에게주었습니다.

다른 질문은 창 그리기가 실제로 어떻게 작동하는지 대답하지만 라이브러리 작동 방식에 대해 혼란스러워서 질문의 가장 근본적인 부분을 다루고 싶었습니다.


8

핵심은 운영 체제가 API를 공개 할 가능성과이 API의 사용법에 대한 자세한 설명입니다.

운영 체제는 호출 규칙이있는 API 세트를 제공합니다. 호출 규칙은 매개 변수가 API에 제공되는 방식과 결과가 리턴되는 방법 및 실제 호출을 실행하는 방법을 정의합니다.

운영 체제와이를위한 코드를 작성하는 컴파일러는 서로 잘 작동하므로 일반적으로 생각하지 않아도됩니다.


7

창을 만들기 위해 특별한 구문이 필요하지 않습니다. OS가 창을 만들기위한 API를 제공하기 만하면됩니다. 이러한 API는 C ++에서 구문을 제공하는 간단한 함수 호출로 구성됩니다.

또한 C 및 C ++는 시스템 프로그래밍 언어라고하며 임의의 포인터 (하드웨어가 일부 장치에 매핑 할 수 있음)에 액세스 할 수 있습니다. 또한 어셈블리에 정의 된 함수를 호출하는 것도 상당히 간단하여 프로세서가 제공하는 모든 작업 범위를 허용합니다. 따라서 C 또는 C ++ 및 소량의 어셈블리를 사용하여 OS 자체를 작성할 수 있습니다.

또한 Qt는 소위 메타 컴파일러를 사용하여 C ++의 구문 을 확장 하므로 나쁜 예 입니다. 그러나 이것은 실제로 창을 그리거나 생성하기 위해 OS에서 제공하는 API를 호출하는 기능과 관련이 없습니다.


7

먼저 약간의 오해가 있다고 생각합니다.

이전에 OS에 창을 요청하거나 네트워크를 통해 통신하는 방법을 요구할 수있는 구문이 없었던 C ++의 방법

OS 작업을 수행하기위한 구문 이 없습니다 . 의미론 의 문제입니다 .

C ++로 작성된 라이브러리를 통해 이러한 기능을 갑자기 얻습니다.

운영 체제는 대부분 C로 작성됩니다. 공유 라이브러리 (dll)를 사용하여 외부 코드를 호출 할 수 있습니다. 또한 운영 체제 코드는 syscalls * 에 시스템 루틴을 등록 하거나 assembly를 사용하여 호출 할 수있는 인터럽트 를 등록 할 수 있습니다 . 공유 라이브러리는 종종 시스템을 호출하기 때문에 인라인 어셈블리를 사용하지 않아도됩니다.

여기에 좋은 튜토리얼이 있습니다 : http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
리눅스 용이지만 원칙은 같습니다.

운영 체제가 그래픽 카드, 네트워크 카드 등에서 어떻게 작동합니까? 매우 광범위한 주제이지만 대부분 인터럽트, 포트에 액세스하거나 일부 데이터를 특수 메모리 영역에 기록해야합니다. 해당 작업이 보호되므로 운영 체제를 통해 해당 작업을 호출해야합니다.


7

다른 답변에 대해 약간 다른 견해를 제공하기 위해 다음과 같이 대답합니다.

(면책 조항 : 나는 사물을 약간 단순화하고 있습니다. 내가주는 상황은 순전히 가설 적이며 인생에 100 % 진실한 것이 아니라 개념을 보여주는 수단으로 쓰여졌습니다).

다른 관점에서 생각하고 기본적인 스레딩, 창 및 메모리 관리 기능을 갖춘 간단한 운영 체제를 작성했다고 상상해보십시오. C ++ 라이브러리를 구현하여 사용자가 C ++로 프로그램하고 창 만들기, 창 그리기 등과 같은 작업을 수행하려고합니다. 문제는 방법입니다.

먼저, C ++는 머신 코드로 컴파일되므로 머신 코드를 사용하여 C ++와 인터페이스하는 방법을 정의해야합니다. 이것은 함수가 들어오고 함수가 인수를 받아들이고 값을 반환하는 곳이므로 코드의 다른 섹션간에 데이터를 전송하는 표준 방법을 제공합니다. 그들은 호출 규칙으로 알려진 것을 설정하여이를 수행합니다 .

호출 규칙의 상태와이 실행됩니다 때 기능을 찾을 수 있도록 인수가 메모리에 배치하는 방법. 함수가 호출되면 호출 함수는 인수를 메모리에 배치 한 다음 CPU가 다른 함수로 건너 뛰도록 요청합니다.이 함수는 호출 된 위치로 건너 뛰기 전에 수행하는 작업을 수행합니다. 이것은 호출되는 코드가 절대적으로 무엇이든 될 수 있으며 함수 호출 방법을 변경하지 않음을 의미합니다. 그러나이 경우 함수 뒤의 코드는 운영 체제와 관련이 있으며 운영 체제의 내부 상태에서 작동합니다.

몇 달 후 모든 OS 기능을 정리했습니다. 사용자는 함수를 호출하여 창을 만들고 그 위에 그릴 수 있으며 스레드 및 모든 종류의 멋진 것을 만들 수 있습니다. 문제는 OS의 기능이 Linux의 기능이나 Windows의 기능과 다를 수 있다는 것입니다. 따라서 사용자가 휴대용 코드를 작성할 수 있도록 표준 인터페이스를 제공해야한다고 결정합니다. 여기 QT가 들어옵니다.

거의 확실하게 알 수 있듯이 QT에는 운영 체제가 수행하는 작업을 수행하기위한 유용한 클래스와 함수가 많이 있지만 기본 운영 체제와 독립적으로 나타나는 방식이 있습니다. 이것이 작동하는 방식은 QT가 사용자에게 보이는 방식으로 균일 한 클래스와 함수를 제공하지만 함수 뒤의 코드는 운영 체제마다 다릅니다. 예를 들어 QT의 QApplication :: closeAllWindows ()는 실제로 사용 된 버전에 따라 각 운영 체제의 특수 창 닫기 함수를 호출합니다. Windows에서는 X Window System을 사용하는 OS에서는 CloseWindow (hwnd)를 호출 할 가능성이 높지만 XDestroyWindow (display, window)를 호출 할 수 있습니다.

명백한 바와 같이, 운영 체제는 많은 계층을 가지고 있으며, 모든 계층은 많은 종류의 인터페이스를 통해 상호 작용해야한다. 내가 다루지 않은 많은 측면이 있지만, 그것들을 설명하는 데는 모두 오랜 시간이 걸릴 것입니다. 운영 체제의 내부 작동에 더 관심이 있다면 OS dev 위키를 확인하는 것이 좋습니다 .

많은 운영 체제가 C / C ++에 인터페이스를 노출시키려는 이유는 머신 코드로 컴파일하기 때문에 어셈블리 명령어를 자체 코드와 혼합하여 프로그래머에게 큰 자유를 제공하기 때문입니다.

다시, 여기에 많은 일이 있습니다. .so 및 .dll 파일과 같은 라이브러리가 C / C ++로 작성 될 필요가없고 어셈블리 또는 다른 언어로 작성 될 수있는 방법을 설명하고 싶습니다.하지만 더 추가하면 전체 기사를 작성하고 내가 원하는만큼 기사를 호스팅 할 사이트가 없습니다.


6

화면에 무언가를 그리려고 할 때, 코드는 CPU가 실행할 수있는 특별한 명령 인 "시스템 호출"이있을 때까지 다른 코드 등을 호출하는 다른 코드를 호출합니다. 컴파일러가 "내장"을 지원하는 경우 이러한 명령어는 어셈블리로 작성되거나 C ++로 작성 될 수 있습니다 (컴파일러가 CPU가 이해할 수있는 특수 코드로 변환하여 "특별하게"처리하는 함수). 그들의 임무는 운영 체제에게 무언가를하도록 지시하는 것입니다.

시스템 호출이 발생하면 마지막으로 디스플레이 드라이버가 화면에 무언가를 그리도록 지시 될 때까지 다른 함수 등을 호출하는 함수가 호출됩니다. 이 시점에서 디스플레이 드라이버는 실제 메모리아닌 메모리 인 것처럼 쓸 수있는 주소 범위 인 실제 메모리 의 특정 영역 을 확인 합니다. 그러나 해당 주소 범위에 쓰면 그래픽 하드웨어 가 메모리 쓰기를 가로 채서 화면에 무언가를 그립니다.
이 메모리 영역에 쓰는 것은 C ++로 코딩 할 수 있는 것입니다 . 소프트웨어 측면에서는 일반적인 메모리 액세스이기 때문입니다. 하드웨어가 다르게 처리하는 것입니다.
그것이 작동하는 방법에 대한 기본적인 설명입니다.


4
Afaik 시스템 콜은 실제로 CPU 명령이 아니며 내장 함수와 관련이 없습니다. 장치와 통신하는 운영 체제 커널의 기능입니다.
MatthiasB

3
@ MatthiasB : 글쎄, 당신은 syscall(그리고 그 사촌 sysenter은) 실제로 CPU 명령 이기 때문에 틀렸다 .
user541686

2
이것은 자신에게 명확하지 않기 때문에 답을 향상시키는 힌트 일뿐입니다. 개인의 공격이나 다른 것으로 보지 마십시오.
MatthiasB

1
@ MatthiasB : 나는 개인적으로 복용하지 않습니다. 나는 이미 대답이 실제로 100 % 정확하지 않다는 것을 알고 있지만 OP에 대답하기에 충분히 간단하다고 생각합니다. 따라서 실제로 더 나은 답변을 작성하는 방법을 알고 있다면 직접 작성하십시오. 답변을하거나 시간을내어 편집하십시오. 나는 그만한 가치가 있다고 생각할만한 추가 할 것이 없기 때문에이 페이지에서 더 나은 것을보고 싶다면 스스로 노력해야합니다.
user541686

3
시스템 호출은 소프트웨어 인터럽트를 사용하여 수행됩니다. sysenter인터럽트 핸들러가 사용하는 컨텍스트 전환이 원하는만큼 빠르지는 않았지만, 기본적으로 OS 커널에 의해 설치된 핸들러로 벡터링되어 처리되는 동안 여전히 인터럽트가 발생하기 때문에 이와 같은 명령어 는 최적화 된 호출 경로입니다. 컨텍스트 전환 프로세스의 일부는 sysenter프로세서의 모드 비트를 변경하여 링 0을 설정하여 모든 권한있는 명령, 레지스터 및 메모리 및 I / O 영역에 대한 전체 액세스를 설정하는 것입니다.
Ben Voigt

4

C ++ 프로그램이 Qt 라이브러리 (C ++로 코딩 됨)를 사용하고 있습니다. Qt 라이브러리는 Windows CreateWindowEx 함수 (kernel32.dll 내부의 C로 코딩 됨)를 사용합니다. 또는 Linux에서는 Xlib (C로 코딩 됨)를 사용하고 있지만 X 프로토콜에서 " Please create a window for me " 라는 원시 바이트를 보낼 수도 있습니다 .

catch-22 질문 관련하여 “첫 번째 C ++ 컴파일러는 C ++로 작성되었습니다”라는 역사적 메모가 있습니다. 실제로 실제로는 몇 가지 C ++ 개념을 가진 C 컴파일러 였으므로 첫 번째 버전을 컴파일 할 수 있습니다. .

마찬가지로 GCC 컴파일러는 GCC 확장을 사용합니다. 먼저 GCC 확장을 버전으로 컴파일 한 다음 다시 컴파일하는 데 사용됩니다. (GCC 빌드 지침)


2

이 질문을 실제로 보는 방법은 실제로 컴파일러 질문입니다.

이런 식으로 보시면 Z ++를 호출하려는 새로 작성된 언어를 어셈블리로 변환하는 어셈블리 코드를 어떤 언어로든 작성할 수 있습니다. 간단하게 컴파일러 (컴파일러)라고 부를 수 있습니다. .

이제이 컴파일러에 몇 가지 기본 기능을 제공하여 int, string, array 등을 작성할 수 있습니다. 실제로 Z ++에서 컴파일러 자체를 작성할 수 있도록 충분한 기능을 제공합니다. 이제 Z ++로 작성된 Z ++ 용 컴파일러가 있습니다.

더욱 멋진 점은 이제 기존 기능을 사용하여 해당 컴파일러에 기능을 추가 할 수 있으므로 이전 기능을 사용하여 새로운 기능으로 Z ++ 언어를 확장 할 수 있다는 것입니다

예를 들어, 어떤 색상으로도 픽셀을 그릴 수있는 충분한 코드를 작성하면 Z ++를 사용하여 확장하여 원하는 것을 그릴 수 있습니다.


0

하드웨어가이를 가능하게합니다. 그래픽 메모리는 화면의 모든 픽셀로 구성된 대형 배열로 생각할 수 있습니다. 화면에 그리려면 C ++ 또는 해당 메모리에 직접 액세스 할 수있는 언어를 사용하여이 메모리에 쓸 수 있습니다. 해당 메모리는 그래픽 카드에서 액세스하거나 그래픽 카드에 있습니다.

최신 시스템에서 그래픽 메모리에 직접 액세스하려면 다양한 제한으로 인해 드라이버를 작성해야하므로 간접적 인 수단을 사용해야합니다. 창 (실제로 다른 이미지와 같은 이미지)을 생성 한 다음 해당 이미지를 GPU가 화면에 표시하는 그래픽 메모리에 기록하는 라이브러리. 포인터에 대한 특정 메모리 위치에 쓸 수있는 기능을 제외하고는 언어에 추가 할 것이 없습니다.


내가 만들고자하는 요점은 언어가 새로운 버전의 언어를 다시 작성해야한다는 의미에서 언어를 "확장"할 필요가 없으며, 프로그램에 흥미로운 일을하기 때문에 실제로 순환되지 않는다는 것입니다. 하드웨어와 인터페이스해야합니다.
john
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.