소프트웨어 OS가 특정한 이유는 무엇입니까?


77

특정 운영 체제에서 프로그래밍 언어를 사용하여 제작 된 소프트웨어가 작동하는 이유에 대한 기술적 세부 정보를 확인하려고합니다.

바이너리는 그들이 이해하는 프로세서 특정 기계 언어와 다른 프로세서간에 다른 명령어 세트로 인해 특정 프로세서에 고유하다는 것을 이해합니다. 그러나 운영 체제 고유성은 어디에서 오는가? 나는 그것이 OS에서 제공하는 API라고 가정했지만 책 에서이 다이어그램을 보았습니다. 도표

운영 체제-내부 및 디자인 원칙 7th ed-W. Stallings (Pearson, 2012)

보시다시피 API는 운영 체제의 일부로 표시되지 않습니다.

예를 들어 다음 코드를 사용하여 C로 간단한 프로그램을 작성합니다.

#include<stdio.h>

main()
{
    printf("Hello World");

}

컴파일러는 이것을 컴파일 할 때 OS 특정 작업을 수행합니까?


15
창으로 인쇄합니까? 아니면 콘솔? 또는 그래픽 메모리? 거기에 데이터를 어떻게 넣습니까? Apple의 printf를 살펴보면] [+는 Mac OS 7과는 다른 것이 아니라 Mac OS X과는 매우 다른 것입니다 (컴퓨터 한 줄만 고착).

3
Mac OS 7 용 코드를 작성하면 새 창에 텍스트로 표시되기 때문입니다. Apple에서] [+를 사용하면 메모리의 일부 세그먼트에 직접 쓰는 것입니다. Mac OS X에서는 콘솔에 기록합니다. 따라서 라이브러리 계층에서 처리하는 실행 하드웨어를 기반으로 코드 처리를 작성하는 세 가지 방법이 있습니다.

2
@StevenBurnap 네 - en.wikipedia.org/wiki/Aztec_C

10
FFT 기능은 재 컴파일하지 않고도 Windows 또는 Linux (동일한 CPU)에서 행복하게 실행됩니다. 그러나 결과를 어떻게 표시 할 것입니까? 물론 운영 체제 API를 사용합니다. ( printfmsvcr90.dll printf에서 libc.so.6 에서와 동일하지 않음 )
user253751

9
API가 "운영 체제의 일부가 아니더라도"한 OS에서 다른 OS로 갈 경우 여전히 다릅니다. (물론 다이어그램에 따르면 "운영 체제의 일부가 아닌"이라는 문구가 실제로 무엇을 의미하는지에 대한 의문이 제기됩니다.)
Theodoros Chatzigiannakis

답변:


78

코드가 CPU에 특정한 경우, OS에 특정한 코드 인 이유를 언급합니다. 이것은 실제로 많은 답변이 가정 한 흥미로운 질문입니다.

CPU 보안 모델

대부분의 CPU 아키텍처에서 실행되는 첫 번째 프로그램 은 내부 링 또는 링 0 내부에서 실행됩니다 . 특정 CPU 아치가 링을 구현하는 방법은 다양하지만 거의 모든 최신 CPU에는 최소 2 가지 작동 모드가 있습니다. 하나는 특권이 있고 CPU가 수행 할 수있는 모든 법적 작업을 수행 할 수있는 '베어 메탈'코드를 실행합니다. 신뢰할 수없고 정의 된 안전한 기능 세트 만 수행 할 수있는 보호 된 코드를 실행합니다. 그러나 일부 CPU는 세분성이 훨씬 높고 VM을 안전하게 사용하기 위해서는 최소 1 또는 2 개의 추가 링이 필요하지만 (종종 음수로 표시)이 범위를 벗어납니다.

OS가 들어오는 곳

초기 단일 작업 OS

초창기 DOS 및 기타 초기 단일 작업 기반 시스템에서 모든 코드는 내부 링에서 실행되었으며, 실행 한 모든 프로그램은 전체 컴퓨터를 최대한 활용했으며 모든 데이터를 지우거나 하드웨어 손상을 포함하여 잘못 작동하면 문자 그대로 모든 작업을 수행 할 수 있습니다 아주 오래된 디스플레이 화면에서 유효하지 않은 디스플레이 모드를 설정하는 것과 같은 극단적 인 경우에는 악의가없는 버그가있는 코드로 인해 발생할 수 있습니다.

이 코드는 프로그램을 메모리에로드 할 수있는 로더 (초기 이진 형식의 경우 매우 간단)가 있고 코드가 드라이버에 의존하지 않고 모든 하드웨어 액세스 자체를 구현하는 한 실제로 OS에 구애받지 않습니다. 링 0에서 실행되는 한 모든 OS입니다. 참고 : 이와 같은 매우 간단한 OS 는 단순히 다른 프로그램을 실행하는 데 사용되며 추가 기능을 제공하지 않는 경우 일반적으로 모니터라고 합니다.

최신 멀티 태스킹 OS

UNIX , NT로 시작하는 Windows 버전 및 기타 다양한 OS가 현재 상황을 개선하기로 결정한 최신 운영 체제 는 사용자가 멀티 태스킹과 같은 추가 기능을 원했기 때문에 한 번에 두 개 이상의 응용 프로그램을 실행하고 보호 할 수있는 버그를 추가했습니다. 응용 프로그램의 악성 코드)는 더 이상 컴퓨터와 데이터에 무제한의 피해를 줄 수 없습니다.

