2009-10-21 6 views
16

프로그램이 일부 언어에서 ASM -> 기계 코드 (직접 실행 가능)로 컴파일됩니다. 사람들이 이것이 플랫폼에 의존한다고 말하면, 형성되는 바이너리가 x86, x86-64와 같은 명령어 세트 아키텍처를 사용하는 CPU에서만 (정확하게) 실행된다는 것을 의미합니다. 그것은 ISA의 차이로 인해 (잘못)/다른 프로세스에서 (전혀) 실행되지 않을 수도 있습니다. 권리?프로그램은 어떻게 실행됩니까? 운영 체제는 어디에서 작동합니까?

이제는 바이너리 개념이 혼란 스럽습니다. 모든 것은 "기계 언어 코드"& "CPU"에 관한 것입니다. OS는 어디에서 작동합니까? 메모리에로드 될 때 컴파일 된 바이너리가 CPU에 대한 직접 명령어를 가지고 있음을 의미합니다. & CPU는 한 번에 하나의 명령을 실행합니다. 프로세스 관리를 제외하고 어디에서나 운영 체제 역할을 볼 수 없었습니다 link text. 운영 체제와 상관없이 동일한 ISA의 CPU에서 실행되어야합니다. 권리?

아직까지는 그렇지 않습니다. Windows 컴퓨터에서 x86에 코드를 빌드하면 어떻게됩니까? Mac x86 시스템이나 Linux x86 시스템에서는 실행되지 않습니다.

여기에 뭔가가 빠졌습니다. 제 혼란을 치우십시오.

답변

13

최신 CPU에는 운영 체제 자체의 코어 ("커널 모드")와 실행중인 프로그램의 모드 ("사용자 모드")의 두 가지 모드가 있습니다.). 사용자 모드에서 CPU는 많은 일을 할 수 없습니다.

예를 들어 마우스 클릭은 일반적으로 사용자 모드가 아닌 커널에서 발견됩니다. 그러나 OS는 이벤트를 사용자 모드로 디스패치하고 거기에서 올바른 프로그램으로 디스패치합니다. 다른 방법으로는 협력이 필요합니다. 프로그램이 화면을 자유롭게 그릴 수는 없지만 OS 및 커널 모드를 통해 그 부분을 그리는 것이 필요합니다.

마찬가지로 프로그램을 시작하는 행위는 일반적으로 협력입니다. OS의 셸 부분도 사용자 모드 프로그램입니다. 마우스 클릭을 가져 와서 프로세스 시작을위한 마우스 클릭이라고 판단합니다. 그런 다음 쉘은 운영 체제의 커널 모드 부분에 해당 프로그램에 대한 새 프로세스를 시작하라고 지시합니다.

커널 모드에서 새 프로세스를 시작해야 할 때 먼저 부기 용 메모리를 할당 한 다음 프로그램을로드합니다. 이것은 바이너리에서 명령을 검색하는 것뿐만 아니라 프로그램을 OS에 연결하는 것과 관련이 있습니다. 이것은 일반적으로 바이너리의 진입 점 (고전적으로 int main(int argc, char** argv))과 프로그램이 OS를 호출하고자하는 모든 점을 찾아야합니다.

서로 다른 운영 체제는 프로그램을 OS와 연결하는 다른 방법을 사용합니다. 결과적으로 로딩 프로세스가 다르며 바이너리 파일 형식도 다를 수 있습니다. 그것은 절대적인 것이 아닙니다. 바이너리 용 ELF 형식은 여러 운영 체제에 사용되며 Microsoft는 모든 현재 운영 체제에서 PE 형식을 사용합니다. 두 경우 모두 형식은 바이너리의 정확한 형식을 설명하므로 OS가 프로그램을 OS에 연결할 수 있는지 여부를 결정할 수 있습니다. 예를 들어 Win32 바이너리의 경우 PE 형식이므로 리눅스는 윈도우 7-64와 마찬가지로 Windows 2000을로드하지 않습니다. 반면에 Win64 바이너리는 PE 형식이기도하지만 Windows 2000에서는이를 거부합니다.

