응용 프로그램 이진 인터페이스 (ABI) 란 무엇입니까?


493

나는 ABI가 무엇인지 명확하게 이해하지 못했습니다. 저에게 Wikipedia 기사를 알려주지 마십시오. 내가 이해할 수 있다면, 나는 그렇게 긴 게시물을 게시하지 않을 것입니다.

이것은 다른 인터페이스에 대한 나의 사고 방식입니다.

TV 리모컨은 사용자와 TV 간의 인터페이스입니다. 기존 엔터티이지만 그 자체로는 쓸모가 없습니다 (기능을 제공하지 않음). 리모컨의 각 버튼에 대한 모든 기능은 텔레비전 세트에서 구현됩니다.

인터페이스 : 해당 기능 functionalityconsumer기능 사이의 "기존 엔티티"계층 입니다. 인터페이스 자체는 아무것도하지 않습니다. 그것은 뒤에있는 기능을 호출합니다.

이제 사용자가 누구인지에 따라 다른 유형의 인터페이스가 있습니다.

CLI (명령 줄 인터페이스) 명령은 기존 엔터티이며 소비자는 사용자이며 기능은 뒤에 있습니다.

functionality: 이 인터페이스를 설명하는 목적을 해결하는 소프트웨어 기능.

existing entities: 명령

consumer: 사용자

GUI (Graphical User Interface) 창, 버튼 등은 기존 엔터티이며 다시 소비자는 사용자이며 기능은 뒤에 있습니다.

functionality: 이 인터페이스를 설명하는 몇 가지 문제를 해결하는 소프트웨어 기능.

existing entities: 창, 버튼 등

consumer: 사용자

API (Application Programming Interface) 기능 (또는보다 정확한 인터페이스) (인터페이스 기반 프로그래밍) 인터페이스는 기존 엔터티이며 여기서 소비자는 사용자가 아닌 다른 프로그램이며 기능은이 계층 뒤에 있습니다.

functionality: 이 인터페이스를 설명하는 몇 가지 문제를 해결하는 소프트웨어 기능.

existing entities: 기능, 인터페이스 (기능 배열).

consumer: 다른 프로그램 / 응용 프로그램.

응용 프로그램 이진 인터페이스 (ABI) 여기에서 문제가 시작됩니다.

functionality: ???

existing entities: ???

consumer: ???

  • 다른 언어로 소프트웨어를 작성했으며 다른 종류의 인터페이스 (CLI, GUI 및 API)를 제공했지만 ABI를 제공했는지 확실하지 않습니다.

위키피디아의 말 :

ABI는 다음과 같은 세부 사항을 다룹니다.

  • 데이터 유형, 크기 및 정렬;
  • 함수의 인수가 전달되고 반환 값을 검색하는 방법을 제어하는 ​​호출 규칙;
  • 시스템 호출 번호 및 응용 프로그램이 운영 체제를 시스템 호출하는 방법

다른 ABI는 다음과 같은 세부 정보를 표준화합니다

  • C ++ 이름 맹 글링
  • 예외 전파
  • 동일한 플랫폼에서 컴파일러 간 호출 규칙이지만 플랫폼 간 호환성이 필요하지 않습니다.
  • 누가 이러한 세부 정보가 필요합니까? OS를 말하지 마십시오. 어셈블리 프로그래밍을 알고 있습니다. 링크 및로드 작동 방식을 알고 있습니다. 나는 무슨 일이 일어나는지 정확히 알고 있습니다.

  • C ++ 이름 맹 글링이 왜 들어 왔습니까? 나는 우리가 이진 레벨에서 이야기하고 있다고 생각했다. 언어는 왜 들어 옵니까?

어쨌든 [PDF] System V Application Binary Interface Edition 4.1 (1997-03-18) 을 다운로드하여 정확히 무엇이 포함되어 있는지 확인했습니다. 글쎄, 대부분은 말이되지 않았다.

  • ELF 파일 형식 을 설명하기 위해 왜 두 개의 장 (4 및 5)이 포함되어 있습니까? 실제로, 이들은이 사양에서 유일하게 중요한 두 장입니다. 나머지 장은 "프로세서 별"입니다. 어쨌든, 나는 그것이 완전히 다른 주제라고 생각합니다. ELF 파일 형식 사양 ABI 라고 말하지 마십시오 . 정의에 따라 인터페이스 가 될 수 없습니다 .

  • 나는 우리가 그렇게 낮은 수준에서 이야기하기 때문에 매우 구체적이어야한다는 것을 알고 있습니다. 그러나 "ISA (Instruction Set Architecture)"가 어떻게 특정되는지 잘 모르겠습니다.

  • Microsoft Windows ABI는 어디에서 찾을 수 있습니까?

이것이 저를 괴롭히는 주요 질문입니다.


7
컴파일러는 ABI를 알아야합니다. 링커는 ABI를 알아야합니다. 커널이 제대로 실행되도록 프로그램을 RAM에 설정하려면 ABI를 알아야합니다. C ++의 경우 아래에서 볼 수 있듯이 오버로드 및 개인 메소드로 인해 의도적으로 레이블을 횡설수설로 바꾸고 링커와 다른 컴파일러는 호환되는 이름 맹 글링이 있어야합니다. 즉, 동일한 ABI입니다.
Justin Smith

8
나는 그 질문이 너무 분명하다고 생각한다. 예상되는 답변 형식은 무엇인지, 아직 받아 들일 수있는 하나의 만족스러운 답변은 정확히 설명하지 않습니다.
legends2k

3
@ legends2k 내 문제는 OP가 실제로 ABI가 무엇인지 알고 있지만 그것을 모르는 것입니다. 대다수의 프로그래머는 OS / 플랫폼 디자이너의 직무이므로 ABI를 설계하거나 제공하지 않습니다.
JesperE

4
@JesperE : 나는 당신의 요점에 동의합니다. 그러나 OP는 아마도 ABI를 제공 할 필요는 없지만 적합하다고 생각되는 형식으로 명확하게 알고 싶어 할 것입니다.
legends2k

2
나는 무지했다. 최근에이 모든 것들을 다루면서 ABI가 실제로 무엇인지 깨달았습니다. 예, 템플릿에 결함이 있음에 동의합니다. ABI를 내 템플릿에 맞추는 것은 적절하지 않습니다. 감사합니다 @ JasperE. 당신의 대답을 깨닫기 위해서는 직장 경험이 필요했습니다.
클로 발톱

답변:


534

"ABI"를 이해하는 한 가지 쉬운 방법은 "ABI"를 "API"와 비교하는 것입니다.

이미 API 개념에 익숙합니다. 예를 들어 일부 라이브러리 또는 OS의 기능을 사용하려면 API에 대해 프로그래밍합니다. API는 외부 유형의 기능에 액세스하기 위해 코드에서 사용할 수있는 데이터 유형 / 구조, 상수, 함수 등으로 구성됩니다.