이것은 위에서 언급 한 링을 사용하여 수행되었으며 OS는 링 0에서 실행되는 유일한 위치를 차지하고 응용 프로그램은 신뢰할 수없는 외부 링에서 실행되며 OS가 허용 한 제한된 작업 세트 만 수행 할 수 있습니다.

그러나 이렇게 증가 된 유틸리티 및 보호는 비용이 들었고, 프로그램은 이제 스스로 할 수없는 작업을 수행하기 위해 OS와 협력해야했으며 더 이상 예를 들어 메모리에 액세스하여 임의의 하드 디스크를 직접 변경하여 하드 디스크를 직접 제어 할 수 없었습니다. 대신에, 그들은 OS에 요청하지 않은 파일을 변경하지 않고 작업을 수행 할 수 있는지 확인하고 작업이 실제로 유효한지 확인하기 위해 이러한 작업을 수행하도록 OS에 요청해야했습니다. 하드웨어를 정의되지 않은 상태로 두지 않습니다.

각 OS는 이러한 보호에 대해 서로 다른 구현을 결정했습니다. 부분적으로 OS가 설계된 아키텍처와 부분적으로 해당 OS의 디자인과 원칙을 기반으로합니다. 예를 들어 UNIX는 다중 사용자 사용에 적합하고 집중된 머신에 중점을 둡니다. Windows가 더 단순하게 설계되고 단일 사용자로 느린 하드웨어에서 실행되도록이 기능을 사용할 수 있습니다. 사용자 공간 프로그램이 OS와 통신하는 방식은 X86에서 ARM 또는 MIPS와는 완전히 다르므로 멀티 플랫폼 OS가 대상 하드웨어에서 작업해야 할 필요성에 따라 결정을 내려야합니다.

이러한 OS 별 상호 작용을 일반적으로 "시스템 호출"이라고하며 사용자 공간 프로그램이 OS를 통해 하드웨어와 완전히 상호 작용하는 방식을 포함합니다. OS의 기능에 따라 근본적으로 다르므로 시스템 호출을 통해 작동하는 프로그램은 OS에 따라 다릅니다.

프로그램 로더

시스템 호출에 더하여, 각각의 OS는로부터 프로그램을로드하기위한 다양한 방법을 제공하는 보조 저장 매체메모리 는 방법 일 수있는 프로그램이 OS를 설명하는 특수 헤더를 포함해야 특정 OS에 의해 수하물되기 위해서는, 로드하고 실행합니다.

이 헤더 는 다른 형식 의 로더작성하는 것이 거의 사소한 것이었지만 동적 링크 및 약한 선언과 같은 고급 기능을 지원하는 elf와 같은 최신 형식에서는 OS가 바이너리를로드하려고 시도하는 것이 거의 불가능합니다. 이것은 시스템 호출 비 호환성이 없더라도 프로그램을 실행할 수있는 방식으로 램에 배치하는 것은 매우 어렵다는 것을 의미합니다.

도서관

프로그램은 시스템 호출을 거의 사용하지 않지만 시스템 호출을 프로그래밍 언어에 대해 약간 더 친숙한 형식으로 래핑하는 라이브러리를 통해 거의 독점적으로 기능을 얻습니다. Windows NT 이상에서는 대부분의 다른 프로그래밍 언어에도 비슷한 방식으로 시스템 기능을 래핑하는 유사한 라이브러리가 있습니다.

이러한 라이브러리는 위에서 설명한 바와 같이 크로스 플랫폼 문제를 어느 정도 극복 할 수 있으며, SDL과 같은 광범위한 OS에 대한 호출을 내부적으로 관리하면서 애플리케이션에 균일 한 플랫폼을 제공하도록 설계된 다양한 라이브러리가 있습니다 . 프로그램은 이진 호환이 될 수 없으며, 이러한 라이브러리를 사용하는 프로그램은 플랫폼간에 공통 소스를 가질 수 있으므로 재 컴파일처럼 간단하게 이식 할 수 있습니다.

위의 예외

여기에 언급 한 모든 내용에도 불구하고 둘 이상의 운영 체제에서 프로그램을 실행할 수 없다는 한계를 극복하려는 시도가있었습니다. 몇 가지 좋은 예는 Win32 프로그램 로더, 이진 형식 및 Windows 라이브러리가 다양한 UNIX에서 실행될 수 있도록하는 시스템 라이브러리를 성공적으로 에뮬레이트 한 Wine 프로젝트 입니다. 또한 여러 BSD UNIX 운영 체제에서 Linux 소프트웨어를 실행할 수있는 호환성 계층과 물론 MacOS X에서 이전 MacOS 소프트웨어를 실행할 수있는 Apple 자체의 심이 있습니다.