+0

Re "* 그러므로 Linux는 *를로드하지 않습니다."그러나 Linux 소프트웨어가 그 기능을 실행할 수 없도록 막는 것은 무엇입니까? – Pacerier

+0

실제로 Mac에서 PE 러너 구현을 중단하면 모든 Windows 애플리케이션을 Mac에서 즉시 실행할 수 있습니다. – Pacerier

+0

@ 수락어 : 대부분 돈. 즉, Microsoft는 ELF 하위 시스템 (Linux 용 Windows 서브 시스템)을 구현했습니다. – MSalters

0

OS는 특정 기능과 하드웨어에 액세스하기위한 도구와 API를 제공합니다.

예를 들어 Microsoft Windows에서 창을 만들려면 창을 만들려면 OS의 DLL이 있어야합니다.

API를 직접 작성하지 않으려면 OS에서 제공하는 API를 사용하십시오. 그것이 OS가 작동하는 곳입니다.

+1

높은 수준에서 이것은 정확합니다. 그러나 운영 체제가 하드웨어 나 페이지 테이블에 직접 액세스하지 못하게하므로 "직접 API를 작성할 수 없습니다. 그래서 어떤 수준에서는 여전히 OS 관련 시스템 호출을해야합니다. –

7

두 가지 방법 :

가장 먼저 대답은 "시스템 호출"입니다. I/O를 수행하고, 장치와 상호 작용하고, 메모리를 할당하고, 프로세스를 포크하는 등의 기능을 호출 할 때마다 해당 함수는 "시스템 호출"을 수행해야합니다. syscall 명령 자체가 인 반면 X86에는 사용할 수있는 시스템 호출과 매개 변수가 OS에 따라 다릅니다.

프로그램이 어떤 시스템 호출도하지 않더라도 (확실하지는 않지만 확실하지는 않지만) 기계 코드를 감싸는 형식은 OS마다 다릅니다. 따라서 exe (PE)와 Linux 실행 파일 (ELF)의 파일 형식이 다르므로 exe 파일이 Linux에서 실행되지 않습니다.

편집 : 이것들은 상세 수준입니다. 더 높은 수준의 대답은 파일, 콘솔/GUI, 메모리 할당 등에 액세스해야하는 모든 것이 OS 특정 적이라고 말합니다.

+2

그래서, 1. HLL에서 ML로 컴파일 할 때 컴파일러는 fopen() 또는 acess 프린터 기능을 OS마다 다른 "시스템 호출"이라고합니다. 권리? 2. HLL을 'CPU ISA'및 'OS 시스템 호출'특정 ML 코드로 컴파일 할뿐만 아니라 OS에 따라이 파일 형식의 PE/ELF 변환 작업을 수행합니다. 권리? – claws

+2

아니요, 여전히 fopen()을 호출합니다. fopen의 어딘가에 "시스템 호출"명령이 있습니다. syscall 명령은 프로세서를 "커널 모드"로 변경하여 모든 종류의 보호 기능을 제거하고 시스템이 실제로 하드웨어에 액세스 할 수 있도록합니다. 프로그램이 보호 모드에서 실행되며 하드웨어에 전혀 액세스 할 수 없습니다. –

+1

> syscall 명령어 자체는 X86의 일부이지만 사용 가능한 시스템 호출과 매개 변수는 OS에 따라 다릅니다. 어디에서 찾을 수 있습니까? 난 그냥 같은 기능에 대해 다른 OS의 다른 시스템 호출을 한눈에 "파일 열기"라고 말하고 싶습니다. 인터넷 검색 중이지만 정확히 찾고있는 것을 찾을 수 없습니다. – claws

3

