โมโนเอกซ์เป็นยังไงบ้าง?


149

ฉันกำลังเรียนรู้ C # ดังนั้นฉันจึงทำโปรแกรม C # เล็ก ๆ ที่กล่าวHello, World!แล้วรวบรวมmono-cscและเรียกใช้ด้วยmono:

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

ผมสังเกตเห็นว่าเมื่อฉันตีTABในbash, Hello.exeถูกทำเครื่องหมายปฏิบัติการ อันที่จริงมันทำงานโดยเพียงแค่โหลดเปลือกชื่อไฟล์!

Hello.exeคือไม่ได้เป็นแฟ้มเอลฟ์ที่มีนามสกุลไฟล์ตลก:

$ 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เป็นชั้นเข้ากันได้สำหรับปพลิเคชันของ Windows จะใช้เวลาประมาณ 5 เท่าเป็นเวลานานเพื่อให้ทำงานHello.exeเป็นmonoและดำเนินการโดยตรงไม่ดังนั้นจึงไม่ได้wineว่ามันวิ่ง

ฉันสมมติว่ามีบางmonoเคอร์เนลโมดูลที่ติดตั้งกับmonoที่จุดตัดexecsyscall / s หรือจับไบนารีที่ขึ้นต้นด้วย4D 5Aแต่lsmod | grep monoเพื่อน ๆ กลับข้อผิดพลาด

เกิดอะไรขึ้นที่นี่และเคอร์เนลรู้ได้อย่างไรว่าไฟล์ปฏิบัติการนี้มีความพิเศษ?