그러나 이러한 프로젝트는 엄청난 수준의 수동 개발 노력을 통해 작동합니다. 두 OS가 얼마나 다른지에 따라 난이도가 비교적 작은 심에서 다른 OS의 거의 완전한 에뮬레이션에 이르기까지 전체 운영 체제 자체를 작성하는 것보다 더 복잡하기 때문에 규칙이 아니라 예외입니다.


6
+1 "소프트웨어 OS는 왜 고유합니까?" 역사이기 때문에.
Paul Draper

2
CPU 보안 모델이 x86에서 시작 되었습니까? 왜 그리고 언제 모델이 발명 되었습니까?
n611x007

8
@naxa 아니요, x86보다 오래 전부터 1969 년 Multics를 위해 부분적으로 처음 구현되었으며 GE-645 컴퓨터 에서이 모델을 필요로하는 유용한 다중 사용자 시간 공유 기능을 갖춘 최초의 OS입니다 . 소프트웨어 지원, 하드웨어에서 최초의 완전하고 안전한 구현은 그 후속 제품인 Honeywell 6180 이었습니다. 이것은 완전히 하드웨어 기반이었으며 Multics가 교차 간섭의 기회없이 여러 사용자의 코드를 실행할 수있게했습니다.
Vality

@Vality 또한 IBM LPAR 은 ~ 1972입니다.
Elliott Frisch 1

@ElliottFrisch 와우, 그것은 인상적입니다. 나는 그것이 그렇게 이른 것을 깨닫지 못했습니다. 그 정보 주셔서 감사합니다.
Vality

48

보시다시피 API는 운영 체제의 일부로 표시되지 않습니다.

나는 당신이 다이어그램을 너무 많이 읽고 있다고 생각합니다. 예, OS는 운영 체제 함수 호출 방법에 대한 이진 인터페이스를 지정하고 실행 파일의 파일 형식도 정의하지만 호출 할 수있는 함수 카탈로그를 제공한다는 의미에서 API도 제공합니다. OS 서비스를 호출하는 애플리케이션

다이어그램은 단지 운영 체제 기능이 일반적으로 간단한 라이브러리 호출과 다른 메커니즘을 통해 호출된다는 것을 강조하려고한다고 생각합니다. 일반적인 OS의 대부분은 프로세서 인터럽트를 사용하여 OS 기능에 액세스합니다. 일반적인 최신 운영 체제에서는 사용자 프로그램이 하드웨어에 직접 액세스 할 수 없습니다 . 콘솔에 문자를 쓰려면 OS에 요청해야합니다. 콘솔에 쓰는 데 사용되는 시스템 호출은 OS마다 다르므로 소프트웨어가 OS에 특정한 이유에 대한 예가 있습니다.

printf는 C 런타임 라이브러리의 함수이며 일반적인 구현에서는 상당히 복잡한 함수입니다. Google을 사용하면 온라인에서 여러 버전의 소스를 찾을 수 있습니다. 하나의 가이드 투어는이 페이지를 참조하십시오 . 풀에서 다운되었지만 하나 이상의 시스템 호출이 발생하고 각 시스템 호출은 호스트 운영 체제에 따라 다릅니다.


4
모든 프로그램이 입력 또는 출력없이 두 개의 숫자를 추가하는 것이라면 어떨까요? 그 프로그램이 여전히 OS에 특정한 것입니까?
Paul

2
OS는 대부분의 하드웨어 관련 사항을 추상화 계층 뒤에 배치하기위한 것입니다. 그러나 OS 자체 (추상화)는 구현마다 다를 수 있습니다. POSIX는 일부 OS (약간 또는 이하)가 고수하고 일부는있을 수 있지만 전체 OS는 추상화의 "보이는"부분에서 너무 많이 다릅니다. 앞에서 말했듯이 : Windows에서 / home / user를 열 수 없으며 * N * X 시스템에서 HKEY_LOCAL_MACHINE \ ...에 액세스 할 수 없습니다. 당신은 할 수 있습니다 이 가까이 함께 이러한 시스템을 유치하는 데 도움하지만 항상 (OS POV에서) "3 자"입니다 가상 ( "에뮬레이션") 소프트웨어를 작성.
RobIII

16
@ 폴 네. 특히, 실행 파일로 패키지되는 방식은 OS마다 다릅니다.
OrangeDog

4
@TimSeguine 저는 XP 대 7에 대한 귀하의 의견에 동의하지 않습니다. XP에서와 동일한 API가 7에 존재하도록 많은 작업이 Microsoft에 의해 수행됩니다. 분명히 여기서 일어난 일은 프로그램이 특정 API 또는 계약에 대해 실행되도록 설계되었다는 것입니다. 새로운 OS는 동일한 API / 계약을 준수했습니다. 그러나 Windows의 경우 API는 매우 독점적이므로 다른 OS 공급 업체는이를 지원하지 않습니다. 그럼에도 불구하고 7에서 실행되지 않는 많은 프로그램의 예가 많이 있습니다.
ArTs