ABI는 매우 유사합니다. API의 컴파일 된 버전 (또는 기계 언어 레벨의 API)으로 생각하십시오. 소스 코드를 작성할 때 API를 통해 라이브러리에 액세스합니다. 코드가 컴파일되면 응용 프로그램은 ABI를 통해 라이브러리의 이진 데이터에 액세스합니다. ABI는 컴파일 된 응용 프로그램이 API와 마찬가지로 외부 라이브러리에 액세스하는 데 사용하는 구조와 메서드를 낮은 수준에서만 정의합니다. API는 함수에 인수를 전달하는 순서를 정의합니다. ABI는 방법 의 역학을 정의 합니다이러한 인수는 전달됩니다 (레지스터, 스택 등). API는 라이브러리의 일부 기능을 정의합니다. ABI는 라이브러리를 사용하는 모든 프로그램이 원하는 기능을 찾아서 실행할 수 있도록 라이브러리 파일 내에 코드가 저장되는 방식을 정의합니다.

외부 라이브러리를 사용하는 응용 프로그램의 경우 ABI가 중요합니다. 라이브러리는 코드 및 기타 리소스로 가득 차 있지만 프로그램은 라이브러리 파일 내에서 필요한 것을 찾는 방법을 알아야합니다. ABI는 라이브러리 내용이 파일 내에 저장되는 방법을 정의하고 프로그램은 ABI를 사용하여 파일을 검색하고 필요한 것을 찾습니다. 시스템의 모든 항목이 동일한 ABI를 준수하는 경우, 모든 프로그램은 누가 만든지에 관계없이 모든 라이브러리 파일을 사용할 수 있습니다. Linux와 Windows는 다른 ABI를 사용하므로 Windows 프로그램은 Linux 용으로 컴파일 된 라이브러리에 액세스하는 방법을 모릅니다.

때로는 ABI 변경이 불가피합니다. 이 경우 해당 라이브러리를 사용하는 모든 프로그램은 새 버전의 라이브러리를 사용하도록 다시 컴파일되지 않으면 작동하지 않습니다. ABI가 변경되었지만 API가 변경되지 않으면 이전 및 새 라이브러리 버전을 "소스 호환"이라고도합니다. 즉, 한 라이브러리 버전 용으로 컴파일 된 프로그램은 다른 라이브러리 버전과 작동하지 않지만, 하나를 위해 작성된 소스 코드는 다시 컴파일 된 경우 다른 소스 용으로 작동합니다.

이러한 이유로 개발자는 중단을 최소화하기 위해 ABI를 안정적으로 유지하려고합니다. ABI를 안정적으로 유지한다는 것은 함수 인터페이스 (반환 유형 및 수, 유형 및 인수 순서), 데이터 유형 또는 데이터 구조의 정의, 정의 된 상수 등을 변경하지 않음을 의미합니다. 새로운 함수 및 데이터 유형을 추가 할 수 있지만 기존 유형은 그대로 있어야합니다. 똑같다. 예를 들어 라이브러리가 함수의 오프셋을 나타 내기 위해 32 비트 정수를 사용하고 64 비트 정수로 전환하면 해당 라이브러리를 사용하는 이미 컴파일 된 코드가 해당 필드 (또는 그 뒤를 따르는)에 올바르게 액세스하지 못합니다 . 데이터 구조 멤버에 액세스하면 컴파일 중에 메모리 주소 및 오프셋으로 변환되고 데이터 구조가 변경되면

매우 낮은 수준의 시스템 설계 작업을 수행하지 않는 한 ABI가 반드시 명시 적으로 제공하는 것은 아닙니다. C 애플리케이션과 Pascal 애플리케이션은 컴파일 된 후에 동일한 ABI를 사용할 수 있으므로 언어별로 다릅니다.

편집하다:SysV ABI 문서의 ELF 파일 형식 관련 장에 대한 질문과 관련하여 :이 정보가 포함 된 이유는 ELF 형식이 운영 체제와 응용 프로그램 간의 인터페이스를 정의하기 때문입니다. OS에게 프로그램을 실행하도록 지시하면 프로그램이 특정 방식으로 포맷 될 것으로 예상하고 (예를 들어) 바이너리의 첫 번째 섹션이 특정 메모리 오프셋에서 특정 정보를 포함하는 ELF 헤더가 될 것으로 예상합니다. 응용 프로그램이 자신에 대한 중요한 정보를 운영 체제와 통신하는 방법입니다. ELF 이외의 이진 형식 (예 : a.out 또는 PE)으로 프로그램을 빌드하면 ELF 형식의 응용 프로그램이 필요한 OS에서 이진 파일을 해석하거나 응용 프로그램을 실행할 수 없습니다.

IIRC, Windows는 현재 Portable Executable (또는 PE) 형식을 사용합니다. 해당 위키 백과 페이지의 "외부 링크"섹션에 PE 형식에 대한 자세한 정보가있는 링크가 있습니다.

또한 C ++ 이름 맹 글링에 대한 참고 사항 : 라이브러리 파일에서 함수를 찾을 때 함수는 일반적으로 이름별로 검색됩니다. C ++에서는 함수 이름을 오버로드 할 수 있으므로 이름만으로는 함수를 식별하기에 충분하지 않습니다. C ++ 컴파일러에는 내부적으로 name mangling 이라고하는 고유 한 방식이 있습니다. ABI는 다른 언어 나 컴파일러로 빌드 된 프로그램이 필요한 것을 찾을 수 있도록 함수 이름을 인코딩하는 표준 방법을 정의 할 수 있습니다. extern "c"C ++ 프로그램에서 사용할 때는 다른 소프트웨어에서 이해할 수있는 표준화 된 이름의 녹음 방법을 사용하도록 컴파일러에 지시합니다.


2
@ bta, 좋은 답변 주셔서 감사합니다. 전화 컨벤션은 일종의 ABI입니까? 감사합니다
camino

37
좋은 대답입니다. 이것 외에는 ABI가 아닙니다. ABI는 호출 규칙 및 구조 레이아웃 규칙을 결정하는 일련의 규칙입니다. Pascal은 C 애플리케이션에서 역순으로 스택의 인수를 전달하므로 pascal 및 C 컴파일러는 동일한 ABI로 컴파일되지 않습니다. C 및 Pascal 컴파일러에 대한 각 표준은 암시 적으로 이것이 사실임을 보증합니다. C ++ 컴파일러는 표준 방법이 없기 때문에 이름을 맹 글링하는 "표준"방법을 정의 할 수 없습니다. Windows에서 경쟁하는 C ++ 컴파일러가있을 때 C ++ 이름 맹 글링 규칙이 C ++ 컴파일러간에 호환되지 않았습니다.
Robin Davies


1
@RobinDavies : Pascal 컴파일러가 호출자가 제공 한 함수 pop 인수를 호출 한 플랫폼에서 C 컴파일러는 일반적으로 프로그래머가 특정 함수가 동일한 호출 규칙을 사용하거나 사용하도록 예상 할 수있는 수단을 정의합니다. 파스칼 컴파일러는 C 컴파일러가 기본적으로 호출 된 함수가 호출자가 배치 한 모든 것을 스택에 남겨 두는 규칙을 사용합니다.
supercat