OS는 "서비스"에 액세스하려고 할 때 작동합니다. 예를 들어 하드웨어 수준에서 사용자가 대신 사용할 수 있습니다. 파일 시스템이라고 불리는 "데이터베이스"안에있는 파일을 열고 난수를 생성하십시오 (모든 현대적인 OS에는이 기능이 있습니다).

예를 들어, GNU/Linux에서 "서비스"(실제로 "시스템 호출"이라고 함)에 액세스하려면 레지스터를 채우고 int 80h를 호출해야합니다.

실행 파일에 다른 파일 형식이 있기 때문에 프로그램이 다른 OS에서 실행되지 않습니다. 예를 들어 Win에는 COFF/PE가 있고 Linux에는 ELF 파일 형식이 있으며 (다른 파일 형식과 마찬가지로 "메타 데이터 ", 예 : HTML (또는 SGML) 파일 형식).

+3

NB : "서비스"는 커널 모드에서 사용할 수있는 일종의 저수준 함수이며 "Windows 서비스"(* nix OS의 데몬)와 혼동하지 마십시오. –

1

OS는 (a) 기계 코드가 실행되는 환경과 (b) 표준 서비스를 제공합니다.(a)가 없으면 코드가 처음부터 실행되지 않으며 (b)가 없으면 절대적으로 모든 것을 직접 구현하고 하드웨어를 직접 공격해야합니다.

+0

하드웨어에 직접 코딩하지 않으시겠습니까?** 그렇다면 그것은 OS 전반에서 작동 할 것입니까? ** – Pacerier

9

01010110011은 x86에서 뭔가를 의미하고 ARM에서는 다른 것을 의미하므로 다른 프로세서에서는 실행되지 않습니다. x86-64는 이전 버전의 x86과 호환되므로 x86 프로그램을 실행할 수 있습니다.

진은 OS가 (윈도우 = PE, MAC/리눅스 = ELF) 임의의 통상의 바이너리

메모리로하여 OS로드를 이해하고 소정의 값으로 필드들을 채우는 특정 형식이고 . 이러한 "특정 값"은 ​​kernel32 또는 libc와 같은 공유 라이브러리 (dll, so)에있는 API 함수의 주소입니다. 바이너리 자체가 하드 드라이브, 네트워크 카드, 게임 패드 등에 액세스하는 방법을 모르기 때문에 API 주소가 필요합니다. 프로그램은이 주소를 사용하여 OS 또는 다른 라이브러리에있는 특정 기능을 호출합니다.

본질적으로 바이너리에는 모든 것이 작동하도록 OS에서 채워야하는 중요한 부분이 없습니다. OS가 잘못된 부분을 채우면 서로 통신 할 수 없으므로 바이너리가 작동하지 않습니다. 그것은 user32.dll을 다른 파일로 대체하거나 mac osx에서 linux 실행 파일을 실행하려고 할 때 일어납니다.

그래서 libc는 파일을 여는 방법을 어떻게 알고 있습니까?

libc는 OS 코어 기능에 대한 하위 레벨 액세스 인 syscalls를 사용합니다.특정 CPU 레지스터를 채운 다음 인터럽트 (특수 CPU 명령어)를 트리거하여 수행하는 것을 제외하고는 함수 호출과 비슷합니다.

그렇다면 OS가 파일을 여는 방법을 어떻게 알 수 있습니까?

그건 OS가하는 일 중 하나입니다. 그러나 하드 드라이브와 대화하는 방법을 어떻게 알 수 있습니까? 정확히 어떻게 작동하는지 모르지만 OS가 BIOS 기능에 매핑되는 특정 메모리 위치를 쓰거나 읽음으로써이를 수행한다고 상상합니다.

그래서 BIOS가 하드 드라이브와 통신하는 방법을 알고 있습니까?