3
@Paul : 입력 / 출력이없는 프로그램비어있는 프로그램 이며, no-op로 컴파일해야합니다.
Bergi

14

컴파일러는 이것을 컴파일 할 때 OS 특정 작업을 수행합니까?

아마. 컴파일 및 링크 프로세스 중 어느 시점에서 코드는 OS 특정 바이너리로 바뀌고 필요한 라이브러리와 연결됩니다. OS가 프로그램을로드하고 실행을 시작할 수 있도록 프로그램은 운영 체제가 예상하는 형식으로 저장해야합니다. 또한 표준 라이브러리 기능을 호출합니다.이 기능 printf()은 운영 체제가 제공하는 서비스 측면에서 구현됩니다.

라이브러리는 운영 체제와 하드웨어의 추상화 계층 인 인터페이스를 제공하므로 다른 운영 체제 나 다른 하드웨어에 맞게 프로그램을 다시 컴파일 할 수 있습니다. 그러나 추상화는 소스 수준에서 존재합니다. 일단 프로그램이 컴파일되고 연결되면 해당 OS의 특정 인터페이스 구현에 연결됩니다.


12

여러 가지 이유가 있지만 매우 중요한 이유는 운영 체제가 프로그램을 구성하는 일련의 바이트를 메모리로 읽고 해당 프로그램과 함께 제공되는 라이브러리를 찾아 메모리에로드하는 방법을 알아야한다는 것입니다. 그런 다음 프로그램 코드를 실행하십시오. 이를 위해 OS 작성자는 일련의 바이트에 대해 특정 형식을 작성하여 OS 코드가 프로그램 구조의 다양한 부분을 찾을 위치를 알 수 있도록합니다. 주요 운영 체제마다 작성자가 다르기 때문에 이러한 형식은 종종 서로 관련이 없습니다. 특히 Windows 실행 파일 형식 은 대부분의 Unix 변형이 사용 하는 ELF 형식 과 거의 공통점이 없습니다 . 따라서이 모든로드, 동적 링크 및 실행 코드는 OS마다 달라야합니다.

다음으로, 각 OS는 하드웨어 계층과 통신하기위한 서로 다른 라이브러리 세트를 제공합니다. 이것들은 당신이 언급 한 API이며, 일반적으로 개발자에게 더 간단한 인터페이스를 제공하면서 더 복잡하고 더 구체적인 호출을 OS 자체의 깊이로 변환하는 라이브러리입니다.이 호출은 종종 문서화되지 않거나 안전합니다. 최신 "OS"API가 이전 API에 부분적으로 또는 전체적으로 구축되므로이 계층은 종종 매우 회색입니다. 예를 들어, Windows에서 Microsoft가 수년에 걸쳐 생성 한 많은 최신 API는 본질적으로 원래 Win32 API 위에있는 계층입니다.

귀하의 예에서는 발생하지 않지만 개발자가 직면하는 가장 큰 문제 중 하나는 GUI를 나타내는 창 관리자와의 인터페이스입니다. 창 관리자가 "OS"의 일부인지 여부는 때때로 OS 자체뿐만 아니라 Windows의 GUI가 OS와 더 깊은 수준으로 통합되는 반면 Linux 및 OS X의 GUI는 더 직접적으로 분리됩니다. 오늘날 사람들이 일반적으로 "운영 체제"라고 부르는 것은 많은 응용 프로그램 수준 구성 요소가 포함되어 있기 때문에 교과서에서 설명하는 것보다 훨씬 큰 힘이되기 때문에 매우 중요합니다.

마지막으로 OS 문제는 아니지만 실행 파일 생성에서 중요한 것은 시스템마다 다른 어셈블리 언어 대상이 있으므로 실제 생성 된 객체 코드가 달라야한다는 것입니다. 이것은 엄격하게 "OS"문제가 아니라 하드웨어 문제이지만, 하드웨어 플랫폼마다 다른 빌드가 필요하다는 것을 의미합니다.


2
로드 된 코드를 유지하는 데 필요한 것보다 적은 양의 RAM (있는 경우) 만 사용하여 더 간단한 실행 파일 형식을로드 할 수있는 반면, 더 복잡한 형식의 경우에는 경우에 따라 더 큰 RAM 풋 프린트가 필요할 수 있습니다. 후에도 로딩. MS-DOS는 임의의 세그먼트의 오프셋 0x100에서 시작하여 RAM에 순차적 바이트를 읽어서 최종 주소로 CX를로드 한 다음 점프하여 COM 파일을 최대 63.75K까지로드합니다. 단일 패스 컴파일은 백 패치 (플로피와 함께 사용)없이 수행 할 수 있습니다.
supercat