C 컴파일러가 생성 한 obj 파일에 ABI가 포함되어 있다고 말할 수 있습니까?
미투 라즈

144

OS 수준에서 어셈블리 및 작동 방식을 알고 있다면 특정 ABI를 준수하는 것입니다. ABI는 매개 변수가 전달되는 방식, 반환 값이 배치되는 방식 등을 관리합니다. 많은 플랫폼에서 선택할 수있는 ABI는 하나 뿐이며이 경우 ABI는 "일이 어떻게 작동 하는가"입니다.

그러나 ABI는 클래스 / 객체가 C ++로 배치되는 방식과 같은 사항도 관리합니다. 모듈 경계에 걸쳐 객체 참조를 전달하거나 다른 컴파일러로 컴파일 된 코드를 혼합하려는 경우에 필요합니다.

또한 32 비트 바이너리를 실행할 수있는 64 비트 OS가있는 경우 32 비트 및 64 비트 코드에 대해 서로 다른 ABI가 있습니다.

일반적으로 동일한 실행 파일에 연결하는 모든 코드는 동일한 ABI를 준수해야합니다. 다른 ABI를 사용하여 코드간에 통신하려면 일부 형식의 RPC 또는 직렬화 프로토콜을 사용해야합니다.

다른 유형의 인터페이스를 고정 된 특성 세트로 짜내기 위해 너무 열심히 노력하고 있다고 생각합니다. 예를 들어 인터페이스를 반드시 소비자와 생산자로 분리 할 필요는 없습니다. 인터페이스는 두 엔티티가 상호 작용하는 규칙입니다.

ABI는 (부분적으로) ISA에 구애받지 않을 수 있습니다. 호출 규칙과 같은 일부 측면은 ISA에 의존하지만 다른 측면 (예 : C ++ 클래스 레이아웃)은 그렇지 않습니다.

잘 정의 된 ABI는 컴파일러를 작성하는 사람들에게 매우 중요합니다. 잘 정의 된 ABI가 없으면 상호 운용 가능한 코드를 생성 할 수 없습니다.

편집 : 명확히해야 할 몇 가지 참고 사항 :

  • ABI의 "이진"은 문자열이나 텍스트 사용을 배제하지 않습니다. C ++ 클래스를 내보내는 DLL을 링크하려면 메소드 및 유형 서명을 인코딩해야합니다. 그것이 C ++ 이름 관리가 나오는 곳입니다.
  • ABI를 제공하지 않은 이유는 대다수의 프로그래머가 절대로 그렇게하지 않기 때문입니다. ABI는 플랫폼 (예 : 운영 체제)을 디자인하는 동일한 사람들이 제공하며, 거의 사용되지 않는 ABI를 설계 할 수있는 프로그래머는 거의 없습니다.

템플릿에 결함이 있다고 확신하지 않습니다. 인터페이스를위한이 템플릿이있는 모든 곳이 사실이기 때문입니다. 그렇습니다. ABI도이 템플릿에 적합하기를 기대하지만 그렇지 않습니다. 중요한 것은 여전히 ​​이해할 수 없다는 것입니다. 내가 너무 바보 같은지 모르겠지만 내 머리에 들어 가지 않습니다. 답변과 위키 기사를 알 수 없습니다.
발톱 4

2
@jesperE, "ABI는 매개 변수가 전달되는 방식, 리턴 값이 배치되는 위치 등을 제어합니다."는 "cdecl, stdcall, fastcall, pascal"입니다.
camino

3
예. 올바른 이름은 "통화 규칙"이며 ABI의 일부입니다. en.wikipedia.org/wiki/X86_calling_conventions
JesperE

4
이는 정확하고 정밀한 상세도없이 대답 (오히려 소음 )!
Nawaz 2016 년

약간의 어셈블리를 작성하는 것이 좋습니다. 이는 사람들이 ABI를보다 확실한 방식으로 이해하는 데 도움이됩니다.
KunYu Tsai

40

실제로 ABI가 필요 하지 않습니다.

  • 프로그램에 기능이 없으며-
  • 귀하의 프로그램은 말 그대로 실행되는 유일한 프로그램이며 다른 것과 대화 할 필요가없는 단독 실행 파일 (예 : 임베디드 시스템)입니다.

지나치게 단순화 된 요약 :

API : "여기에 호출 할 수있는 모든 기능이 있습니다."

ABI : "이것은 함수를 호출하는 방법 입니다."

ABI는 제대로 작동하도록 프로그램을 컴파일하기 위해 컴파일러와 링커가 준수하는 규칙 세트입니다. ABI는 여러 주제를 다룹니다.

  • 아마도 ABI의 가장 크고 중요한 부분은 "호출 규칙"이라고도 하는 프로 시저 호출 표준 입니다. 호출 규칙은 "함수"가 어셈블리 코드로 변환되는 방식을 표준화합니다.
  • ABI는 또한 이름 이 어떻게 다른 코드가 해당 라이브러리를 호출하고 전달할 인수를 알 수 있도록 라이브러리에서 노출 된 함수 을 표시 . 이것을 "이름 맹 글링"이라고합니다.
  • ABI는 또한 어떤 유형의 데이터 유형을 사용할 수 있는지, 어떻게 정렬해야하는지 및 기타 하위 수준의 세부 사항을 지시합니다.

ABI의 핵심이라고 생각하는 전화 회의에 대해 자세히 살펴보십시오.

기계 자체에는 "기능"이라는 개념이 없습니다. c와 같은 고급 언어로 함수를 작성할 때 컴파일러는와 같은 어셈블리 코드 행을 생성합니다 _MyFunction1:. 이 레이블 은 결국 어셈블러에서 주소로 확인됩니다. 이 레이블은 어셈블리 코드에서 "기능"의 "시작"을 표시합니다. 고급 코드에서 해당 함수를 "호출"할 때 실제로 수행하는 작업은 CPU가 점프하는 것입니다. 해당 레이블의 주소에 계속 거기에 실행.