나도 몰라, 나는 그 수준에서 프로그래밍을 한 적이 없다. BIOS가 하드 드라이브 커넥터에 하드 연결되어 있고 하드 드라이브와 "SATA"를 말하기 위해 1과 0의 올바른 순서를 보낼 수 있다고 상상합니다. 아마도 "이 섹터 읽기"와 같은 간단한 것들만 말할 수 있습니다

섹터를 읽는 방법을 하드 드라이브가 어떻게 알 수 있습니까?

나는 정말로 이것을 모르고 있기 때문에 일부 하드웨어 사용자를 계속 허용 할 것입니다.

+1

위대한 게시물, 고마워. 하나의 사소한 메모 : 나는 OS X가 ELF 대신에 MACH-O를 사용한다고 생각한다. http://en.wikipedia.org/wiki/Mach-O 그 주제에 익숙하지 않기 때문에 그것에 대해 확신하지 못한다. – Stephen

+0

@martin, Re "* user32.dll을 다른 파일로 바꿀 수 있다면 *",하지만 질문은 왜 프로그램 내에 "user32.dll"임베디드 ** 기능을 가지고 있다면 프로그램이 작동하지 않을 것입니다 ? – Pacerier

+0

@Pacerier'user32.dll'은 차례대로 다른 DLL에 의존하므로 프로그램에 모두 포함시켜야합니다. 그렇게하면 "정적으로 링크 된"실행 파일을 얻을 수 있습니다.이 실행 파일은 Windows의 로더에 의해 거부 될 것입니다. 리눅스에서 정적으로 링크 된 실행 파일을 실행할 수는 있지만, 커널 모드로의 함수 호출 인 x86 용'syscall' 명령을 통해 유용한 일을하는 시스템 호출이 필연적으로 포함됩니다. 커널 API는 실행 파일이 올바르게 동작 할 수 있도록 예상대로 동작해야합니다 (즉, Linux 커널 인터페이스를 구현해야합니다). – Martin

0

또한 에 OS가 프로그램 시작을 처리하는을 추가하려고합니다. 프로세스 공간을 준비하고 초기화하여 프로그램을 시작하고 프로그램 지침을로드하고 프로그램을 제어 할 수 있도록합니다.

1

고급 언어로 생성 된 기계 명령어는 시스템 호출을 포함하여 사용자가 호출 한 라이브러리를 제공하는 라이브러리의 호출 규칙에 적합합니다. 일반적으로 어딘가에 사용자 공간 라이브러리에 래핑 되더라도, 시스템 호출을 할 필요가 없을 수도 있습니다).

또한 몇 가지 예외가 있습니다 (예 : 포인터 크기, 기본 유형, 구조체 레이아웃, C++의 클래스 구현 등에 대한 가정에주의해야 함).

파일 형식은 운영 체제가 코드를 프로세스로 실행하고 프로세스를 필요한 상태로 부트 스트랩 할 수 있도록 필요한 후크/공개적으로 표시되는 기능 및 데이터를 지정합니다. Windows에서의 C/C++ 개발에 익숙하다면, 하위 시스템의 개념은 부트 스트랩 레벨, 제공된 자원 및 진입 점 서명 (보통 대부분의 시스템에서는 main(int, char **))을 지시합니다.

어셈블리 언어에 대한 코드해야합니다

높은 수준의 언어, 명령어 세트 아키텍처 및 실행 파일 형식의 선택이 주어진 시스템에서 바이너리를 실행할 수있는 능력에 영향을 줄 수있는 방법에 대한 몇 가지 좋은 사례가있다 특정 ISA. 이들은 CPU 유형의 제품군에 특정한 지침을 사용합니다. 이 지침은 해당 CPU가 해당 명령어 세트를 지원하는 경우 다른 제품군의 CPU 인 에서 작동합니다. 예를 들어 x86 코드는 amd64 운영 체제에서 어느 정도 작동하며 x86 운영 체제를 실행하는 amd64 CPU에서 확실히 작동합니다.