1
... 컴파일러가 각 루틴에 모든 패치 포인트 목록을 포함시킵니다. 각 패치 목록에는 이전과 같은 목록의 주소가 포함되며 마지막 목록의 주소는 코드 끝에 배치됩니다. OS는 코드를 원시 바이트로로드하지만 코드의 작은 루틴은 코드의 주요 부분을 실행하기 전에 필요한 모든 주소 패치를 적용 할 수 있습니다.
supercat

9

에서 다른 답변 내 :

초기 DOS 시스템과 Microsoft의 세계 기여는 다음과 같습니다.

Autocad는 인쇄 할 수있는 각 프린터마다 드라이버를 작성해야했습니다. 연꽃 1-2-3도 마찬가지였습니다. 실제로 소프트웨어를 인쇄하려면 고유 한 드라이버를 작성해야합니다. 10 개의 프린터와 10 개의 프로그램이 있다면, 본질적으로 동일한 코드의 100 개의 서로 다른 조각을 개별적으로 독립적으로 작성해야했습니다.

Windows 3.1에서 달성하려는 작업 (GEM 및 기타 여러 추상화 계층과 함께)은 프린터 제조업체가 프린터에 대해 하나의 드라이버를 작성하고 프로그래머가 Windows 프린터 클래스에 대해 하나의 드라이버를 작성하도록합니다.

이제 10 개의 프로그램과 10 개의 프린터를 사용하면 20 개의 코드 만 작성하면되고, 코드의 Microsoft 측면이 모든 사람에게 동일하기 때문에 MS의 예제는 수행해야 할 작업이 거의 없음을 의미했습니다.

이제 프로그램은 지원하기로 선택한 10 대의 프린터 만이 아니라 제조업체가 Windows 용 드라이버를 제공 한 모든 프린터로 제한되었습니다.

따라서 OS는 응용 프로그램에 서비스를 제공하므로 응용 프로그램이 중복 작업을 수행 할 필요가 없습니다.

예제 C 프로그램은 printf를 사용하여 문자를 사용자 인터페이스에 표시하는 OS 특정 자원 인 stdout으로 문자를 보냅니다. 프로그램은 사용자 인터페이스의 위치를 ​​알 필요가 없습니다. DOS에있을 수 있고, 그래픽 창에있을 수 있으며, 다른 프로그램에 파이프되어 다른 프로세스에 대한 입력으로 사용될 수 있습니다.

OS가 이러한 리소스를 제공하므로 프로그래머는 적은 노력으로 훨씬 더 많은 것을 달성 할 수 있습니다.

그러나 프로그램을 시작하는 것조차 복잡합니다. OS는 처음에 실행 파일 에 OS를 시작하는 방법과 일부 경우 (Android 또는 iOS와 같은 고급 환경) 외부에있는 리소스를 만지기 때문에 승인이 필요한 리소스를 알려주 는 실행 파일 에 특정 정보가있을 것으로 예상합니다 . "샌드 박스"-사용자 및 기타 앱이 오작동하는 프로그램으로부터 보호하는 데 도움이되는 보안 조치입니다.

따라서 실행 가능한 머신 코드가 동일하고 필요한 OS 리소스가 없어도 Windows 용으로 컴파일 된 프로그램은 동일한 에뮬레이션이나 변환 계층이없는 OS X 운영 체제에서 동일한 정확한 하드웨어에서도 실행되지 않습니다.

초기 DOS 스타일 운영 체제는 종종 동일한 API (BIOS)를 구현하고 하드웨어에 연결하여 서비스를 제공하기 때문에 프로그램을 공유 할 수 있습니다. 따라서 일련의 프로세서 명령어의 메모리 이미지 인 COM 프로그램 을 작성하고 컴파일 한 경우 CP / M, MS-DOS 및 기타 여러 운영 체제에서 실행할 수 있습니다. 실제로 최신 Windows 시스템에서 COM 프로그램을 계속 실행할 수 있습니다. 다른 운영 체제는 동일한 BIOS API 후크를 사용하지 않으므로 COM 프로그램은 에뮬레이션 또는 변환 계층없이 다시 실행되지 않습니다. EXE 프로그램은 단순한 프로세서 명령 이상을 포함하는 구조를 따르므로 메모리에로드하고 실행하는 방법을 이해하지 못하는 시스템에서는 API 문제와 함께 실행되지 않습니다.


7

사실, 진짜 답이 있다는 것입니다 경우 모든 OS가했던 것과 같은 실행 가능한 바이너리 파일 레이아웃을 이해 하고 (운영체제가 제공하는 않는) 경우에만 OS는 것으로합니다 (C 표준 라이브러리처럼) 표준화 기능에 자신을 제한, 당신의 소프트웨어는 실제로 모든 OS에서 실행됩니다.

물론 현실은 그렇지 않습니다. EXE파일은 같은 형식이없는 ELF그래서 각 운영 체제는 모든 파일 형식을 해석 할 수 있어야합니다 *. 모두 같은 CPU에 대한 바이너리 코드를 포함하더라도, 파일을, 그리고 그들은 단순히이 작업을 수행하지 않았다 에 그들이 나중에 그렇게 시작할 이유가 없었습니다 (거의 확실히 기술적 인 이유보다는 상업적인 이유로).