점프 준비를 위해 컴파일러는 중요한 것들을 많이해야합니다. 호출 규칙은 컴파일러가이 모든 작업을 수행하기 위해 따르는 점검 목록과 같습니다.

  • 먼저 컴파일러는 현재 주소를 저장하기 위해 약간의 어셈블리 코드를 삽입하므로 "기능"이 완료되면 CPU가 올바른 위치로 되돌아 가서 계속 실행할 수 있습니다.
  • 다음으로 컴파일러는 인수를 전달하는 어셈블리 코드를 생성합니다.
    • 일부 호출 규칙에 따르면 인수는 스택에 있어야합니다 ( 물론 특정 순서 로).
    • 다른 규칙에 따르면 인수는 특정 레지스터에 넣어야합니다 ( 물론 데이터 유형따라 다름 ).
    • 또 다른 규칙에 따르면 특정 스택 및 레지스터 조합을 사용해야합니다.
  • 물론, 이전에 이러한 레지스터에 중요한 것이 있었으면 이제 해당 값을 덮어 쓰고 영원히 잃어 버렸으므로 일부 호출 규칙에 따라 인수를 저장하기 전에 컴파일러가 해당 레지스터 중 일부를 저장하도록 지시 할 수 있습니다.
  • 이제 컴파일러는 CPU에게 이전에 만든 레이블 ( _MyFunction1:) 로 이동하도록 지시하는 점프 명령을 삽입합니다 . 이 시점에서 CPU가 "기능"에 있다고 간주 할 수 있습니다.
  • 함수의 끝에서 컴파일러는 CPU가 올바른 위치에 반환 값을 쓰도록하는 어셈블리 코드를 넣습니다. 호출 규칙은 반환 값을 특정 레지스터 (유형에 따라 다름)에 넣을 것인지 아니면 스택에 넣을 것인지를 지시합니다.
  • 이제 정리할 차례입니다. 호출 규칙은 컴파일러가 정리 어셈블리 코드를 배치 할 위치를 나타냅니다.
    • 일부 규칙에 따르면 호출자는 스택을 정리해야합니다. 이는 "기능"이 완료되고 CPU가 이전 위치로 되돌아 간 후 실행되는 다음 코드는 매우 구체적인 정리 코드 여야 함을 의미합니다.
    • 다른 규칙에 따르면 클린업 코드의 일부 특정 부분은 건너 뛰기 전에 "기능"의 끝에 있어야합니다 .

많은 ABI / 통화 규칙이 있습니다. 몇 가지 주요 사항은 다음과 같습니다.

  • x86 또는 x86-64 CPU (32 비트 환경)의 경우 :
    • CDECL
    • STDCALL
    • 패스트 콜
    • 벡터 통화
    • 이 통화
  • x86-64 CPU (64 비트 환경)의 경우 :
    • SYSTEMV
    • MSNATIVE
    • 벡터 통화
  • ARM CPU (32 비트)
    • AAPCS
  • ARM CPU (64 비트)
    • AAPCS64

다음 은 다른 ABI를 위해 컴파일 할 때 생성되는 어셈블리의 차이점을 실제로 보여주는 훌륭한 페이지입니다.

언급해야 할 또 다른 사항은 ABI가 프로그램의 실행 모듈 에서만 관련이 없다는 것 입니다. 것 또한 프로그램이 라이브러리 기능을 제대로 호출을 확인하기 위해 링커가 사용. 컴퓨터에서 여러 개의 공유 라이브러리를 실행하고 있으며 컴파일러가 각 ABI가 사용하는 것을 알고있는 한 스택을 폭파하지 않고 적절하게 함수를 호출 할 수 있습니다.

라이브러리 함수를 호출하는 방법을 이해하는 컴파일러는 매우 중요합니다. 호스팅 된 플랫폼 (즉, OS가 프로그램을로드하는 플랫폼)에서 커널 호출 없이는 프로그램을 깜박일 수도 없습니다.


19

ABI (Application Binary Interface)는 API와 유사하지만 소스 코드 레벨에서 호출자가 액세스 할 수 없습니다. 이진 표현 만 액세스 가능 / 사용 가능합니다.

ABI는 프로세서 아키텍처 레벨 또는 OS 레벨에서 정의 될 수 있습니다. ABI는 컴파일러의 코드 생성기 단계가 따르는 표준입니다. 표준은 OS 또는 프로세서에 의해 고정됩니다.

기능 : 구현 언어 또는 특정 컴파일러 / 링커 / 툴체인과 독립적으로 함수 호출을 수행하는 메커니즘 / 표준을 정의하십시오. JNI 또는 Python-C 인터페이스 등을 허용하는 메커니즘을 제공하십시오.

기존 엔티티 : 기계 코드 형태의 기능.

소비자 : 다른 함수 (다른 언어로 된 함수 포함, 다른 컴파일러에서 컴파일 또는 다른 링커로 링크)


아키텍처에 의해 ABI가 정의되는 이유는 무엇입니까? 동일한 아키텍처의 다른 OS가 다른 ABI를 정의 할 수없는 이유는 무엇입니까?
Andreas Haferburg

10

기능 : 컴파일러, 어셈블리 작성자, 링커 및 운영 체제에 영향을주는 계약 세트입니다. 계약은 함수 배치 방법, 매개 변수 전달 위치, 매개 변수 전달 방법, 함수 리턴 작동 방식을 지정합니다. 이들은 일반적으로 (프로세서 아키텍처, 운영 체제) 튜플에 고유합니다.

기존 엔티티 : 매개 변수 레이아웃, 함수 의미론, 레지스터 할당 예를 들어 ARM 아키텍처에는 수많은 ABI가 있습니다 (APCS, EABI, GNU-EABI, 여러 역사적 사례는 신경 쓰지 마십시오). 혼합 ABI를 사용하면 경계를 넘어 호출 할 때 코드가 작동하지 않습니다.

소비자 : 컴파일러, 어셈블리 작성자, 운영 체제, CPU 특정 아키텍처.

누가 이러한 세부 정보가 필요합니까? 컴파일러, 어셈블리 작성자, 코드 생성 (또는 정렬 요구 사항)을 수행하는 링커, 운영 체제 (인터럽트 처리, syscall 인터페이스). 어셈블리 프로그래밍을 수행 한 경우 ABI를 준수한 것입니다!

C ++ 이름 맹 글링은 특별한 경우입니다-링커 및 동적 링커 중심 문제-이름 맹 글링이 표준화되지 않으면 동적 연결이 작동하지 않습니다. 따라서 C ++ ABI는 바로 C ++ ABI라고합니다. 링커 수준 문제가 아니라 코드 생성 문제입니다. C ++ 바이너리가 있으면 소스에서 다시 컴파일하지 않고 다른 C ++ ABI (이름 변경, 예외 처리)와 호환되도록 할 수 없습니다.

ELF는 로더 및 동적 링커 사용을위한 파일 형식입니다. ELF는 이진 코드 및 데이터를위한 컨테이너 형식이며, 따라서 코드의 ABI를 지정합니다. PE 실행 파일이 ABI가 아니기 때문에 ELF를 엄격한 의미에서 ABI로 간주하지 않습니다.

모든 ABI는 명령어 세트에 따라 다릅니다. ARM ABI는 MSP430 또는 x86_64 프로세서에서 의미가 없습니다.

Windows에는 여러 ABI가 있습니다. 예를 들어 fastcall과 stdcall은 두 가지 일반적인 ABI입니다. syscall ABI는 다시 다릅니다.


9

적어도 귀하의 질문에 답변을 드리겠습니다. Linux ABI가 시스템 호출에 어떤 영향을 미치는지, 왜 유용한 지에 대한 예를 들어 보자.

