모노는 어떻습니까?


149

나는 C #을 배우고 있으므로라는 작은 C # 프로그램을 만든 Hello, World!다음 컴파일 mono-csc하고 실행했습니다 mono.

$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!

나는 명중 할 때 눈치 TABbash, Hello.exe실행 표시되었다. 실제로 파일 이름을로드하는 쉘만으로 실행됩니다!

Hello.exe파일 확장자가 재미있는 ELF 파일 이 아닙니다 .

$ readelf -a Hello.exe
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
$ xxd Hello.exe | head -n1
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............

MZ이는 Microsoft Windows 정적으로 링크 된 실행 파일임을 의미합니다. Windows 상자에 놓으면 실행해야합니다.

내가 한 wine설치하지만, wine윈도우 응용 프로그램에 대한 호환성 계층되고, 약 5 배 오래 실행하는 데 걸리는 Hello.exemono하고 직접 않습니다 실행, 그래서 그것은 아니에요 wine그게 실행합니다.

나는 syscall / s 를 가로 채 거나로 시작하는 바이너리를 잡는 mono커널 모듈이 설치되어 있다고 가정 하고 있지만 친구는 오류를 반환합니다.monoexec4D 5Alsmod | grep mono

여기서 무슨 일이 일어나고 있으며 커널은 실행 파일이 특별 하다는 것을 어떻게 알 수 있습니까?


그냥 증거 것이 아니라 쉘 작업 마술, 내가 사용하는 쉘은 쓰레기를 (일명 sh)을 실행하고 여전히 기본적으로 실행됩니다.


해설자가 호기심을 보였기 때문에 프로그램 전체가 다음과 같습니다.

using System;

class Hello {
  /// <summary>
  ///   The main entry point for the application
  /// </summary>
  [STAThread]
  public static void Main(string[] args) {
    System.Console.Write("Hello, World!\n");
  }
}

4
당신은 대답을 얻었다, 그러나 당신이 좋아하는 명령을 실행하면 나는 조금 혼란 스러워요 동안 php hello.php이나 python hello.py또는 perl hello.pl자바와 같은 컴파일 언어의 경우에는 또는 java hello그들도 실행 가능하지만 읽기 프로그램들이 없습니다로 실행 파일을 실행할 것입니다. 당신이 실행 그러나 경우 ./hello.exe대신 mono hello.exe.는 I는 경우에 확실히 binfmt 지원을 사용하여보다 합리적인 질문과 허용 대답을 (발견
kuldeep.kamboj

@ kuldeep.kamboj 나는 당신이 무슨 말을하는지 잘 모르겠지만 Windows 실행 파일이 Linux 상자에서 "기본적으로"실행되는 것에 놀랐습니다.
고양이

1
실제로 내가 말하는 것은 모든 코드 파일 (또는 컴파일 된 파일)이 형식으로 프로그램을 통해 실행될 수 있다는 것 program codefile입니다. 귀하의 경우 프로그램은 모노이지만 내 예제에는 php, python, perl 및 java가 포함됩니다. 모노가 .exe 파일 이외의 확장명을 코드를 통해 여전히 실행할 수 있는지 의심합니다. 컴파일 된 코드를 실행하기 때문에 창에 전혀 의존해서는 안됩니다. 그러나 소스 파일에 Windows 전용 API와 같은 종속 코드가있는 경우 분명히 해당 exe 파일을 실행하려면 와인이 필요합니다.
kuldeep.kamboj

4
이것의 놀라운 아이러니의 일부는 /etc/magic또는 /usr/share/file/magic(또는 비슷한 마법의 위치)이 작업을 수행하는 데 필요한 정보가 들어있는 파일이라는 것입니다.

1
@cat은 매우 흥미로운 파일입니다 (좋아하는 파일을 원한다면 아마도 내 첫 번째 선택 일 것입니다). 모든 종류의 파일을 식별하기위한 정보가 있습니다. 그러나 파일 실행 방법을 파악하려면 먼저 파일이 무엇인지 식별해야합니다. 그것이 파일과 그 마술이하는 일입니다. 비슷한 일이 있습니다. Linux에 대한 Java 바이너리 커널 지원 은 모노에서 수행하는 것과 비슷하지만 $ foo.jar오히려 할 수 $ java -jar foo.jar있습니다.

답변:


183

이것은 binfmt_misc 의 작동 방식입니다. 알 수없는 바이너리를 실행하는 방법을 커널에 알려줍니다. /proc/sys/fs/binfmt_misc; 의 내용을보십시오 여기에 보이는 파일들 중에서 Mono 바이너리를 실행하는 방법을 설명해야합니다.

enabled
interpreter /usr/lib/binfmt-support/run-detectors
flags:
offset 0
magic 4d5a

(데비안 시스템에서). 이것은 MZ( 4d5a)로 시작하는 바이너리가 커널에 알려 줘야합니다 run-detectors. 후자는 Mono 또는 Wine을 사용하여 바이너리를 실행할지 여부를 알아냅니다.

이진 유형은 언제든지 추가, 제거, 활성화 및 비활성화 할 수 있습니다. 자세한 내용은 위의 문서를 참조하십시오 (시맨틱은 놀랍습니다. 여기에 사용 된 가상 파일 시스템은 표준 파일 시스템과 완전히 동작하지 않습니다). /proc/sys/fs/binfmt_misc/status전역 상태를 제공하고 각 바이너리 "설명자"는 개별 상태를 표시합니다. 비활성화하는 또 다른 방법은 binfmt_misc모듈로 빌드 된 경우 커널 모듈을 언로드하는 것입니다. 이것은 또한 완전히 피하기 위해 블랙리스트에 올릴 수 있음을 의미합니다.

이 기능을 사용하면 MZ 실행 파일 (Windows PE 및 PE + 바이너리뿐만 아니라 DOS 및 OS / 2 바이너리 포함), Java JAR 파일과 같은 새로운 바이너리 유형을 지원할 수 있습니다. 또한 알려진 바이너리 유형을 지원할 수 있습니다. 일반적으로 Qemu를 사용하는 새로운 아키텍처; 따라서 적절한 라이브러리를 사용하면 Intel 프로세서에서 ARM Linux 바이너리를 투명하게 실행할 수 있습니다!

귀하의 질문은 .NET 의미의 크로스 컴파일에서 비롯되었으며 다음과 같은주의 사항 binfmt_misc이 있습니다. 크로스 컴파일 된 바이너리를 실행할 수있는 시스템에서 크로스 컴파일을 시도하면 일부 구성 스크립트가 잘못 작동합니다. 일반적으로 크로스 컴파일을 감지하려면 바이너리를 빌드하고 실행해야합니다. 그것이 실행되면 크로스 컴파일하지 않고 그렇지 않으면 컴파일러가 고장난 것입니다. autoconf이 경우 스크립트는 일반적으로 빌드 및 호스트 아키텍처를 명시 적으로 지정하여 수정할 수 있지만 때로는 binfmt_misc일시적 으로 비활성화해야합니다 .


2
/ proc에 관심이있는 사람들에게는 / proc / *의 작동 방식에 관심이있을 수 있습니다 . 슈퍼 사용자 .
CVn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.