또한 프로그램은 C 라이브러리가 수행하지 않는 방법 (디렉토리의 내용을 나열하는 것과 같은 간단한 작업의 경우에도)을 수행해야 할 경우가 있으며, 이러한 경우 모든 OS는 사용자의 달성을위한 자체 기능을 제공합니다. 자연스럽게 당신이 사용할 분모가 가장 낮다는 것을 의미합니다 ( 분모를 직접 만들지 않는 한 ).

따라서 원칙적으로 완벽하게 가능합니다. 실제로 WINE은 Linux에서 Windows 실행 파일을 직접 실행 합니다 .
그러나 그것은 많은 작업이며 (보통) 상업적으로 정당화되지 않습니다.

* 참고 : 이진 코드보다 실행 파일에 더 많은 것이 있습니다. 있다 이에 수출 기능 무엇을 필요로 얼마나 많은 스택 메모리, 파일에 따라 도서관 어떤 운영 체제를 알려줍니다 정보, 다른 운영 체제 관련 디버그 정보를 찾을 수 있습니다 그것은에 따라 달라질 수 있습니다 라이브러리는, "어떻게 필요한 경우 파일을 메모리에 재배치 "하고 예외 처리가 올바르게 작동하는 방법 등을 다시 한 번 반복하십시오. 모든 사람이 동의하는 단일 형식이 있을 있지만 단순히 그렇지 않습니다.


재미있는 사실 : OS간에 실행할 수있는 표준화 된 posiz 이진 형식이 있습니다. 그것은 일반적으로 사용되지 않습니다.
Marcin

@Marcin : Windows를 OS로 간주하지 않는 것 같습니다. (또는 Windows가 POSIX 바이너리를 실행할 수 있다고 말하는가?) 내 대답의 목적 상 POSIX는 내가 말하는 표준이 아닙니다. POSIX의 X는 Unix를 나타냅니다. Windows에 POSIX 하위 시스템이 있더라도 Windows에서 사용하도록 의도 된 것은 아닙니다.
Mehrdad

1. 모든 OS에서 실행하지 않고 여러 OS에서 실행할 수 있습니다. 2. NT 이후 Windows는 posix 바이너리를 실행할 수있었습니다.
Marcin

1
@Marcin : (1) POSIX의 X는 UNIX를 나타냅니다 . 그것은 다른 OS가 따라야 할 표준이 아니며 다양한 유닉스 사이의 공통 분모에 도달하려는 시도 일뿐입니다. 여러 가지 유닉스 운영체제가 존재한다는 사실은 제가 유닉스 이외의 다른 운영 체제에서 호환성에 대해 만들려고 한 시점과는 전혀 관련이 없습니다 . (2) # 2에 대한 참조를 제공 할 수 있습니까?
Mehrdad

1
@Mehrdad : Marcin이 옳습니다. Windows SUA (Unix 응용 프로그램 용 하위 시스템)는 POSIX 호환
MSalters

5

다이어그램에는 "라이브러리"에 의해 "운영 체제"레이어와 "애플리케이션"레이어 (대부분)가 분리되어 있으며 "애플리케이션"과 "OS"는 서로를 알 필요가 없습니다. 그것은 다이어그램의 단순화이지만, 사실이 아닙니다.

문제는 "라이브러리"에는 실제로 구현, 응용 프로그램 인터페이스 및 OS 인터페이스의 세 부분이 있다는 것입니다. 원칙적으로 처음 두 개는 OS에 관한 한 (보편 위치에 따라 다름) "범용"으로 만들 수 있지만 세 번째 부분 인 OS에 대한 인터페이스는 일반적으로 할 수 없습니다. OS에 대한 인터페이스는 OS, 제공하는 API, 패키징 메커니즘 (예 : Windows DLL에서 사용하는 파일 형식) 등에 따라 달라집니다.

"라이브러리"는 일반적으로 단일 패키지로 제공되므로 프로그램에서 사용할 "라이브러리"를 선택하면 특정 OS에 커밋됩니다. 이것은 두 가지 방법 중 하나입니다. a) 프로그래머가 사전에 완전히 선택한 다음 라이브러리와 응용 프로그램 간의 바인딩은 보편적 일 수 있지만 라이브러리 자체는 OS에 바인딩됩니다. 또는 b) 프로그래머는 프로그램을 실행할 때 라이브러리가 선택되도록 프로그램을 설정하지만 프로그램과 라이브러리 사이의 바인딩 메커니즘 자체는 OS에 따라 다릅니다 (예 : Windows의 DLL 메커니즘). 각각의 장단점이 있지만 사전에 선택을해야합니다.

이제 이것이 불가능하다는 의미는 아니지만 매우 영리해야합니다. 문제를 극복하려면 런타임에 라이브러리를 선택하는 경로를 따라야하며 OS에 의존하지 않는 범용 바인딩 메커니즘을 사용해야합니다. 따라서이를 유지 관리해야합니다. 더 많은 작업). 때때로 가치가 있습니다.