시스템 호출은 사용자 공간 프로그램이 커널 공간에 무언가를 요구하는 방법입니다. 호출에 대한 숫자 코드와 인수를 특정 레지스터에 넣고 인터럽트를 트리거하여 작동합니다. 커널 공간으로의 전환이 발생하고 커널은 숫자 코드와 인수를 찾고 요청을 처리하고 결과를 레지스터에 다시 넣고 사용자 공간으로의 전환을 트리거합니다. 예를 들어 응용 프로그램이 메모리를 할당하거나 파일을 열 때 (syscall은 "brk"및 "open") 필요합니다.

이제 syscall은 짧은 이름 "brk"등과 해당 opcode를 가지며 시스템 고유 헤더 파일에 정의됩니다. 이 opcode가 동일하게 유지되는 한 재 컴파일하지 않고도 다른 업데이트 된 커널로 동일한 컴파일 된 userland 프로그램을 실행할 수 있습니다. 따라서 사전 컴파일 된 이진에서 사용되는 인터페이스이므로 ABI가 있습니다.


4

공유 라이브러리에서 코드를 호출하거나 컴파일 단위 사이의 코드를 호출하려면 객체 파일에 호출 레이블이 포함되어 있어야합니다. C ++는 데이터 숨기기를 강제하고 오버로드 된 메소드를 허용하기 위해 메소드 레이블의 이름을 맹 글링합니다. 따라서 동일한 ABI를 명시 적으로 지원하지 않으면 다른 C ++ 컴파일러의 파일을 혼합 할 수 없습니다.


4

ABI와 API를 구별하는 가장 좋은 방법은 다음과 같은 용도와 이유를 아는 것입니다.

x86-64의 경우 일반적으로 하나의 ABI가 있으며 x86 32 비트의 경우 다른 세트가 있습니다.

http://www.x86-64.org/documentation/abi.pdf

https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html

http://people.freebsd.org/~obrien/amd64-elf-abi.pdf

Linux + FreeBSD + MacOSX는 약간의 변형이 있습니다. Windows x64에는 자체 ABI가 있습니다.

http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/

ABI를 알고 다른 컴파일러가 그것을 따르는 것으로 가정하면 바이너리는 이론적으로 서로 호출하는 방법 (특히 라이브러리 API)을 알고 스택을 통해 또는 레지스터 등으로 매개 변수를 전달하는 방법을 알고 있습니다. 또는 함수를 호출 할 때 어떤 레지스터가 변경되는지 등 기본적으로 이러한 지식은 소프트웨어가 서로 통합하는 데 도움이됩니다. 레지스터 / 스택 레이아웃의 순서를 알면 많은 문제없이 어셈블리로 작성된 서로 다른 소프트웨어를 쉽게 조각 할 수 있습니다.

그러나 API는 다릅니다.

다른 소프트웨어가이 API를 사용하여 빌드되는 경우 서로 호출 할 수 있도록 인수가 정의 된 고급 기능 이름입니다. 그러나 SAME ABI의 추가 요구 사항을 준수해야합니다.

예를 들어 Windows는 POSIX API를 준수했습니다.

https://ko.wikipedia.org/wiki/Windows_Services_for_UNIX

https://ko.wikipedia.org/wiki/POSIX

또한 Linux는 POSIX를 준수합니다. 그러나 바이너리는 그냥 옮겨서 즉시 실행할 수는 없습니다. 그러나 POSIX 호환 API에서 동일한 이름을 사용했기 때문에 C에서 동일한 소프트웨어를 가져 와서 다른 OS에서 다시 컴파일하여 즉시 실행할 수 있습니다.

API는 사전 컴파일 단계 인 소프트웨어의 통합을 용이하게하기위한 것입니다. 따라서 ABI가 다르면 컴파일 후 소프트웨어가 완전히 다르게 보일 수 있습니다.

ABI는 바이너리 / 어셈블리 레벨에서 소프트웨어의 정확한 통합을 정의하기위한 것입니다.


Windows x86-64 호출 규칙은 다른 모든 x86-64 OS에서 사용하는 SysV 호출 규칙을 사용하지 않습니다. Linux / OS X / FreeBSD는 모두 동일한 호출 규칙을 공유 하지만 전체 ABI를 공유 하지는 않습니다 . OS의 ABI에는 시스템 호출 번호가 포함됩니다. 예를 들어 freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/…SYS_execve32 비트 리눅스에서는 11이지만 FreeBSD에서는 59 라고 말합니다 .
Peter Cordes

귀하의 의견에 감사드립니다 .ABI와 API의 차이점에 더 잘 응답하도록 내 의견을 수정했습니다.
피터 테오

호출 규칙과 전체 ABI (시스템 호출 및 모든 것)의 차이점이 여전히 없습니다. Linux (커널)가 FreeBSD 호환성 계층을 제공하기 때문에 Linux에서 일부 FreeBSD 바이너리를 실행할 수 있습니다. 그럼에도 불구하고 이것은 Linux가 제공하지 않는 FreeBSD ABI의 일부를 사용하지 않는 바이너리로 제한됩니다. (예 : FreeBSD 전용 시스템 호출) ABI 호환은 두 시스템 모두에서 동일하게 컴파일 할 수있을뿐만 아니라 동일한 바이너리를 실행할 수 있음을 의미합니다.
Peter Cordes

"FreeBSD 호환성 레이어"는 들어 본 적이 없습니다. 관련 리눅스 커널 소스 코드를 가리킬 수 있습니까? 그러나 그 반대는 존재합니다 : freebsd.org/doc/en_US.ISO8859-1/books/handbook/linuxemu.html .
피터 테오

내가 사용하는 것이 아닙니다. 나는 그런 것이 존재 한다고 생각 했지만 더 이상 존재하지 않을 것입니다. tldp.org/HOWTO/Linux+FreeBSD-6.html에 따르면 유지 관리되지 않았 으며 그 방법은 2000 년입니다. xD. unix.stackexchange.com/questions/172038/… 포기되지 않았 음을 확인합니다 (아무도 그것을 원하지 않을만큼). personality(2)설정할 수 있습니다 PER_BSD. 내가 본 기억이 생각 personality(PER_LINUX)strace출력 모든 시간,하지만 현대적인 64 비트 리눅스 바이너리는 더 이상 그렇게하지 않습니다.
Peter Cordes

4

Linux 공유 라이브러리 최소 실행 가능 ABI 예

공유 라이브러리와 관련하여 "안정적인 ABI를 갖는"의 가장 중요한 의미는 라이브러리 변경 후 프로그램을 다시 컴파일 할 필요가 없다는 것입니다.

예를 들어 :

  • 공유 라이브러리를 판매하는 경우 모든 새 릴리스에 대해 라이브러리에 의존하는 모든 것을 다시 컴파일해야하는 번거 로움을 사용자에게 저장합니다.

  • 사용자 배포판에 존재하는 공유 라이브러리에 의존하는 비공개 소스 프로그램을 판매하는 경우, 특정 버전의 대상 OS에서 ABI가 안정적이라고 확신 할 경우 사전 빌드를 적게 테스트하고 테스트 할 수 있습니다.

    이는 시스템의 많은 프로그램이 링크되는 C 표준 라이브러리의 경우 특히 중요합니다.

