Mono huyền diệu như thế nào?


149

Tôi đang học C #, vì vậy tôi đã tạo một chương trình C # nhỏ nói rằng Hello, World!, sau đó biên dịch nó mono-cscvà chạy nó với mono:

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

Tôi nhận thấy rằng khi tôi nhấn TABvào bash, Hello.exeđã được đánh dấu thực thi. Thật vậy, nó chạy bằng một vỏ tải tên tệp!

Hello.exekhông một file ELF có phần mở rộng tập tin buồn cười:

$ 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..............

MZcó nghĩa là Microsoft Windows được thực thi liên kết tĩnh. Thả nó vào một hộp Windows và nó sẽ (nên) chạy.

Tôi đã winecài đặt, nhưng wine, là một lớp tương thích với các ứng dụng Windows, mất khoảng 5x thời gian để chạy Hello.exenhư monovà thực hiện nó trực tiếp làm, vì vậy nó không winechạy nó.

Tôi giả sử có một số monomô-đun hạt nhân được cài đặt với chức mononăng chặn các tòa nhà exec/ s hoặc bắt các nhị phân bắt đầu bằng 4D 5A, nhưng lsmod | grep monobạn bè trả lại lỗi.

Chuyện gì đang xảy ra ở đây, và làm thế nào để nhân biết rằng này thực thi là đặc biệt?


Để chứng minh đó không phải phép thuật hoạt động của vỏ của tôi , tôi đã sử dụng Crap Shell (hay còn gọi là sh) để chạy nó và nó vẫn chạy tự nhiên.


Đây là chương trình đầy đủ, vì một người bình luận tò mò:

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
Trong khi bạn có câu trả lời, Nhưng tôi chút bối rối, Nếu bạn chạy các lệnh như php hello.phphoặc python hello.pyhoặc perl hello.plhoặc trong trường hợp ngôn ngữ biên dịch như java java hellohọ cũng sẽ chạy như họ không thực thi có nhưng một chương trình đọc và thực thi tập tin. Tuy nhiên, nếu bạn chạy ./hello.exethay vì mono hello.exetôi thấy câu hỏi của bạn và chấp nhận câu trả lời hợp lý hơn (trong trường hợp chắc chắn sử dụng binfmt-support.
kuldeep.kamboj

@ kuldeep.kamboj Tôi không chắc là tôi hiểu bạn đang nói gì nhưng tôi chỉ ngạc nhiên khi một tệp thực thi Windows chạy "nguyên bản" trên hộp Linux.
con mèo

1
Trên thực tế những gì tôi đã nói rằng bất kỳ tệp mã (hoặc tệp được biên dịch) có thể được thực thi thông qua chương trình của nó ở định dạng program codefile, trong trường hợp chương trình của bạn là đơn sắc, trong khi các ví dụ của tôi bao gồm php, python, perl và java. Tôi nghi ngờ nếu mono cho phép mở rộng ra ngoài tệp .exe vẫn được thực thi thông qua mã. Nó không nên phụ thuộc vào tất cả trên các cửa sổ vì cuối cùng điều này được thực thi một mã được biên dịch. Tuy nhiên, nếu tệp nguồn của bạn có một số mã phụ thuộc như API chỉ có windows thì rõ ràng bạn phải cần rượu để chạy tệp exe đó.
kuldeep.kamboj

4
Một phần của sự trớ trêu tuyệt vời của điều này là /etc/magichoặc /usr/share/file/magic(hoặc vị trí ma thuật tương tự) là tệp chứa thông tin cần thiết để có thể làm điều này.

1
@cat đó là một tệp rất thú vị (nếu tôi có một tệp yêu thích, nó có thể là lựa chọn đầu tiên của tôi). Nó có thông tin để xác định tất cả các loại tập tin. Nhưng bạn cần xác định tập tin là gì trước khi bạn có thể tìm ra cách chạy nó. Đó là những gì tập tin và ma thuật của nó làm. Một điều tương tự - Hỗ trợ hạt nhân nhị phân Java cho Linux một thời gian ngắn để bạn có thể làm $ foo.jarthay vì $ java -jar foo.jar- tương tự như những gì được thực hiện cho đơn âm.

Câu trả lời:


183

Đây là binfmt_misc đang hoạt động: nó cho phép hạt nhân được cho biết cách chạy nhị phân mà nó không biết. Nhìn vào nội dung của /proc/sys/fs/binfmt_misc; Trong số các tệp bạn thấy ở đó, người ta sẽ giải thích cách chạy nhị phân Mono:

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

(trên hệ thống Debian). Điều này nói với kernel rằng các nhị phân bắt đầu bằng MZ( 4d5a) nên được cung cấp cho run-detectors. Cái sau chỉ ra liệu nên sử dụng Mono hay Wine để chạy nhị phân.

Các loại nhị phân có thể được thêm, xóa, bật và tắt bất cứ lúc nào; xem tài liệu ở trên để biết chi tiết (ngữ nghĩa là đáng ngạc nhiên, hệ thống tệp ảo được sử dụng ở đây không hoạt động hoàn toàn giống như một hệ thống tệp tiêu chuẩn). /proc/sys/fs/binfmt_misc/statusđưa ra trạng thái toàn cầu và mỗi "mô tả" nhị phân hiển thị trạng thái riêng của nó. Một cách khác để vô hiệu hóa binfmt_misclà dỡ bỏ mô-đun hạt nhân của nó, nếu nó được xây dựng như một mô-đun; điều này cũng có nghĩa là có thể liệt kê nó để tránh nó hoàn toàn.

Tính năng này cho phép các loại nhị phân mới được hỗ trợ, chẳng hạn như các tệp thực thi MZ (bao gồm các nhị phân Windows PE và PE +, nhưng cũng có các tệp nhị phân DOS và OS / 2!), Các tệp JAR của Java ... Nó cũng cho phép các loại nhị phân đã biết được hỗ trợ trên kiến trúc mới, thường sử dụng Qemu; do đó, với các thư viện thích hợp, bạn có thể chạy nhị phân ARM Linux trên bộ xử lý Intel!

Câu hỏi của bạn xuất phát từ việc biên dịch chéo, mặc dù theo nghĩa .NET và điều đó dẫn đến một cảnh báo với binfmt_misc: một số tập lệnh cấu hình hoạt động sai khi bạn cố gắng biên dịch chéo trên một hệ thống có thể chạy các nhị phân được biên dịch chéo. Thông thường, phát hiện biên dịch chéo bao gồm xây dựng nhị phân và cố gắng chạy nó; nếu nó chạy, bạn không biên dịch chéo, nếu không, bạn (hoặc trình biên dịch của bạn bị hỏng). autoconftập lệnh thường có thể được sửa trong trường hợp này bằng cách chỉ định rõ ràng kiến ​​trúc xây dựng và máy chủ lưu trữ, nhưng đôi khi bạn sẽ phải tắt binfmt_misctạm thời ...


2
Đối với những người tò mò về / Proc, bạn có thể quan tâm đến việc / Proc / * hoạt động như thế nào? trên Siêu người dùng .
một CVn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.