그럴 필요는 없지만, 그렇게하려는 노력을 기울이면 특정 프로세서에 묶고 싶지 않을 가능성이 높으므로 가상 머신을 작성하고 컴파일하게됩니다. 프로그램을 프로세서 중립 코드 형식으로

지금 당신은 내가 어디로 가고 있는지 알았을 것입니다. Java와 같은 언어 플랫폼은 정확히 그렇게합니다. Java 런타임 (라이브러리)은 Java 프로그램과 라이브러리 (Java 런타임이 프로그램을 열고 실행하는 방법) 간의 OS 중립 바인딩을 정의하고 현재 OS에 특정한 구현을 제공합니다. .NET은 Microsoft가 Windows 이외의 다른 것에 대해서는 "라이브러리"(런타임)를 제공하지 않는다는 점을 제외하고는 어느 정도 동일한 작업을 수행합니다. 실제로 Flash는 브라우저 범위가 더 제한적이지만 동일한 작업을 수행합니다.

마지막으로, 사용자 정의 바인딩 메커니즘없이 동일한 작업을 수행 할 수있는 방법이 있습니다. 일반적인 도구를 사용할 수는 있지만 사용자가 OS를 선택할 때까지 라이브러리에 대한 바인딩 단계를 연기하십시오. 그것이 소스 코드를 배포 할 때 일어나는 일입니다. 사용자는 프로그램을 가져 와서 실행할 준비가되면 프로세서 (컴파일)와 OS (링크)에 바인딩합니다.

그것은 모두 레이어를 어떻게 슬라이스하는지에 달려 있습니다. 하루가 끝나면 항상 특정 기계 코드를 실행하는 특정 하드웨어로 만든 컴퓨팅 장치가 있습니다. 레이어는 주로 개념적 프레임 워크로 존재합니다.


3

소프트웨어가 항상 OS에 특정한 것은 아닙니다. 모두 자바 및 이전 P-코드 시스템 (심지어 ScummVM에서) 운영 시스템에서 휴대용 소프트웨어를 할 수 있습니다. Infocom ( ZorkZ-machine 제작자 )도 다른 가상 머신을 기반으로 하는 관계형 데이터베이스 를 보유했습니다. 그러나 어떤 수준에서는 이러한 추상화조차도 컴퓨터에서 실행되도록 실제 명령으로 변환해야합니다.


3
Java는 가상 시스템에서 실행되지만 OS 간은 아닙니다. 각 OS마다 다른 JVM 바이너리를 사용해야합니다
Izkata

3
@Izkata True이지만 소프트웨어를 다시 컴파일하지는 않습니다 (JVM 만). 또한, 나의 마지막 문장을보십시오. 그러나 썬은 바이트 코드를 직접 실행할 수있는 마이크로 프로세서를 가지고 있다고 지적 할 것이다.
Elliott Frisch

3
Java는 일반적으로 하나는 아니지만 OS는 OS입니다. Java 소프트웨어는 Java OS에만 해당되며 대부분의 "실제"OS에 대한 Java OS 에뮬레이터가 있습니다. 그러나 WINE을 사용하여 Linux에서 Windows 소프트웨어를 실행하는 것처럼 모든 호스트 및 대상 OS에서 동일한 작업을 수행 할 수 있습니다.
user253751

@immibis 더 구체적입니다. Java Foundation Classes (JFC, Java 표준 라이브러리)는 프레임 워크입니다. Java 자체는 언어입니다. JVM은 OS와 유사합니다. 이름에 "Virtual Machine"이 있으며 실행중인 코드의 관점에서 OS와 유사한 기능을 수행합니다.

1

당신은 말합니다

특정 운영 체제 용 프로그래밍 언어를 사용하여 제작 된 소프트웨어는 해당 운영 체제에서만 작동합니다

그러나 예제로 제공하는 프로그램은 많은 운영 체제 및 일부 베어 메탈 환경에서 작동합니다.

여기서 중요한 것은 소스 코드와 컴파일 된 바이너리의 차이점입니다. C 프로그래밍 언어는 특별히 소스 형태로 OS에 독립적으로 설계되었습니다. "인쇄 콘솔로 인쇄"와 같은 것들에 대한 해석을 구현 자에게 맡기면됩니다. 그러나 C는 OS에 특정한 것에 따를 수 있습니다 (이유는 다른 답변 참조). 예를 들어 PE 또는 ELF 실행 파일 형식입니다.


6
OP가 소스 코드가 아닌 바이너리에 대해 묻는 것은 분명합니다.
Caleb

0

다른 사람들은 기술적 세부 사항을 잘 다루었습니다. 기술적 인 이유가 적은 UX / UI 측면에 대해 언급하고 싶습니다.

한 번만 쓰고 어딘가 어색해