이제 나는 이것에 대한 최소한의 구체적인 실행 가능한 예를 제공하고 싶습니다.

main.c

#include <assert.h>
#include <stdlib.h>

#include "mylib.h"

int main(void) {
    mylib_mystruct *myobject = mylib_init(1);
    assert(myobject->old_field == 1);
    free(myobject);
    return EXIT_SUCCESS;
}

mylib.c

#include <stdlib.h>

#include "mylib.h"

mylib_mystruct* mylib_init(int old_field) {
    mylib_mystruct *myobject;
    myobject = malloc(sizeof(mylib_mystruct));
    myobject->old_field = old_field;
    return myobject;
}

mylib.h

#ifndef MYLIB_H
#define MYLIB_H

typedef struct {
    int old_field;
} mylib_mystruct;

mylib_mystruct* mylib_init(int old_field);

#endif

다음을 사용하여 컴파일 및 실행

cc='gcc -pedantic-errors -std=c89 -Wall -Wextra'
$cc -fPIC -c -o mylib.o mylib.c
$cc -L . -shared -o libmylib.so mylib.o
$cc -L . -o main.out main.c -lmylib
LD_LIBRARY_PATH=. ./main.out

이제 라이브러리 v2의 경우 mylib_mystruct호출 할 새 필드를 추가한다고 가정합니다.new_field .

다음 old_field과 같이 필드를 추가 한 경우 :

typedef struct {
    int new_field;
    int old_field;
} mylib_mystruct;

라이브러리를 재 구축했지만 main.out 어설 션이 실패합니다!

그 이유는 다음과 같습니다.

myobject->old_field == 1

첫 번째 int구조체 에 액세스하려고하는 어셈블리를 생성했습니다 . 이는 이제 new_field예상 대신old_field .

따라서이 변경으로 인해 ABI가 중단되었습니다.

경우, 그러나, 우리는 추가 new_field한 후 old_field:

typedef struct {
    int old_field;
    int new_field;
} mylib_mystruct;

이전에 생성 된 어셈블리는 여전히 첫 번째 어셈블리에 액세스합니다. int 구조체에 하고 프로그램은 여전히 ​​작동합니다 .ABI를 안정적으로 유지했기 때문입니다.

다음은 GitHub에서이 예제완전 자동화 된 버전입니다. .

이 ABI를 안정적으로 유지하는 또 다른 방법 mylib_mystruct불투명 구조체 로 취급하는 것입니다 메서드 도우미를 통해서만 해당 필드에 액세스하는 것입니다. 따라서 ABI를 안정적으로 유지할 수 있지만 더 많은 함수 호출을 수행하면 성능 오버 헤드가 발생합니다.

API 대 ABI

이전 예제에서 new_fieldbefore 를 추가 old_field하면 API가 아닌 ABI 만 중단 했다는 점에 주목하는 것이 흥미 롭습니다 .

이것이 의미하는 바는 main.c프로그램을 라이브러리에 대해 다시 컴파일 했다면 상관없이 작동했을 것입니다.

그러나 예를 들어 함수 서명을 변경 한 경우 API를 중단했을 수도 있습니다.

mylib_mystruct* mylib_init(int old_field, int new_field);

이 경우 main.c컴파일을 완전히 중지합니다.

시맨틱 API vs 프로그래밍 API

또한 시맨틱 변경이라는 세 번째 유형으로 API 변경을 분류 할 수 있습니다.

시맨틱 API는 일반적으로 API가 수행해야하는 것에 대한 자연어 설명이며 일반적으로 API 문서에 포함됩니다.

따라서 프로그램 빌드 자체를 중단하지 않고 시맨틱 API를 중단 할 수 있습니다.

예를 들어 수정 한 경우

myobject->old_field = old_field;

에:

myobject->old_field = old_field + 1;

그러면 프로그래밍 API 나 ABI가 모두 깨지지 않았지만 main.c의미 API가 깨졌습니다.

프로그래밍 방식으로 계약 API를 확인하는 두 가지 방법이 있습니다.

  • 코너 케이스를 테스트하십시오. 쉬운 일이지만 항상 놓칠 수 있습니다.
  • 공식적인 검증 . 수행하기는 더 어렵지만 수학적 정확성을 입증하여 문서와 테스트를 "인간"/ 기계 검증 가능한 방식으로 통합합니다! 공식적인 설명에 버그가없는 한 ;-)

    이 개념은 수학 자체의 공식화와 밀접한 관련이 있습니다. /math/53969/what-does-formal-mean/3297537#3297537

C / C ++ 공유 라이브러리 ABI를 망가 뜨리는 모든 것의 목록

TODO : 최고의 목록을 찾아서 작성하십시오.

Java 최소 실행 가능 예제

Java에서 이진 호환성이란 무엇입니까?

우분투 18.10, GCC 8.2.0에서 테스트되었습니다.


3

통화가 성공하려면 ABI가 발신자와 수신자간에 일관되어야합니다. 스택 사용, 레지스터 사용, 루틴 종료 스택 팝. 이 모든 것이 ABI의 가장 중요한 부분입니다.


3

요약

ABI (application binary interface)를 정의하는 정확한 계층에 대한 다양한 해석과 견해가 있습니다.

내 관점에서 ABI는 주관적인 규칙입니다 특정 API에 대해 주어진 / 플랫폼으로 간주되는 것에 입니다. ABI는 특정 API에 대해 "변경되지 않거나"실행기, 도구, 링커, 컴파일러, jvm 및 OS와 같은 런타임 환경에서 해결 될 규칙의 "휴식"입니다.

인터페이스 정의 : ABI, API

joda-time과 같은 라이브러리를 사용하려면에 대한 종속성을 선언해야합니다 joda-time-<major>.<minor>.<patch>.jar. 라이브러리는 모범 사례를 따르고 시맨틱 버전 관리를 사용 합니다. 이는 세 가지 수준에서 API 호환성을 정의합니다.

  1. 패치-모든 코드를 변경할 필요는 없습니다. 라이브러리는 일부 버그를 수정합니다.
  2. 사소한-추가 이후 코드를 변경할 필요가 없습니다
  3. 주요-인터페이스 (API)가 변경되었으며 코드를 변경해야 할 수도 있습니다.

동일한 라이브러리의 새로운 주요 릴리스를 사용하기 위해서는 많은 다른 규칙이 여전히 준수되어야합니다.

  • 라이브러리에 사용되는 이진 언어 (Java의 경우 Java 바이트 코드를 정의하는 JVM 대상 버전)
  • 전화 컨벤션
  • JVM 규칙
  • 연결 규칙
  • 런타임 규칙이 모든 것은 우리가 사용하는 도구에 의해 정의되고 관리됩니다.