เพื่อพิสูจน์ว่ามันไม่ใช่เวทย์มนตร์ของเปลือกหอยฉันใช้Crap Shell (aka 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 java helloพวกเขาก็จะเรียกใช้เนื่องจากไม่มีการปฏิบัติการ แต่โปรแกรมอ่านและเรียกใช้ไฟล์ อย่างไรก็ตามถ้าคุณเรียกใช้./hello.exeแทนmono hello.exeฉันพบคำถามของคุณและยอมรับคำตอบที่สมเหตุสมผลมากขึ้น (ซึ่งในกรณีที่ใช้ binfmt-support อย่างแน่นอน
kuldeep.kamboj

@ kuldeep.kamboj ฉันไม่แน่ใจว่าฉันเข้าใจสิ่งที่คุณกำลังพูด แต่ฉันก็แปลกใจที่ปฏิบัติการแบบ Windows รัน "กำเนิด" บนกล่อง Linux
แมว

1
จริงๆแล้วสิ่งที่ฉันบอกว่าไฟล์รหัสใด ๆ (หรือไฟล์ที่คอมไพล์) สามารถดำเนินการผ่านโปรแกรมในรูปแบบprogram codefileในกรณีที่โปรแกรมของคุณเป็นขาวดำในขณะที่ตัวอย่างของฉันมี php, python, perl และ java ฉันสงสัยว่า mono อนุญาตให้มีการขยายไปยังไฟล์อื่นที่ไม่ใช่. exe หรือยังถูกเรียกใช้งานผ่านโค้ด ไม่ควรขึ้นอยู่กับหน้าต่างเลยเพราะนี่คือรหัสที่คอมไพล์แล้ว อย่างไรก็ตามหากไฟล์ต้นฉบับของคุณมีโค้ดที่ขึ้นต่อกันเช่น API เฉพาะของ Windows คุณต้องมีไวน์สำหรับการเรียกใช้ไฟล์ exe นั้น
kuldeep.kamboj

4
ส่วนหนึ่งของการประชดที่ยอดเยี่ยมของเรื่องนี้ก็คือ /etc/magicหรือ/usr/share/file/magic(หรือตำแหน่งเวทมนตร์ที่คล้ายกัน) เป็นไฟล์ที่มีข้อมูลที่จำเป็นในการทำเช่นนี้

1
@cat มันเป็นไฟล์ที่น่าสนใจมาก (ถ้าฉันจะมีไฟล์โปรดมันน่าจะเป็นตัวเลือกแรกของฉัน) มีข้อมูลสำหรับระบุไฟล์ทุกประเภท แต่คุณต้องระบุว่าไฟล์ใดเป็นไฟล์แรกก่อนจึงจะสามารถทราบวิธีเรียกใช้ นั่นคือสิ่งที่ไฟล์และความมหัศจรรย์ของมันทำ สิ่งที่คล้ายกัน - การสนับสนุน Java Binary Kernel สำหรับ Linuxจากชั่วขณะหนึ่งคุณสามารถทำได้$ foo.jarมากกว่า$ java -jar foo.jar- คล้ายกับสิ่งที่ทำสำหรับโมโน

คำตอบ:


183

นี่คือการดำเนินการbinfmt_misc : อนุญาตให้เคอร์เนลได้รับการบอกวิธีเรียกใช้ไบนารีที่ไม่ทราบ ดูเนื้อหาของ/proc/sys/fs/binfmt_misc; ในบรรดาไฟล์ที่คุณเห็นคุณควรอธิบายวิธีการเรียกใช้ไบนารีไบนารี่:

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

(บนระบบ Debian) นี้จะบอกเคอร์เนลที่ไบนารีที่เริ่มต้นด้วยMZ( 4d5a) run-detectorsควรจะให้กับ ตัวเลขหลังว่าจะใช้โมโนหรือไวน์เพื่อรันไบนารี

ประเภทไบนารีสามารถเพิ่มลบเปิดใช้งานและปิดใช้งานได้ตลอดเวลา ดูรายละเอียดในเอกสารข้างต้น (ความหมายที่น่าแปลกใจระบบไฟล์เสมือนที่ใช้ที่นี่ไม่ทำงานเหมือนระบบไฟล์มาตรฐานทั้งหมด) /proc/sys/fs/binfmt_misc/statusให้สถานะทั่วโลกและ "บ่งชี้" ไบนารีแต่ละแสดงสถานะของตน อีกวิธีในการปิดการใช้งานbinfmt_miscคือการยกเลิกการโหลดโมดูลเคอร์เนลถ้ามันถูกสร้างเป็นโมดูล นี่ก็หมายความว่าเป็นไปได้ที่จะขึ้นบัญชีดำเพื่อหลีกเลี่ยงมันโดยสิ้นเชิง

คุณลักษณะนี้ช่วยให้รองรับประเภทไบนารีใหม่ได้เช่น MZ executables (ซึ่งรวมถึง Windows PE และ PE + ไบนารี แต่ยังรวมถึง DOS และ OS / 2 ไบนารี!), ไฟล์ Java JAR ... นอกจากนี้ยังอนุญาตให้รองรับประเภทไบนารีที่รู้จัก สถาปัตยกรรมใหม่มักใช้ Qemu; ดังนั้นด้วยห้องสมุดที่เหมาะสมคุณสามารถเรียกใช้ไบนารีลินุกซ์ ARM บนโปรเซสเซอร์ของ Intel!

คำถามของคุณเกิดจากการคอมไพล์ข้ามแม้ว่าในแง่ของ. NET และนั่นคือข้อแม้binfmt_misc: สคริปต์การกำหนดค่าบางอย่างทำงานผิดปกติเมื่อคุณพยายามที่จะคอมไพล์ข้ามระบบที่สามารถเรียกใช้ไบนารี่ที่รวบรวมข้าม โดยทั่วไปแล้วการตรวจจับข้ามการรวบรวมเกี่ยวข้องกับการสร้างไบนารีและพยายามเรียกใช้ ถ้ามันทำงานคุณจะไม่คอมไพล์ข้ามถ้ามันไม่ได้คุณจะ (หรือคอมไพเลอร์ของคุณเสีย) autoconfโดยปกติสคริปต์สามารถแก้ไขได้ในกรณีนี้โดยระบุการสร้างและโฮสต์สถาปัตยกรรมอย่างชัดเจน แต่บางครั้งคุณจะต้องปิดการใช้งานbinfmt_miscชั่วคราว ...


2
สำหรับผู้ที่อยากรู้ / proc คุณอาจสนใจ/ proc / * ทำงานอย่างไร บนSuper User
CVn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.