모든 운영 체제에는 자체 사용자 인터페이스 API 및 디자인 표준이 있습니다. 프로그램에 대해 하나의 사용자 인터페이스를 작성하고 여러 운영 체제에서 실행할 수는 있지만 프로그램을 사용하면 어느 곳에서나 프로그램이 제대로 작동하지 않을 수 있습니다. 좋은 사용자 인터페이스를 만들려면 지원되는 각 플랫폼에 대한 세부 정보를 조정해야합니다.

이것들 중 많은 것들이 약간의 세부 사항이지만 잘못 이해하면 사용자를 실망시킬 것입니다.

  • Windows와 OSX에서 대화 상자의 버튼 순서가 다른지 확인하십시오. 이것을 잘못하면 사용자는 근육 기억으로 잘못된 버튼을 클릭합니다. Windows는 "Ok", "Cancel"순서로 있습니다. OSX의 순서가 바뀌었고 do-it 버튼의 텍스트는 수행 할 조치에 대한 간단한 설명입니다 : "취소", "휴지통으로 이동".
  • "뒤로"동작은 iOS 및 Android에서 다릅니다. iOS 애플리케이션은 필요에 따라 일반적으로 왼쪽 상단에 자신의 뒤로 버튼을 그립니다. Android에는 화면 회전에 따라 왼쪽 아래 또는 오른쪽 아래에 전용 버튼이 있습니다. OS 뒤로 버튼이 무시되면 Android 로의 빠른 포트가 올바르게 작동하지 않습니다.
  • 모멘텀 스크롤은 iOS, OSX 및 Android마다 다릅니다. 안타깝게도 네이티브 UI 코드를 작성하지 않는 경우 고유 한 스크롤 동작을 작성해야합니다.

기술적으로 모든 곳에서 실행되는 하나의 UI 코드베이스를 작성할 수있는 경우에도 지원되는 각 운영 체제에 맞게 조정하는 것이 가장 좋습니다.


-2

이 시점에서 중요한 차이점은 컴파일러를 링커에서 분리하는 것입니다. 컴파일러는 거의 동일한 출력을 생성 할 가능성이 높습니다 (차이는 주로 여러 가지로 인한 #if WINDOWS것임). 반면 링커 는 라이브러리 연결, 실행 파일 작성 등 모든 플랫폼 관련 항목 을 처리 해야 합니다.

다시 말해, 컴파일러는 실제 실행 가능한 코드를 생성하고 CPU의 명령어와 리소스를 사용해야하기 때문에 CPU 아키텍처에 주로 관심을 갖습니다 (.NET의 IL 또는 JVM의 바이트 코드는 가상 CPU의 명령어 세트로 간주됨에 유의하십시오) 이보기에서). 예를 들어 x86ARM에 대해 코드를 별도로 컴파일해야하는 이유가 여기에 있습니다 .

반면, 링커는이 모든 원시 데이터와 명령어를 가져 와서 로더 (현재는 거의 항상 OS 임)가 이해할 수있는 형식으로, 정적으로 링크 된 라이브러리를 링크해야합니다. (동적 연결, 메모리 할당 등에 필요한 코드도 포함).

다시 말해, 코드를 한 번만 컴파일하여 Linux와 Windows에서 실행할 수 있지만 두 번 링크 하여 두 개의 다른 실행 파일을 생성 해야합니다 . 이제 실제로 코드에서 허용량을 만들어야하는 경우가 많으므로 (사전 컴파일러 지시문이 나오는 위치) 한 번의 링크 컴파일 두 번도 많이 사용되지 않습니다. 사람들이 컴파일 과정에서 컴파일과 링크를 단일 단계로 처리하고 있다는 사실은 말할 것도 없습니다 (더 이상 컴파일러 자체에 관심이없는 것처럼).

DOS 시대의 소프트웨어는 종종 이진 이식성이 높았지만, DOS 나 Unix가 아니라 대부분의 IBM 스타일 PC에 공통적 인 특정 계약에 대해서도 컴파일되었다는 사실을 이해해야합니다. 소프트웨어 인터럽트. 필요한 레지스터 만 설정하고 int 13h그래픽 함수 등을 호출 하기 만하면 CPU가 인터럽트 테이블에 선언 된 메모리 포인터로 점프하기 때문에 정적 링크가 필요하지 않습니다 . 물론, 페달 대 금속 성능을 얻으려면 이러한 모든 방법을 직접 작성해야했지만 기본적으로 OS를 돌아 다니는 것이 전부였습니다. 물론 OS API와의 상호 작용이 필요한 무언가가 있습니다-프로그램 종료. 그러나 여전히 가장 간단한 형식을 사용했다면 (예 :COM헤더가없고 지침 만있는 DOS에서는 종료하지 않으려는 경우가 있습니다. 행운입니다! 물론 런타임에서도 적절한 종료를 처리 할 수 ​​있으므로 동일한 실행 파일에 Unix 종료 및 DOS 종료 코드를 둘 수 있으며 런타임에 사용할 코드를 감지 할 수 있습니다 :)


이 단지에서 설명 점을 반복하는 것 어제 게시 된 사전 답변
모기를
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.