자바 사례 연구

예를 들어, Java는 이러한 모든 규칙을 도구가 아닌 공식적인 JVM 사양으로 표준화했습니다. 이 사양을 통해 다른 공급 업체는 호환 가능한 라이브러리를 출력 할 수있는 다른 도구 세트를 제공 할 수있었습니다.

Java는 ABI에 대한 두 가지 흥미로운 사례 연구 인 Scala 버전과 Dalvik 가상 머신을 제공합니다.

Dalvik 가상 머신으로 ABI 중단

Dalvik VM에는 Java 바이트 코드와 다른 유형의 바이트 코드가 필요합니다. Dalvik 라이브러리는 Dalvik에 대한 Java 바이트 코드 (동일한 API로)를 변환하여 얻습니다. 이런 식으로 동일한 API의 두 가지 버전을 얻을 수 있습니다 : original에 의해 정의 됨 joda-time-1.7.2.jar. 우리는 저를 부를 수 joda-time-1.7.2.jarjoda-time-1.7.2-dalvik.jar. 이들은 스택 지향 표준 Java vms를위한 다른 ABI를 사용합니다. Oracle, IBM, Java 또는 기타; 두 번째 ABI는 Dalvik 주변의 ABI입니다.

스칼라 후속 릴리스는 호환되지 않습니다

스칼라는 부 스칼라 버전 (2.X) 사이에서 이진 호환성을 갖지 않습니다. 이러한 이유로 동일한 API "io.reactivex"%% "rxscala"% "0.26.5"에는 Scala 2.10, 2.11 및 2.12의 세 가지 버전이 있습니다 (향후 더). 무엇이 바뀌 었습니까? 지금은 모르겠지만 바이너리는 호환되지 않습니다. 아마도 최신 버전은 오래된 가상 머신에서 라이브러리를 사용할 수 없게 만드는 것들, 아마도 링크 / 이름 지정 / 매개 변수 규칙과 관련된 것들을 추가합니다.

Java 후속 릴리스가 호환되지 않습니다

Java는 또한 주요 JVM 릴리스 인 4,5,6,7,8,9에 문제가 있습니다. 이전 버전과의 호환성 만 제공합니다. Jvm9는 -target다른 모든 버전에 대해 컴파일 / 타겟팅 된 코드 (javac의 옵션)를 실행하는 방법을 알고 있지만 JVM 4는 JVM 5를 대상으로하는 코드를 실행하는 방법을 모릅니다. 이 비 호환성은 다른 솔루션 덕분에 레이더 아래로 날아갑니다.

  1. 시맨틱 버전 관리 : 라이브러리가 더 높은 JVM을 대상으로 할 때 일반적으로 주 버전을 변경합니다.
  2. JVM 4를 ABI로 사용하면 안전합니다.
  3. Java 9는 동일한 대상 라이브러리에 특정 대상 JVM에 대한 바이트 코드를 포함하는 방법에 대한 사양을 추가합니다.

API 정의로 시작한 이유는 무엇입니까?

API와 ABI는 호환성을 정의하는 방법에 대한 규칙 일뿐입니다. 하위 계층은 과도하게 높은 수준의 의미론과 관련하여 일반적입니다. 그렇기 때문에 몇 가지 규칙을 쉽게 만들 수 있습니다. 첫 번째 종류의 규칙은 메모리 정렬, 바이트 인코딩, 호출 규칙, 빅 엔디안 인코딩 및 리틀 엔디안 인코딩 등에 관한 것입니다. 그 위에는 설명 된 다른 규칙, 연결 규칙, Java에서 사용되는 것과 같은 중간 바이트 코드 또는 GCC에서 사용하는 LLVM IR 셋째, 라이브러리를 찾는 방법,로드하는 방법에 대한 규칙을 얻습니다 (Java 클래스 로더 참조). 개념이 점점 더 높아질수록 주어진 것으로 간주되는 새로운 규칙이 있습니다. 그것이 시맨틱 버전 으로하지 않은 이유 입니다. 그들은 암시 적이거나버전. 로 시맨틱 버전을 수정할 수 <major>-<minor>-<patch>-<platform/ABI>있습니다. 이 사실은 이미 무슨 일이 일어나고있는 것입니다 : 플랫폼이 이미있는 rpm, dll, jar(JVM 바이트 코드), warJVM (+ 웹 서버) apk, 2.11(특정 스칼라 버전) 등등. APK를 말할 때 이미 API의 특정 ABI 부분에 대해 이야기합니다.

API를 다른 ABI로 이식 가능