c는 ISA의 세부 사항을 대부분 추상화합니다. 몇 가지 명백한 예외에는 포인터 크기와 엔디안이 있습니다. 다양한 잘 알려진 인터페이스가 libc를 통해 예상 수준으로 제공됩니다 (예 : printf, main, fopen 및 기타). 여기에는 이러한 호출을하기 위해 예상되는 레지스터 및 스택 상태가 포함되므로 C 코드가 다른 운영 체제 및 아키텍처에서 변경없이 작동 할 수 있습니다.다른 인터페이스도 직접 제공되거나 C 코드의 이식성을 높이기 위해 플랫폼 별 인터페이스를 예상 인터페이스에 래핑하여 제공 할 수 있습니다.

파이썬 및 다른 유사한 "가상화 된"언어는 또 다른 추상화 수준에서 작동하며 몇 가지 예외가 있습니다. 예를 들어 특정 플랫폼이나 문자 인코딩 차이에 대한 기능은 수정하지 않고 실행할 수 있습니다. 수많은 시스템. 이는 성능 및 실행 파일 크기를 희생시키면서 다양한 ISA 및 운영 체제 조합에 대해 통일 된 인터페이스를 제공함으로써 달성됩니다.

0

유추 :

다른 나라에서 집사를 고용한다고 해봅시다. 그는 당신이 말하는 단어를 이해하지 못하기 때문에 별 트레킹과 같은 번역기를 사용할 수 있습니다. 이제 그는 자신의 고차원 언어를 이해할 수 있습니다. 왜냐하면 말을 할 때 그는 자신의 언어를 듣기 때문입니다.

이제는 그가 A에서 B로 걸어 가기를 원한다고 가정 해 봅시다. 다리 나 발에 직접 말하지 않고 직접 물어 보자. 그는 자신의 몸을 통제하고 있습니다. 1) 귀하의 요청을 적절히 전달하고 2) 취업 의무에 해당한다고 결정하면 그는 A에서 B로 이동할 것입니다.

이제 마지막으로 동일한 국가에서 새로운 하인이 나옵니다. 당신은 새로운 star-trek-translator를 사지 않을 것입니다.) 당신은 그가 A에서 B로 걸어 가기를 원합니다. 그러나이 종은 당신이 더 크게 말하고 묻는 동안 제발 말할 것을 요구합니다. 당신은 그가 더 유연하기 때문에 이것을 참았습니다. 당신이 원하면 C를 통해 A에서 B로 가도록 요청할 수 있습니다 - 이전의 집사가 그 일을 할 수 있었지만 발을 끌고 불평했습니다.

또 다른 행운의 비결은 번역기 설정을 조정하여 언어 처리가 가능하므로 아무 것도 변경되지 않는다는 것입니다. 그러나 새로운 설정으로 오래된 집사와 이야기한다면, 혼란스러워하고 자신의 언어를 사용한다고해도 이해하지 못합니다.

분명하지 않은 경우 butlers는 ISA가 같지만 운영 체제가 다른 컴퓨터입니다. 변환기는 ISA를 대상으로하는 교차 컴파일러 도구 체인입니다.

+0

"새 star-trek-translator를 사지 않기 때문에"번역자가 언급 했습니까? – Pacerier

+0

또한 다른 ISA를 사용할 때 일어나는 일과 함께이 비유를 확장하는 것이 좋습니다. – Pacerier

+0

@Pacerier 번역기는 ISA를 대상으로하는 크로스 컴파일러 도구 체인입니다. 요점은 번역자가 x86이나 다른 기계어를 생산하더라도 커널에 자체 인터페이스가 있기 때문에 명령어를 다르게 사용해야한다는 것입니다. 이것은 다른 라이브러리에 링크하고 사용하는 이진 형식을 사용하는 것을 의미합니다. 사용자 프로그램이 스스로 실행되지 않으면, 커널/버틀러에게 이야기해야합니다. – jiggunjer

관련 문제