추상화의 최상위 레벨 (가장 높은 API로 작성된 소스는 다른 하위 레벨 추상화로 다시 컴파일 / 포팅 될 수 있습니다.

rxscala에 대한 소스가 있다고 가정 해 봅시다. 스칼라 도구가 변경되면 다시 컴파일 할 수 있습니다. JVM이 변경되면 높은 수준의 개념을 신경 쓰지 않고 이전 컴퓨터에서 새 컴퓨터로 자동 변환 할 수 있습니다. 포팅이 어려울 수 있지만 다른 클라이언트에게 도움이 될 것입니다. 완전히 다른 어셈블러 코드를 사용하여 새 운영 체제를 작성하면 변환기를 작성할 수 있습니다.

여러 언어로 포팅 된 API

반응 스트림 과 같은 여러 언어로 포팅되는 API가 있습니다 . 일반적으로 특정 언어 / 플랫폼에 대한 매핑을 정의합니다. API는 공식적으로 인간 언어 또는 특정 프로그래밍 언어로 정의 된 마스터 사양이라고 주장합니다. 다른 모든 "매핑"은 ABI라는 의미에서 일반적인 ABI보다 더 많은 API입니다. REST 인터페이스에서도 마찬가지입니다.


1

요컨대, 철학적으로는 일종의 것들만 잘 어울릴 수 있으며 ABI는 함께 작동하는 소프트웨어 의 종류 로 볼 수 있습니다 .


1

나는 또한 ABI를 이해하려고 노력했으며 JesperE의 대답은 매우 도움이되었습니다.

매우 간단한 관점에서 바이너리 호환성을 고려하여 ABI를 이해하려고 시도 할 수 있습니다.

KDE 위키는 라이브러리를 바이너리 호환으로 정의합니다. "이전 버전의 라이브러리에 동적으로 링크 된 프로그램이 다시 컴파일 할 필요없이 최신 버전의 라이브러리로 계속 실행되는 경우" 동적 연결에 대한 자세한 내용은 정적 연결 및 동적 연결을 참조하십시오.

이제 라이브러리가 바이너리 호환성이되는 데 필요한 가장 기본적인 측면 만 살펴 보도록하겠습니다 (라이브러리에 대한 소스 코드 변경이 없다고 가정).

  1. 동일 / 역 호환 가능한 명령어 세트 아키텍처 (프로세서 명령어, 레지스터 파일 구조, 스택 구성, 메모리 액세스 유형, 프로세서가 직접 액세스 할 수있는 기본 데이터 유형의 크기, 레이아웃 및 정렬)
  2. 동일한 통화 규칙
  3. 동일한 이름 조작 규칙 (Fortran 프로그램이 일부 C ++ 라이브러리 함수를 호출해야하는 경우 필요할 수 있음).

물론 많은 다른 세부 사항이 있지만 이것은 대부분 ABI가 다루는 것입니다.

더 구체적으로, 위의 질문에 답하기 위해 다음을 추론 할 수 있습니다.

ABI 기능 : 이진 호환성

기존 엔터티 : 기존 프로그램 / 라이브러리 / OS

소비자 : 라이브러리, OS

도움이 되었기를 바랍니다!


1

응용 프로그램 이진 인터페이스 (ABI)

기능성 :

  • 프로그래머의 모델에서 기본 시스템의 도메인 데이터 유형, 크기, 정렬, 호출 규칙으로의 변환. 함수의 인수가 전달되고 값을 검색하는 방법을 제어합니다. 시스템 호출 번호 및 응용 프로그램이 운영 체제를 시스템 호출하는 방법 고급 언어 컴파일러의 이름 관리 체계, 예외 전파 및 동일한 플랫폼의 컴파일러 간 호출 규칙이지만 플랫폼 간 호환성이 필요하지 않습니다.

기존 엔터티 :

  • 프로그램 실행에 직접 참여하는 논리 블록 : ALU, 범용 레지스터, I / O의 메모리 / I / O 매핑 레지스터 등

소비자:

  • 언어 프로세서 링커, 어셈블러 ...

빌드 툴 체인이 전체적으로 작동하도록 보장해야하는 사람이라면 누구나 필요합니다. 하나의 모듈을 어셈블리 언어로, 다른 모듈을 파이썬으로 작성하고 자신의 부트 로더 대신 운영 체제를 사용하려는 경우 "응용 프로그램"모듈이 "이진"경계를 넘어서 작동하며 이러한 "인터페이스"의 동의가 필요합니다.

응용 프로그램에서 다른 고급 언어의 개체 파일을 연결해야 할 수 있기 때문에 C ++ 이름 조작. Visual C ++로 작성된 Windows에 대한 시스템 호출을 만드는 GCC 표준 라이브러리 사용을 고려하십시오.

JVM은 다른 아이디어가있을 수 있지만 ELF는 해석을 위해 객체 파일에서 링커를 기대할 수 있습니다.

Windows RT 스토어 앱의 경우 빌드 도구 체인을 함께 작동 시키려면 ARM ABI를 검색해보십시오.


1

ABI라는 용어는 별개의 두 가지 관련 개념을 나타내는 데 사용됩니다.

컴파일러에 대해 언급 할 때 소스 레벨 구성에서 이진 구성으로 변환하는 데 사용되는 규칙을 말합니다. 데이터 유형이 얼마나 큽니까? 스택은 어떻게 작동합니까? 매개 변수를 함수에 어떻게 전달합니까? 발신자 대 수신자가 어떤 레지스터를 저장해야합니까?

라이브러리에 대해 언급 할 때 컴파일 된 라이브러리가 제공하는 이진 인터페이스를 나타냅니다. 이 인터페이스는 라이브러리의 소스 코드, 컴파일러가 사용하는 규칙 및 일부 경우 다른 라이브러리에서 가져온 정의를 포함하여 여러 가지 요인의 결과입니다.

라이브러리를 변경하면 API를 중단하지 않고 ABI가 중단 될 수 있습니다. 예를 들어 인터페이스가 같은 라이브러리를 고려하십시오.

void initfoo(FOO * foo)
int usefoo(FOO * foo, int bar)
void cleanupfoo(FOO * foo)

응용 프로그램 프로그래머는 다음과 같은 코드를 작성합니다.

int dostuffwithfoo(int bar) {
  FOO foo;
  initfoo(&foo);
  int result = usefoo(&foo,bar)
  cleanupfoo(&foo);
  return result;
}

응용 프로그램 프로그래머는 FOO의 크기 나 레이아웃에 신경 쓰지 않지만 응용 프로그램 이진은 하드 코딩 된 크기의 foo로 끝납니다. 라이브러리 프로그래머가 foo에 여분의 필드를 추가하고 누군가가 이전 응용 프로그램 바이너리와 함께 새로운 라이브러리 바이너리를 사용하는 경우 라이브러리가 범위를 벗어난 메모리 액세스를 할 수 있습니다.

라이브러리 작성자가 API를 설계 한 경우 OTOH

FOO * newfoo(void)
int usefoo(FOO * foo, int bar)
void deletefoo((FOO * foo, int bar))

응용 프로그램 프로그래머는 다음과 같은 코드를 작성합니다.

int dostuffwithfoo(int bar) {
  FOO * foo;
  foo = newfoo();
  int result = usefoo(foo,bar)
  deletefoo(foo);
  return result;
}

그런 다음 응용 프로그램 바이너리는 FOO의 구조에 대해 아무것도 알 필요가 없으며 라이브러리 안에 모두 숨길 수 있습니다. 당신이 지불하는 가격은 힙 작업이 관련되어 있다는 것입니다.


0

ABI- Application Binary Interface에서 기계 코드 통신에 관한 런타임 이 개 바이너리 프로그램 사이의 부분 처럼 - 응용 프로그램, 라이브러리, OS ... ABI(객체가 메모리에 저장되고 기능이 어떻게 호출되는 방법을 설명합니다 calling convention)

API와 ABI의 좋은 예는 Swift 언어의 iOS 에코 시스템입니다 .

  • Application-다른 언어를 사용하여 응용 프로그램을 만들 때 예를 들어 Swift[Mixing Swift and Objective-C]를 사용하여 응용 프로그램을 만들 수 있습니다 Objective-C.

  • Application - OS- 실행 - Swift runtimestandard librariesOS의 일부이며 그들은 각각의 묶음으로 (예 : 응용 프로그램 프레임 워크)를 포함 할 수 없습니다. Objective-C가 사용하는 것과 동일합니다.

  • Library- Module Stability사례- 컴파일 시간 - 다른 버전의 Swift 컴파일러로 빌드 된 프레임 워크 를 가져올 수 있습니다 . 그것은 다른 버전의 컴파일러 ( .swiftinterface와 함께 사용됨 .swiftmodule)에 의해 소비되는 폐쇄 소스 (사전 빌드) 바이너리를 생성하는 것이 안전하다는 것을 의미합니다.

    Module compiled with _ cannot be imported by the _ compiler
    
  • Library- Library Evolution사례

    1. 컴파일 시간-종속성이 변경된 경우 클라이언트를 다시 컴파일하지 않아도됩니다.
    2. 런타임-시스템 라이브러리 또는 동적 프레임 워크를 새로운 것으로 핫 스왑 할 수 있습니다.

[API 대 ABI]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.