ทำไมซอฟต์แวร์ OS จึงมีความเฉพาะ?


77

ฉันพยายามหารายละเอียดทางเทคนิคว่าทำไมซอฟต์แวร์ที่ผลิตโดยใช้ภาษาการเขียนโปรแกรมสำหรับระบบปฏิบัติการบางระบบสามารถใช้งานได้กับพวกเขาเท่านั้น

ฉันเข้าใจว่าไบนารีนั้นมีความเฉพาะสำหรับโปรเซสเซอร์บางตัวเนื่องจากภาษาเครื่องเฉพาะของโปรเซสเซอร์ที่พวกเขาเข้าใจและชุดคำสั่งต่างกันระหว่างโปรเซสเซอร์ที่ต่างกัน แต่ความจำเพาะของระบบปฏิบัติการมาจากไหน? ฉันเคยคิดว่ามันเป็น API ที่จัดทำโดยระบบปฏิบัติการ แต่จากนั้นฉันเห็นแผนภาพนี้ในหนังสือ: แผนภาพ

ระบบปฏิบัติการ - ภายในและหลักการออกแบบ 7 ed - W. Stallings (Pearson, 2012)

อย่างที่คุณเห็น APIs ไม่ได้ระบุว่าเป็นส่วนหนึ่งของระบบปฏิบัติการ

ตัวอย่างเช่นถ้าฉันสร้างโปรแกรมอย่างง่ายใน C โดยใช้รหัสต่อไปนี้:

#include<stdio.h>

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

}

คอมไพเลอร์ทำอะไรที่เฉพาะกับ OS เมื่อทำการคอมไพล์หรือไม่


15
คุณพิมพ์ไปที่หน้าต่างหรือไม่? หรือคอนโซล? หรือหน่วยความจำกราฟิก? คุณจะใส่ข้อมูลที่นั่นได้อย่างไร ดูที่ printf สำหรับ Apple] [+ จะเงียบแตกต่างจาก Mac OS 7 และค่อนข้างแตกต่างจาก Mac OS X (เพียงติดกับคอมพิวเตอร์หนึ่งบรรทัด)

3
เพราะถ้าคุณเขียนโค้ดนั้นสำหรับ Mac OS 7 มันจะแสดงเป็นข้อความในหน้าต่างใหม่ หากคุณทำบน Apple] [+ มันจะเป็นการเขียนไปยังหน่วยความจำบางส่วนโดยตรง บน Mac OS X จะเขียนลงในคอนโซล ดังนั้นนั่นคือสามวิธีที่แตกต่างกันในการเขียนการจัดการโค้ดตามฮาร์ดแวร์การดำเนินการที่จัดการโดยเลเยอร์ไลบรารี

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

10
ฟังก์ชั่น FFT ของคุณจะทำงานภายใต้ Windows หรือ Linux (บน CPU เดียวกัน) อย่างมีความสุขโดยไม่ต้องทำการคอมไพล์ซ้ำ แต่คุณจะแสดงผลลัพธ์อย่างไร แน่นอนว่าการใช้ API ระบบปฏิบัติการ ( printfจาก msvcr90.dll ไม่เหมือนกับprintfจาก
libc.so.6

9
แม้ว่า APIs จะ "ไม่ได้เป็นส่วนหนึ่งของระบบปฏิบัติการ" แต่ก็ยังคงแตกต่างกันหากคุณไปจาก OS หนึ่งไปยังอีกระบบหนึ่ง (ซึ่งแน่นอนทำให้เกิดคำถามว่าวลี "ไม่ได้เป็นส่วนหนึ่งของระบบปฏิบัติการ" จริงๆหมายถึงตามแผนภาพ)
Theodoros Chatzigiannakis

คำตอบ:


78

คุณพูดถึงว่ารหัสเฉพาะสำหรับ CPU ทำไมต้องเป็นรหัสเฉพาะกับระบบปฏิบัติการด้วย นี่เป็นคำถามที่น่าสนใจมากกว่าที่คำตอบหลายข้อคิดเอาไว้

โมเดลความปลอดภัยของ CPU

วิ่งโปรแกรมแรกในส่วนซีพียูทำงานในสิ่งที่เรียกว่าวงแหวนหรือแหวน 0 วิธีการที่ CPU เฉพาะเจาะจงใช้แหวนแตกต่างกันไป แต่มันหมายถึงว่าเกือบทุก CPU ที่ทันสมัยมีอย่างน้อย 2 โหมดของการดำเนินการอย่างใดอย่างหนึ่งซึ่งเป็นสิทธิพิเศษและเรียกใช้รหัส 'โลหะเปลือย' ซึ่งสามารถดำเนินการทางกฎหมายใด ๆ ไม่น่าเชื่อถือและเรียกใช้รหัสที่ได้รับการป้องกันซึ่งสามารถทำชุดความสามารถที่ปลอดภัยที่กำหนดไว้เท่านั้น ซีพียูบางตัวมีความละเอียดสูงกว่ามากและเพื่อที่จะใช้ VM อย่างปลอดภัยต้องมีวงแหวนพิเศษอย่างน้อย 1 หรือ 2 วง (มักติดป้ายชื่อด้วยจำนวนลบ) อย่างไรก็ตามนี่อยู่นอกเหนือขอบเขตของคำตอบนี้

ที่มาของระบบปฏิบัติการ

ระบบปฏิบัติการ tasking เดียวในช่วงต้น

ในช่วงแรก ๆ ระบบ DOS และ tasking อื่น ๆ ที่ใช้รหัสทั้งหมดทำงานในวงแหวนด้านในทุกโปรแกรมที่คุณเคยวิ่งมีพลังเต็มทั้งคอมพิวเตอร์และสามารถทำอะไรก็ได้อย่างแท้จริงถ้ามันทำงานผิดปกติรวมถึงการลบข้อมูลทั้งหมดของคุณหรือแม้แต่ทำฮาร์ดแวร์เสียหาย ในบางกรณีที่รุนแรงเช่นการตั้งค่าโหมดการแสดงผลที่ไม่ถูกต้องบนหน้าจอแสดงผลที่เก่ามากแย่ลงซึ่งอาจเกิดจากรหัสรถที่ไม่มีความอาฆาตพยาบาท

รหัสนี้จริง ๆ แล้วผู้ไม่เชื่อเรื่องพระเจ้าส่วนใหญ่ตราบใดที่คุณมีโหลดเดอร์ที่สามารถโหลดโปรแกรมลงในหน่วยความจำได้ (ค่อนข้างง่ายสำหรับรูปแบบไบนารีในตอนต้น) และรหัสไม่ได้ขึ้นอยู่กับไดรเวอร์ใด ๆ ระบบปฏิบัติการใด ๆ ตราบเท่าที่มันทำงานในแหวน 0 หมายเหตุระบบปฏิบัติการที่ง่ายมากเช่นนี้มักจะเรียกว่าจอภาพถ้ามันใช้เพียงเพื่อเรียกใช้โปรแกรมอื่น ๆ และไม่มีฟังก์ชั่นเพิ่มเติม

ระบบมัลติทาสกิ้งสมัยใหม่

ระบบปฏิบัติการที่ทันสมัยกว่ารวมถึง UNIX , Windowsรุ่นที่เริ่มต้นด้วย NTและอื่น ๆ ที่ไม่ชัดเจน OSes ตัดสินใจที่จะปรับปรุงในสถานการณ์นี้ผู้ใช้ต้องการคุณสมบัติเพิ่มเติมเช่นมัลติทาสกิ้งเพื่อให้สามารถเรียกใช้มากกว่าหนึ่งแอปพลิเคชันในครั้งเดียว หรือรหัสที่เป็นอันตราย) ในแอปพลิเคชันไม่สามารถทำให้เกิดความเสียหายอย่างไม่ จำกัด กับตัวเครื่องและข้อมูล

สิ่งนี้ทำโดยใช้วงแหวนดังกล่าวข้างต้นระบบปฏิบัติการจะใช้สถานที่เดียวที่ทำงานในริง 0 และแอปพลิเคชันจะทำงานในวงแหวนนอกที่ไม่น่าเชื่อถือเท่านั้นที่สามารถดำเนินการชุดปฏิบัติการที่ จำกัด ซึ่งระบบปฏิบัติการอนุญาต

อย่างไรก็ตามยูทิลิตี้และการป้องกันที่เพิ่มขึ้นนี้มีค่าใช้จ่ายตอนนี้โปรแกรมต้องทำงานกับระบบปฏิบัติการเพื่อทำงานที่พวกเขาไม่ได้รับอนุญาตให้ทำเองพวกเขาไม่สามารถควบคุมฮาร์ดดิสก์ได้โดยตรงโดยการเข้าถึงหน่วยความจำและเปลี่ยนโดยพลการ ข้อมูล แต่พวกเขาต้องขอให้ระบบปฏิบัติการทำงานเหล่านี้เพื่อให้สามารถตรวจสอบว่าพวกเขาได้รับอนุญาตให้ดำเนินการไม่เปลี่ยนไฟล์ที่ไม่ได้เป็นของพวกเขาก็จะตรวจสอบว่าการดำเนินการถูกต้องและแน่นอน จะไม่ปล่อยให้ฮาร์ดแวร์อยู่ในสถานะไม่ได้กำหนด

แต่ละระบบปฏิบัติการตัดสินใจเกี่ยวกับการใช้งานที่แตกต่างกันสำหรับการปกป้องเหล่านี้บางส่วนขึ้นอยู่กับสถาปัตยกรรมที่ระบบปฏิบัติการได้รับการออกแบบและบางส่วนขึ้นอยู่กับการออกแบบและหลักการของระบบปฏิบัติการในคำถาม UNIX ยกตัวอย่างเช่นมุ่งเน้นไปที่เครื่อง คุณลักษณะที่มีอยู่สำหรับสิ่งนี้ในขณะที่หน้าต่างได้รับการออกแบบให้เรียบง่ายขึ้นใช้กับฮาร์ดแวร์ที่ช้ากว่าด้วยผู้ใช้คนเดียว วิธีที่โปรแกรมพื้นที่ผู้ใช้ยังพูดคุยกับระบบปฏิบัติการนั้นแตกต่างอย่างสิ้นเชิงกับ X86 เช่นเดียวกับ ARM หรือ MIPS เช่นบังคับให้ระบบปฏิบัติการหลายแพลตฟอร์มทำการตัดสินใจตามความจำเป็นในการทำงานกับฮาร์ดแวร์ที่เป็นเป้าหมาย

การโต้ตอบเฉพาะระบบปฏิบัติการเหล่านี้มักจะเรียกว่า "การเรียกของระบบ" และรวมถึงวิธีการที่โปรแกรมพื้นที่ผู้ใช้โต้ตอบกับฮาร์ดแวร์ผ่านระบบปฏิบัติการอย่างสมบูรณ์โดยพื้นฐานแล้วพวกเขาแตกต่างกันไปตามฟังก์ชั่นของระบบปฏิบัติการ เฉพาะระบบปฏิบัติการ

ตัวโหลดโปรแกรม

นอกจากนี้ในการเรียกระบบแต่ละระบบปฏิบัติการมีวิธีที่แตกต่างกันในการโหลดโปรแกรมจากสื่อเก็บข้อมูลทุติยภูมิและในหน่วยความจำในการสั่งซื้อที่จะใส่ได้โดยเฉพาะระบบปฏิบัติการโปรแกรมจะต้องมีส่วนหัวเป็นพิเศษซึ่งอธิบายถึงระบบปฏิบัติการว่ามันอาจจะเป็น โหลดและรัน

ส่วนหัวนี้เคยง่ายพอที่การเขียนตัวโหลดสำหรับรูปแบบที่แตกต่างกันนั้นแทบจะไม่สำคัญอย่างไรก็ตามด้วยรูปแบบที่ทันสมัยเช่นเอลฟ์ที่รองรับคุณสมบัติขั้นสูงเช่นการเชื่อมโยงแบบไดนามิกและการประกาศที่อ่อนแอตอนนี้เป็นไปไม่ได้ ซึ่งไม่ได้ออกแบบมาสำหรับมันหมายความว่าแม้ว่าจะไม่มีระบบเรียกความไม่ลงรอยกันมันเป็นเรื่องยากอย่างยิ่งที่จะวางโปรแกรมไว้ใน RAM ในลักษณะที่สามารถทำงานได้

ห้องสมุด

โปรแกรมแทบจะไม่ใช้การเรียกของระบบโดยตรง แต่พวกมันเกือบจะได้รับฟังก์ชั่นการใช้งานของพวกเขาเท่านั้นแม้ว่าไลบรารีที่ล้อมรอบการเรียกของระบบในรูปแบบที่เป็นมิตรสำหรับภาษาการเขียนโปรแกรมเช่น C มี C Standard Library และ glibc ภายใต้ Linux Windows NT และเหนือภาษาการเขียนโปรแกรมอื่นส่วนใหญ่มีไลบรารีที่คล้ายกันซึ่งห่อฟังก์ชันการทำงานของระบบในวิธีที่เหมาะสม

ห้องสมุดเหล่านี้สามารถในระดับหนึ่งแม้จะเอาชนะปัญหาข้ามแพลตฟอร์มดังกล่าวข้างต้นมีช่วงของห้องสมุดซึ่งได้รับการออกแบบมาให้แพลตฟอร์มเครื่องแบบเพื่อการใช้งานในขณะที่ภายในการจัดการการโทรไปยังที่หลากหลายของระบบปฏิบัติการเช่น SDLนี้หมายความว่าแม้ว่า โปรแกรมไม่สามารถเข้ากันได้กับไบนารีโปรแกรมที่ใช้ไลบรารีเหล่านี้สามารถมีแหล่งข้อมูลร่วมกันระหว่างแพลตฟอร์มทำให้การย้ายพอร์ตทำได้ง่ายเหมือนการคอมไพล์ใหม่

ข้อยกเว้นสำหรับข้างต้น

แม้จะมีทั้งหมดที่ฉันพูดที่นี่มีความพยายามที่จะเอาชนะข้อ จำกัด ที่ไม่สามารถเรียกใช้โปรแกรมบนระบบปฏิบัติการมากกว่าหนึ่งระบบ ตัวอย่างที่ดีคือโครงการไวน์ซึ่งประสบความสำเร็จในการจำลองทั้งตัวโหลดโปรแกรม win32 รูปแบบไบนารีและไลบรารีระบบที่อนุญาตให้โปรแกรม Windows ทำงานบน UNIX ต่างๆ นอกจากนี้ยังมีเลเยอร์ที่ใช้งานร่วมกันได้ซึ่งช่วยให้ระบบปฏิบัติการ BSD UNIX หลายตัวสามารถรันซอฟต์แวร์ Linux และแน่นอนว่า shim ของ Apple นั้นอนุญาตให้ใช้งานซอฟต์แวร์ MacOS รุ่นเก่าภายใต้ MacOS X

อย่างไรก็ตามโครงการเหล่านี้ทำงานผ่านการพัฒนาด้วยตนเองในระดับสูง ขึ้นอยู่กับว่า OS ทั้งสองนั้นแตกต่างกันอย่างไรในช่วงความยากลำบากตั้งแต่ชิมขนาดเล็กไปจนถึงการลอกเลียนแบบที่สมบูรณ์ของระบบปฏิบัติการอื่นซึ่งมักจะซับซ้อนกว่าการเขียนระบบปฏิบัติการทั้งหมดในตัวเองดังนั้นนี่คือข้อยกเว้นและไม่ใช่กฎ


6
+1 "เพราะเหตุใดซอฟต์แวร์ระบบปฏิบัติการจึงเจาะจง" เพราะประวัติศาสตร์
พอลเดรเปอร์

2
ความปลอดภัยของ CPU รุ่นที่มาจาก x86 คืออะไร? ทำไมและแบบจำลองถูกคิดค้นเมื่อใด
n611x007

8
@naxa ไม่มันยาวกว่า x86 มันถูกนำมาใช้ครั้งแรกบางส่วนสำหรับ Multics ในปี 1969 ซึ่งเป็นระบบปฏิบัติการแรกที่มีคุณสมบัติการแชร์เวลาหลายผู้ใช้ที่มีประโยชน์ซึ่งต้องการโมเดลนี้ในคอมพิวเตอร์GE-645อย่างไรก็ตามการใช้งานนี้ไม่สมบูรณ์และพึ่งพา สนับสนุนซอฟต์แวร์การดำเนินการครั้งแรกที่สมบูรณ์และมีความปลอดภัยในฮาร์ดแวร์อยู่ในทายาทของมันที่Honeywell 6180 นี่เป็นพื้นฐานของฮาร์ดแวร์อย่างสมบูรณ์และอนุญาตให้ Multics เรียกใช้รหัสจากผู้ใช้หลายคนโดยไม่มีโอกาสรบกวน
Vality

@Vality นอกจากนี้ IBM LPARคือ ~ 1972
Elliott Frisch

@ElliottFrisch ว้าวนั่นน่าประทับใจมาก ฉันไม่ได้ตระหนักว่ามันค่อนข้างเร็ว ขอบคุณสำหรับข้อมูลนั้น
Vality

48

อย่างที่คุณเห็น APIs ไม่ได้ระบุว่าเป็นส่วนหนึ่งของระบบปฏิบัติการ

ฉันคิดว่าคุณกำลังอ่านแผนภาพมากเกินไป ใช่ระบบปฏิบัติการจะระบุอินเทอร์เฟซแบบไบนารีสำหรับวิธีการเรียกใช้ฟังก์ชั่นระบบปฏิบัติการและจะกำหนดรูปแบบไฟล์สำหรับไฟล์ปฏิบัติการ แต่จะให้ API ในแง่ของการให้แคตตาล็อกของฟังก์ชั่นที่สามารถเรียกใช้โดย แอปพลิเคชันเพื่อเรียกใช้บริการระบบปฏิบัติการ

ฉันคิดว่าแผนภาพกำลังพยายามเน้นว่าฟังก์ชั่นระบบปฏิบัติการมักจะถูกเรียกใช้ผ่านกลไกที่แตกต่างจากการเรียกใช้ไลบรารีอย่างง่าย ระบบปฏิบัติการทั่วไปส่วนใหญ่ใช้การขัดจังหวะหน่วยประมวลผลเพื่อเข้าถึงฟังก์ชั่นระบบปฏิบัติการ ระบบปฏิบัติการสมัยใหม่ทั่วไปจะไม่ยอมให้โปรแกรมผู้ใช้เข้าถึงฮาร์ดแวร์ใด ๆได้โดยตรง หากคุณต้องการเขียนอักขระลงในคอนโซลคุณจะต้องขอให้ระบบปฏิบัติการทำงานให้คุณ การเรียกระบบที่ใช้ในการเขียนไปยังคอนโซลจะแตกต่างกันไปตามระบบปฏิบัติการดังนั้นจึงมีตัวอย่างหนึ่งว่าทำไมซอฟต์แวร์เฉพาะระบบปฏิบัติการ

printf เป็นฟังก์ชั่นจากไลบรารีรันไทม์ C และในการใช้งานทั่วไปเป็นฟังก์ชั่นที่ค่อนข้างซับซ้อน หากคุณ google คุณสามารถค้นหาแหล่งที่มาสำหรับหลายรุ่นออนไลน์ ดูหน้านี้ไกด์ทัวร์ของหนึ่ง ลงไปในหญ้าแม้ว่ามันจะจบลงด้วยการโทรหนึ่งระบบขึ้นไปและการโทรของระบบเหล่านั้นแต่ละครั้งก็เฉพาะกับระบบปฏิบัติการโฮสต์


4
จะทำอย่างไรถ้าโปรแกรมทั้งหมดทำเพื่อเพิ่มตัวเลขสองตัวโดยไม่มีอินพุตหรือเอาต์พุต โปรแกรมนั้นยังคงเป็นระบบปฏิบัติการที่เฉพาะเจาะจงหรือไม่?
Paul

2
ระบบปฏิบัติการมีไว้เพื่อวางสิ่งที่เฉพาะเจาะจงฮาร์ดแวร์ส่วนใหญ่ที่อยู่เบื้องหลัง / ในชั้นที่เป็นนามธรรม อย่างไรก็ตามระบบปฏิบัติการของตัวเอง (สิ่งที่เป็นนามธรรม) สามารถแตกต่างจากการใช้งานเพื่อการใช้งาน มี POSIX บาง OS'es (มากหรือน้อย) เป็นไปตามและอาจอื่น ๆ แต่ OS'es โดยรวมก็แตกต่างกันมากเกินไปในส่วน "มองเห็น" ของพวกเขาเป็นนามธรรม ดังที่ได้กล่าวไว้ก่อนหน้านี้: คุณไม่สามารถเปิด / home / user บน windows และคุณไม่สามารถเข้าถึง HKEY_LOCAL_MACHINE \ ... ในระบบ * N * X คุณสามารถเขียนซอฟต์แวร์เสมือน ("จำลอง") เพื่อช่วยให้ระบบเหล่านี้เข้าใกล้กันมากขึ้น แต่นั่นจะเป็น "บุคคลที่สาม" (จาก OS POV) เสมอ
RobIII

16
@ พอลใช่ โดยเฉพาะอย่างยิ่งวิธีที่มันถูกบรรจุลงในโปรแกรมที่เรียกทำงานได้นั้นจะเป็นระบบปฏิบัติการเฉพาะ
OrangeDog

4
@ TimSeguine ฉันไม่เห็นด้วยกับตัวอย่างของ XP ของคุณกับ 7. งานจำนวนมากทำโดย Microsoft เพื่อให้แน่ใจว่า API เดียวกันมีอยู่ใน 7 เช่นเดียวกับใน XP เห็นได้ชัดว่าสิ่งที่เกิดขึ้นที่นี่คือโปรแกรมถูกออกแบบมาเพื่อทำงานกับ API หรือสัญญาบางอย่าง ระบบปฏิบัติการใหม่เพิ่งใช้ API / สัญญาเดียวกัน ในกรณีของ windows อย่างไรก็ตาม API นั้นมีกรรมสิทธิ์เป็นอย่างมากซึ่งเป็นสาเหตุที่ไม่มีผู้จำหน่ายระบบปฏิบัติการรายอื่นสนับสนุน ถึงอย่างนั้นก็มีตัวอย่างมากมายของโปรแกรมที่ไม่ทำงานในวันที่ 7
ArTs

3
@Paul: โปรแกรมที่ไม่มี Input / Output เป็นโปรแกรมเปล่าซึ่งควรจะคอมไพล์เป็น no-op
Bergi

14

คอมไพเลอร์ทำอะไรที่เฉพาะกับ OS เมื่อทำการคอมไพล์หรือไม่

อาจ. ในบางจุดในระหว่างกระบวนการรวบรวมและเชื่อมโยงรหัสของคุณจะเปลี่ยนเป็นไบนารีเฉพาะระบบปฏิบัติการและเชื่อมโยงกับไลบรารีที่จำเป็น โปรแกรมของคุณจะต้องถูกบันทึกในรูปแบบที่ระบบปฏิบัติการคาดหวังเพื่อให้ระบบปฏิบัติการสามารถโหลดโปรแกรมและเริ่มดำเนินการได้ นอกจากนี้คุณกำลังเรียกใช้ฟังก์ชันไลบรารีมาตรฐานprintf()ซึ่งในบางระดับจะถูกนำไปใช้ในแง่ของบริการที่ระบบปฏิบัติการจัดเตรียมไว้ให้

ไลบรารีมีส่วนต่อประสาน - เลเยอร์ของสิ่งที่เป็นนามธรรมจากระบบปฏิบัติการและฮาร์ดแวร์ - และทำให้สามารถคอมไพล์โปรแกรมของคุณสำหรับระบบปฏิบัติการอื่นหรือฮาร์ดแวร์ที่แตกต่างกัน แต่สิ่งที่เป็นนามธรรมนั้นมีอยู่ในระดับแหล่งที่มา - เมื่อโปรแกรมรวบรวมและเชื่อมโยงแล้วมันจะเชื่อมต่อกับการใช้งานเฉพาะของส่วนต่อประสานที่เฉพาะเจาะจงกับระบบปฏิบัติการที่ระบุ


12

มีเหตุผลหลายประการ แต่เหตุผลสำคัญอย่างหนึ่งก็คือระบบปฏิบัติการต้องรู้วิธีการอ่านชุดของไบต์ที่ประกอบขึ้นเป็นโปรแกรมในหน่วยความจำค้นหาไลบรารีที่ไปกับโปรแกรมนั้นและโหลดลงในหน่วยความจำและ จากนั้นเริ่มเรียกใช้งานโค้ดโปรแกรมของคุณ ในการทำเช่นนี้ผู้สร้างระบบปฏิบัติการจะสร้างรูปแบบเฉพาะสำหรับชุดของไบต์นั้นเพื่อให้รหัสระบบปฏิบัติการรู้ตำแหน่งที่จะมองหาส่วนต่าง ๆ ของโครงสร้างของโปรแกรมของคุณ เนื่องจากระบบปฏิบัติการหลักมีผู้เขียนแตกต่างกันรูปแบบเหล่านี้จึงมีความเกี่ยวข้องกันน้อยมาก โดยเฉพาะอย่างยิ่งรูปแบบที่สามารถใช้งานได้กับWindowsมีความคล้ายคลึงกันเล็กน้อยกับฟอร์แมตเอลฟ์ซึ่งส่วนใหญ่ใช้รูปแบบ Unix ดังนั้นการโหลดทั้งหมดการเชื่อมโยงแบบไดนามิกและรหัสการดำเนินการจะต้องเป็นระบบปฏิบัติการที่เฉพาะเจาะจง

ถัดไปแต่ละระบบปฏิบัติการจะมีชุดไลบรารีที่แตกต่างกันสำหรับการพูดคุยกับเลเยอร์ฮาร์ดแวร์ API เหล่านี้คือ API ที่คุณพูดถึงและโดยทั่วไปจะเป็นไลบรารีที่นำเสนออินเทอร์เฟซที่ง่ายกว่าให้กับนักพัฒนาในขณะที่แปลไปเป็นสายที่ซับซ้อนและเฉพาะเจาะจงมากขึ้นในระดับความลึกของระบบปฏิบัติการเอง เลเยอร์นี้มักจะค่อนข้างเทาด้วย API "OS" ที่ใหม่กว่านั้นสร้างขึ้นบางส่วนหรือทั้งหมดบน API ที่เก่ากว่า ตัวอย่างเช่นใน Windows APIs ที่ใหม่กว่าจำนวนมากที่ Microsoft สร้างขึ้นในช่วงหลายปีที่ผ่านมานั้นเป็นชั้น ๆ ที่อยู่ด้านบนของ Win32 API ดั้งเดิม

ปัญหาที่ไม่ได้เกิดขึ้นในตัวอย่างของคุณ แต่นั่นเป็นหนึ่งในปัญหาที่ใหญ่กว่าที่นักพัฒนาเผชิญคืออินเทอร์เฟซกับตัวจัดการหน้าต่างเพื่อนำเสนอ GUI ตัวจัดการหน้าต่างเป็นส่วนหนึ่งของ "OS" หรือไม่ขึ้นอยู่กับมุมมองของคุณเช่นเดียวกับระบบปฏิบัติการของตัวเองโดยมี GUI ใน Windows ที่รวมเข้ากับระบบปฏิบัติการในระดับที่ลึกกว่าในขณะที่ GUI บน Linux และ OS X แยกโดยตรงมากขึ้น สิ่งนี้สำคัญมากเพราะทุกวันนี้สิ่งที่คนทั่วไปเรียกว่า "ระบบปฏิบัติการ" นั้นเป็นสัตว์ร้ายที่ใหญ่กว่าตำราที่มักจะอธิบายเนื่องจากมีส่วนประกอบระดับแอพพลิเคชั่นมากมาย

สุดท้ายไม่ใช่ปัญหาของระบบปฏิบัติการอย่างเคร่งครัด แต่สิ่งที่สำคัญในการสร้างไฟล์ที่ปฏิบัติการได้คือเครื่องต่าง ๆ มีเป้าหมายภาษาแอสเซมบลีที่แตกต่างกันดังนั้นรหัสวัตถุที่สร้างขึ้นจริงต้องแตกต่างกัน สิ่งนี้ไม่ได้พูดถึงปัญหา "OS" อย่างเคร่งครัด แต่เป็นปัญหาฮาร์ดแวร์ แต่หมายความว่าคุณจะต้องมีบิลด์ต่าง ๆ สำหรับแพลตฟอร์มฮาร์ดแวร์ต่าง ๆ


2
มันอาจคุ้มค่าที่จะทราบว่ารูปแบบที่สามารถใช้งานได้ง่ายกว่าสามารถโหลดได้โดยใช้ RAM เพียงเล็กน้อย (ถ้ามี) เกินกว่าที่กำหนดเพื่อเก็บรหัสที่โหลดในขณะที่รูปแบบที่ซับซ้อนอาจต้องใช้ RAM ขนาดใหญ่กว่าในระหว่างและในบางกรณี แม้หลังจากโหลด MS-DOS จะโหลดไฟล์ COM ได้มากถึง 63.75K เพียงแค่อ่านลำดับไบต์ไปที่ RAM เริ่มต้นที่ออฟเซ็ต 0x100 ของเซกเมนต์ตามอำเภอใจโหลด CX ด้วยที่อยู่ปลายทางและข้ามไปที่นั้น การรวบรวมแบบ Single-Pass สามารถทำได้โดยไม่ต้องทำการ back-patching (มีประโยชน์กับ floppies) โดย ...
supercat

1
... การที่คอมไพเลอร์รวมกับรายการรูทแพตช์ทุกชุดซึ่งแต่ละอันจะรวมที่อยู่ของรายการดังกล่าวก่อนหน้านี้และวางที่อยู่ของรายการสุดท้ายที่ส่วนท้ายของรหัส ระบบปฏิบัติการจะโหลดรหัสเป็นไบต์ดิบ แต่รูทีนขนาดเล็กภายในรหัสสามารถใช้โปรแกรมแก้ไขที่อยู่ที่จำเป็นทั้งหมดก่อนที่จะเรียกใช้ส่วนหลักของรหัส
supercat

9

จากคำตอบของฉันอีก:

พิจารณาเครื่อง DOS ก่อนหน้านี้และสิ่งที่ Microsoft ให้การสนับสนุนโลกคือ

Autocad ต้องเขียนไดรเวอร์สำหรับเครื่องพิมพ์แต่ละเครื่องที่สามารถพิมพ์ได้ ดอกบัว 1-2-3 ก็เช่นกัน ความจริงแล้วถ้าคุณต้องการให้ซอฟต์แวร์พิมพ์คุณต้องเขียนไดรเวอร์ของคุณเอง หากมีเครื่องพิมพ์ 10 เครื่องและ 10 โปรแกรมดังนั้น 100 ชิ้นส่วนต่าง ๆ ของรหัสเดียวกันจะต้องเขียนแยกต่างหากและเป็นอิสระ

สิ่งที่ windows 3.1 พยายามทำ (รวมถึง GEM และเลเยอร์ abstraction อื่น ๆ อีกมากมาย) ทำให้ผู้ผลิตเครื่องพิมพ์เขียนไดร์เวอร์หนึ่งตัวสำหรับเครื่องพิมพ์ของพวกเขาและโปรแกรมเมอร์เขียนไดร์เวอร์หนึ่งตัวสำหรับคลาสเครื่องพิมพ์ของ windows

ขณะนี้มี 10 โปรแกรมและเครื่องพิมพ์ 10 เครื่องต้องเขียนโค้ดเพียง 20 ชิ้นและเนื่องจากโค้ดด้านไมโครซอฟท์นั้นเหมือนกันสำหรับทุกคนดังนั้นตัวอย่างจาก MS จึงหมายความว่าคุณมีงานต้องทำน้อยมาก

ตอนนี้โปรแกรมไม่ได้ จำกัด อยู่เพียงแค่เครื่องพิมพ์ 10 เครื่องที่พวกเขาเลือกให้การสนับสนุน แต่เครื่องพิมพ์ทั้งหมดที่ผู้ผลิตให้ไดรเวอร์สำหรับใน windows

ดังนั้นระบบปฏิบัติการจึงให้บริการกับแอพพลิเคชั่นดังนั้นแอพพลิเคชั่นไม่จำเป็นต้องทำงานซ้ำซ้อน

ตัวอย่างโปรแกรม C ของคุณใช้ printf ซึ่งส่งอักขระไปยัง stdout - ทรัพยากรเฉพาะของระบบปฏิบัติการที่จะแสดงอักขระบนส่วนต่อประสานผู้ใช้ โปรแกรมไม่จำเป็นต้องรู้ว่าส่วนต่อประสานผู้ใช้อยู่ที่ใด - อาจอยู่ใน DOS อาจอยู่ในหน้าต่างกราฟิกก็สามารถไพพ์ไปยังโปรแกรมอื่นและใช้เป็นอินพุตไปยังกระบวนการอื่น

เนื่องจากระบบปฏิบัติการให้ทรัพยากรเหล่านี้โปรแกรมเมอร์จึงสามารถทำงานได้มากขึ้นด้วยการทำงานเพียงเล็กน้อย

อย่างไรก็ตามแม้กระทั่งการเริ่มต้นโปรแกรมก็มีความซับซ้อน ระบบปฏิบัติการคาดว่าไฟล์ที่ปฏิบัติการได้จะมีข้อมูลบางอย่างในตอนเริ่มต้นซึ่งบอกกับระบบปฏิบัติการว่าควรเริ่มต้นอย่างไรและในบางกรณี (ในสภาพแวดล้อมขั้นสูงเช่น android หรือ iOS) ทรัพยากรใดบ้างที่จำเป็นต้องได้รับการอนุมัติ "sandbox" - มาตรการรักษาความปลอดภัยเพื่อช่วยปกป้องผู้ใช้และแอปอื่น ๆ จากโปรแกรมที่ทำงานผิดปกติ

ดังนั้นแม้ว่ารหัสเครื่องที่ปฏิบัติการได้จะเหมือนกันและไม่จำเป็นต้องมีทรัพยากรระบบปฏิบัติการโปรแกรมที่คอมไพล์สำหรับ Windows จะไม่ทำงานบนระบบปฏิบัติการ OS X โดยไม่มีการจำลองเพิ่มเติมหรือเลเยอร์การแปลแม้ในฮาร์ดแวร์เดียวกัน

ระบบปฏิบัติการรูปแบบ DOS ยุคแรก ๆ มักจะใช้โปรแกรมร่วมกันเพราะพวกเขาใช้ API เดียวกันในฮาร์ดแวร์ (BIOS) และระบบปฏิบัติการเชื่อมต่อกับฮาร์ดแวร์เพื่อให้บริการ ดังนั้นหากคุณเขียนและคอมไพล์โปรแกรม COM - ซึ่งเป็นเพียงภาพหน่วยความจำของชุดคำสั่งโปรเซสเซอร์ - คุณสามารถเรียกใช้บน CP / M, MS-DOS และระบบปฏิบัติการอื่น ๆ ในความเป็นจริงคุณยังคงสามารถเรียกใช้โปรแกรม COM บนเครื่อง windows ที่ทันสมัย ระบบปฏิบัติการอื่นไม่ใช้ hooks API API ของ BIOS ที่เหมือนกันดังนั้นโปรแกรม COM จะไม่ทำงานโดยไม่มีเลเยอร์การจำลองหรือการแปลอีกครั้ง โปรแกรม EXE เป็นไปตามโครงสร้างที่มีมากกว่าตัวประมวลผลคำแนะนำเท่านั้นและด้วยปัญหา API มันจะไม่ทำงานบนเครื่องที่ไม่เข้าใจวิธีการโหลดลงในหน่วยความจำและดำเนินการ


7

ที่จริงแล้วคำตอบที่แท้จริงคือว่าถ้าทุกระบบปฏิบัติการไม่เข้าใจรูปแบบไฟล์เดียวกันปฏิบัติการไบนารีและคุณจะ จำกัด ตัวเองให้ฟังก์ชั่นมาตรฐาน (เช่นในห้องสมุดมาตรฐาน C) ที่ OS ที่ให้ไว้ (ซึ่งระบบปฏิบัติการจะให้) จากนั้นซอฟต์แวร์ของคุณจะที่จริงแล้วทำงานบนระบบปฏิบัติการใด ๆ

แน่นอนความเป็นจริงไม่ใช่กรณี EXEไฟล์ไม่ได้มีรูปแบบเช่นเดียวกับELFไฟล์แม้ว่าทั้งสองมีรหัสไบนารีสำหรับ CPU เดียวกัน. * ดังนั้นแต่ละระบบปฏิบัติการจะต้องสามารถที่จะตีความรูปแบบไฟล์ทั้งหมดและพวกเขาก็ไม่ได้ทำเช่นนี้ใน การเริ่มต้นและไม่มีเหตุผลสำหรับพวกเขาที่จะเริ่มทำในภายหลัง (เกือบจะแน่นอนด้วยเหตุผลเชิงพาณิชย์มากกว่าทางเทคนิค)

นอกจากนี้โปรแกรมของคุณอาจต้องทำสิ่งต่าง ๆ ที่ไลบรารี C ไม่ได้กำหนดวิธีการทำ (แม้แต่สำหรับสิ่งที่เรียบง่ายเช่นการแสดงรายการเนื้อหาของไดเรกทอรี) และในกรณีเหล่านั้นทุกระบบปฏิบัติการมีฟังก์ชันของตัวเองเพื่อให้บรรลุเป้าหมาย งานซึ่งหมายความว่าโดยธรรมชาติจะไม่มีตัวหารร่วมที่ต่ำที่สุดสำหรับคุณที่จะใช้ (เว้นแต่คุณจะสร้างตัวหารนั้นเอง)

ดังนั้นในหลักการมันเป็นไปได้อย่างสมบูรณ์แบบ ในความเป็นจริง WINE รันโปรแกรมปฏิบัติการ Windows ได้โดยตรงบน Linux
แต่มันเป็นงานตันและ (โดยปกติ) ไม่ยุติธรรมในเชิงพาณิชย์

* หมายเหตุ: มีเป็นจำนวนมากมากขึ้นในแฟ้มที่ปฏิบัติการกว่ารหัสไบนารีเพียง มีเป็นตันของข้อมูลที่บอกว่าระบบปฏิบัติการสิ่งที่ห้องสมุดไฟล์ขึ้นอยู่กับเท่าใดหน่วยความจำสแต็คที่มันต้องการสิ่งที่ฟังก์ชั่นการส่งออกไปยังที่อื่น ๆห้องสมุดที่อาจขึ้นอยู่กับมันที่ระบบปฏิบัติการอาจพบข้อมูลการแก้ปัญหาที่เกี่ยวข้องกับวิธีการ " หาตำแหน่ง "ไฟล์ในหน่วยความจำอีกครั้งถ้าจำเป็นวิธีการจัดการข้อยกเว้นทำงานอย่างถูกต้อง ฯลฯ ฯลฯ .... อีกครั้งอาจมีรูปแบบเดียวสำหรับสิ่งนี้ที่ทุกคนเห็นด้วย แต่ไม่มี


สนุกจริง: มีรูปแบบไบนารี posiz มาตรฐานซึ่งสามารถเรียกใช้ข้ามระบบปฏิบัติการได้ มันไม่ได้ใช้กันทั่วไป
Marcin

@Marcin: ดูเหมือนว่าคุณจะไม่ถือว่า Windows เป็นระบบปฏิบัติการ (หรือคุณกำลังบอกว่า Windows สามารถรัน POSIX ไบนารีได้หรือไม่!) สำหรับวัตถุประสงค์ของคำตอบของฉัน POSIX ไม่ใช่มาตรฐานที่ฉันอ้างถึง X ใน POSIX ย่อมาจาก Unix มันไม่เคยตั้งใจที่จะใช้โดยเช่น Windows แม้ว่า Windows จะเกิดขึ้นกับระบบย่อย POSIX
Mehrdad

1. บางสิ่งสามารถทำงานได้ในหลาย ๆ OS โดยไม่ต้องใช้งานข้าม OS ทั้งหมด 2. Windows ตั้งแต่ NT สามารถรัน posix ไบนารีได้
Marcin

1
@Marcin: (1) เช่นฉันกล่าวว่า X ใน POSIX ย่อมาจากยูนิกซ์ มันไม่ได้เป็นมาตรฐานที่ตั้งใจจะตามด้วยระบบปฏิบัติการอื่นมันเป็นเพียงความพยายามที่จะเข้าถึงตัวส่วนร่วมระหว่างยูนิกซ์ต่างๆซึ่งยอดเยี่ยม แต่ก็ไม่น่าอัศจรรย์ ความจริงที่ว่า Unix OS นั้นมีหลายรสชาตินั้นไม่เกี่ยวข้องกับจุดที่ฉันพยายามจะทำเกี่ยวกับความเข้ากันได้กับระบบปฏิบัติการอื่นที่ไม่ใช่ยูนิกซ์ (2) คุณสามารถให้การอ้างอิงสำหรับ # 2 ได้หรือไม่
Mehrdad

1
@Mehrdad: Marcin ถูกต้อง; Windows SUA (ระบบย่อยสำหรับแอปพลิเคชั่น Unix) เป็นไปตาม POSIX
MSalters

5

แผนภาพมีเลเยอร์ "แอปพลิเคชัน" (ส่วนใหญ่) แยกออกจากเลเยอร์ "ระบบปฏิบัติการ" โดย "ไลบรา" และนั่นก็หมายความว่า "แอปพลิเคชัน" และ "OS" ไม่จำเป็นต้องรู้ซึ่งกันและกัน นั่นคือการทำให้เข้าใจง่ายในแผนภาพ แต่ก็ไม่เป็นความจริง

ปัญหาคือว่า "ไลบรารี่" มีสามส่วนจริง ๆ : การนำไปใช้งานอินเทอร์เฟซสำหรับแอปพลิเคชันและอินเทอร์เฟซกับระบบปฏิบัติการ โดยหลักการแล้วสองรายการแรกสามารถสร้าง "สากล" ได้เท่าที่เกี่ยวข้องกับระบบปฏิบัติการ (ขึ้นอยู่กับตำแหน่งที่คุณหั่น) แต่ส่วนที่สาม - ส่วนต่อประสานกับระบบปฏิบัติการ - โดยทั่วไปไม่สามารถทำได้ อินเทอร์เฟซสำหรับระบบปฏิบัติการนั้นจำเป็นต้องขึ้นอยู่กับระบบปฏิบัติการ, API ที่ให้ไว้, กลไกการบรรจุ (เช่นรูปแบบไฟล์ที่ใช้โดย Windows DLL) เป็นต้น

เนื่องจากโดยทั่วไป "ไลบรารี่" นั้นมีให้ใช้งานเป็นแพ็กเกจเดียวนั่นหมายความว่าเมื่อโปรแกรมเลือก "ไลบรารี่" เพื่อใช้งานมันก็จะส่งมอบให้กับระบบปฏิบัติการเฉพาะ สิ่งนี้เกิดขึ้นหนึ่งในสองวิธี: a) โปรแกรมเมอร์เลือกล่วงหน้าอย่างสมบูรณ์จากนั้นการเชื่อมโยงระหว่างไลบรารีกับแอปพลิเคชันอาจเป็นสากล แต่ไลบรารีเองนั้นผูกพันกับระบบปฏิบัติการ หรือ b) โปรแกรมเมอร์กำหนดสิ่งต่าง ๆ เพื่อเลือกไลบรารีเมื่อคุณรันโปรแกรม แต่จากนั้นกลไกการเชื่อมโยงระหว่างโปรแกรมและไลบรารีนั้นขึ้นอยู่กับระบบปฏิบัติการ (เช่นกลไก DLL ใน Windows) แต่ละคนมีข้อดีและข้อเสีย แต่วิธีใดคุณต้องเลือกล่วงหน้า

ตอนนี้ไม่ได้หมายความว่ามันเป็นไปไม่ได้ที่จะทำ แต่คุณต้องฉลาดมาก ในการเอาชนะปัญหาคุณจะต้องไปตามเส้นทางของการเลือกไลบรารีในขณะใช้งานและคุณต้องหากลไกการเชื่อมต่อสากลที่ไม่ได้ขึ้นอยู่กับระบบปฏิบัติการ (ดังนั้นคุณต้องรับผิดชอบในการบำรุงรักษา ทำงานได้มากขึ้น) บางครั้งมันก็คุ้มค่า

คุณไม่จำเป็นต้อง แต่ถ้าคุณกำลังพยายามที่จะทำเช่นนั้นมีโอกาสที่ดีที่คุณไม่ต้องการที่จะเชื่อมโยงกับหน่วยประมวลผลเฉพาะดังนั้นคุณจะเขียนเครื่องเสมือนและคุณจะรวบรวม โปรแกรมของคุณเป็นรูปแบบรหัสเป็นกลางของโปรเซสเซอร์

ตอนนี้คุณควรจะสังเกตุว่าฉันกำลังจะไปไหน ภาษาแพลตฟอร์มอย่าง Java ทำอย่างนั้น Java runtime (ไลบรารี) กำหนดการเชื่อมโยงระหว่างระบบปฏิบัติการกลางระหว่างโปรแกรม Java ของคุณและไลบรารี (วิธีที่ Java runtime เปิดและรันโปรแกรมของคุณ) และให้การปรับใช้เฉพาะกับระบบปฏิบัติการปัจจุบัน .NET ทำสิ่งเดียวกันเท่าที่ยกเว้นว่า Microsoft ไม่ได้ให้ "ไลบรารี่" (รันไทม์) สำหรับสิ่งใดนอกจากวินโดวส์ (แต่คนอื่นทำ - ดูโมโน) และที่จริงแล้ว Flash ก็ทำสิ่งเดียวกันแม้ว่ามันจะมีข้อ จำกัด มากกว่าเบราว์เซอร์

ในที่สุดก็มีวิธีที่จะทำสิ่งเดียวกันโดยไม่ต้องมีกลไกการผูกที่กำหนดเอง คุณสามารถใช้เครื่องมือทั่วไป แต่เลื่อนขั้นตอนการเชื่อมโยงไปยังไลบรารีจนกว่าผู้ใช้เลือกระบบปฏิบัติการ นั่นคือสิ่งที่เกิดขึ้นเมื่อคุณแจกจ่ายซอร์สโค้ด ผู้ใช้นำโปรแกรมของคุณและผูกไว้กับโปรเซสเซอร์ (รวบรวม) และ OS (ลิงก์) เมื่อผู้ใช้พร้อมที่จะเรียกใช้

ทุกอย่างขึ้นอยู่กับว่าคุณจะเลเยอร์เลเยอร์อย่างไร ในตอนท้ายของวันคุณจะมีอุปกรณ์คอมพิวเตอร์ที่ทำกับฮาร์ดแวร์เฉพาะที่ใช้รหัสเครื่องเฉพาะ เลเยอร์จะมีเป็นกรอบแนวคิด


3

ซอฟต์แวร์ไม่ใช่ระบบปฏิบัติการที่เฉพาะเจาะจงเสมอไป ทั้งJavaและระบบ p-code ก่อนหน้า (และแม้แต่ ScummVM) อนุญาตให้ใช้ซอฟต์แวร์ที่พกพาข้ามระบบปฏิบัติการ Infocom (ผู้ผลิตZorkและZ-machine ) ก็มีฐานข้อมูลเชิงสัมพันธ์ที่อ้างอิงจากเครื่องเสมือนอื่น อย่างไรก็ตามในบางระดับมีบางสิ่งที่ต้องแปลแม้แต่ abstractions เหล่านั้นไปเป็นคำแนะนำจริงที่จะดำเนินการบนคอมพิวเตอร์


3
Java ทำงานบนเครื่องเสมือนซึ่งไม่ได้ทำงานข้ามระบบปฏิบัติการ คุณต้องใช้ไบนารี JVM ที่แตกต่างกันสำหรับแต่ละระบบปฏิบัติการ
Izkata

3
@Izkata True แต่คุณไม่ต้องคอมไพล์ซอฟต์แวร์ซ้ำอีกครั้ง (เฉพาะ JVM) ดูประโยคสุดท้ายของฉันด้วย แต่ฉันจะชี้ให้เห็นว่าซันมีไมโครโปรเซสเซอร์ซึ่งสามารถรันโค้ดไบต์ได้โดยตรง
Elliott Frisch

3
Java เป็นระบบปฏิบัติการถึงแม้ว่ามันมักจะไม่คิดว่าเป็นหนึ่ง ซอฟต์แวร์ Java เป็นซอฟต์แวร์เฉพาะของ Java OS และมีโปรแกรมจำลอง Java OS สำหรับ OS "ของจริง" ส่วนใหญ่ แต่คุณสามารถทำสิ่งเดียวกันกับโฮสต์และระบบปฏิบัติการเป้าหมาย - เช่นใช้ซอฟต์แวร์ Windows บน Linux โดยใช้ WINE
253751

@immibis ฉันจะเฉพาะเจาะจงมากขึ้น Java Foundation Classes (JFC, ไลบรารีมาตรฐานของ Java) เป็นกรอบงาน Java เองนั้นเป็นภาษา JVM คล้ายกับระบบปฏิบัติการ: มี "เครื่องเสมือน" ในชื่อและดำเนินการฟังก์ชันที่คล้ายคลึงกับระบบปฏิบัติการจากมุมมองของรหัสที่ใช้งานอยู่

1

คุณพูด

ซอฟต์แวร์ที่ผลิตโดยใช้ภาษาการเขียนโปรแกรมสำหรับระบบปฏิบัติการบางระบบสามารถใช้งานได้กับพวกเขาเท่านั้น

แต่โปรแกรมที่คุณให้เป็นตัวอย่างจะทำงานบนระบบปฏิบัติการหลายระบบและแม้แต่สภาพแวดล้อมที่เป็นโลหะเปลือย

สิ่งสำคัญที่นี่คือความแตกต่างระหว่างซอร์สโค้ดและไบนารีรวบรวม ภาษาการเขียนโปรแกรม C ได้รับการออกแบบมาโดยเฉพาะเพื่อให้ระบบปฏิบัติการเป็นอิสระในรูปแบบต้นฉบับ มันทำได้โดยออกความหมายของสิ่งต่าง ๆ เช่น "พิมพ์ไปยังคอนโซล" ถึงผู้ดำเนินการ แต่ C อาจเป็นไปตามสิ่งที่เฉพาะเจาะจงกับระบบปฏิบัติการ (ดูคำตอบอื่น ๆ ด้วยเหตุผล) ตัวอย่างเช่นรูปแบบที่ดำเนินการ PE หรือ ELF


6
ดูเหมือนว่าค่อนข้างชัดเจนว่า OP กำลังถามเกี่ยวกับไบนารีไม่ใช่ซอร์สโค้ด
คาเลบ

0

คนอื่น ๆ ได้กล่าวถึงรายละเอียดทางเทคนิคอย่างดีฉันอยากจะพูดถึงเหตุผลทางเทคนิคที่น้อยลงด้าน UX / UI ของสิ่งต่าง ๆ :

เขียนครั้งเดียวรู้สึกเขินทุกที่

ทุกระบบปฏิบัติการมี API ส่วนต่อประสานผู้ใช้และมาตรฐานการออกแบบ มีความเป็นไปได้ที่จะเขียนส่วนต่อประสานผู้ใช้สำหรับโปรแกรมและให้มันทำงานบนระบบปฏิบัติการหลายระบบอย่างไรก็ตามทำเช่นนั้นทั้งหมด แต่รับประกันได้ว่าโปรแกรมนั้นจะออกนอกสถานที่ได้ทุกที่ การสร้างส่วนต่อประสานผู้ใช้ที่ดีต้องปรับแต่งรายละเอียดสำหรับแต่ละแพลตฟอร์มที่รองรับ

สิ่งเหล่านี้มีรายละเอียดเล็กน้อย แต่ทำให้พวกเขาเข้าใจผิดและคุณจะทำให้ผู้ใช้ของคุณผิดหวัง

  • ยืนยันไดอะล็อกมีปุ่มต่างกันใน Windows และ OSX ทำสิ่งนี้ผิดและผู้ใช้จะคลิกที่ปุ่มผิดโดยหน่วยความจำของกล้ามเนื้อ Windows มี "Ok", "Cancel" ตามลำดับ OSX ได้เปลี่ยนคำสั่งซื้อและข้อความของปุ่ม do-it เป็นคำอธิบายสั้น ๆ ของการกระทำที่จะดำเนินการ: "ยกเลิก", ​​"ย้ายไปที่ถังขยะ"
  • พฤติกรรม "ย้อนกลับ" แตกต่างกันสำหรับ iOS และ Android แอปพลิเคชั่น iOS วาดปุ่มย้อนกลับของตัวเองตามต้องการโดยปกติจะอยู่ที่มุมบนซ้าย Android มีปุ่มเฉพาะในด้านล่างซ้ายหรือขวาล่างขึ้นอยู่กับการหมุนหน้าจอ พอร์ตด่วนสำหรับ Android จะทำงานไม่ถูกต้องหากปุ่มย้อนกลับของระบบปฏิบัติการถูกละเว้น
  • การเลื่อนโมเมนตัมแตกต่างกันระหว่าง iOS, OSX และ Android น่าเศร้าถ้าคุณไม่ได้เขียนโค้ด UI พื้นฐานคุณอาจต้องเขียนพฤติกรรมการเลื่อนของคุณเอง

แม้ว่าจะเป็นไปได้ในทางเทคนิคที่จะเขียนหนึ่งใน codebase UI ที่ทำงานได้ทุกที่ แต่ก็เป็นการดีที่สุดที่จะทำการปรับเปลี่ยนสำหรับระบบปฏิบัติการที่รองรับแต่ละระบบ


-2

ความแตกต่างที่สำคัญ ณ จุดนี้คือการแยกคอมไพเลอร์ออกจากตัวเชื่อมโยง คอมไพเลอร์มีแนวโน้มที่จะสร้างเอาต์พุตเดียวกันมากขึ้นหรือน้อยลง (ความแตกต่างส่วนใหญ่เกิดจาก#if WINDOWSs ต่างๆ) ในทางกลับกันตัวเชื่อมโยงต้องจัดการทุกสิ่งเฉพาะแพลตฟอร์ม - การเชื่อมโยงไลบรารีการสร้างแฟ้มที่ปฏิบัติการได้เป็นต้น

คอมไพเลอร์ใส่ใจเรื่องสถาปัตยกรรมซีพียูเป็นส่วนใหญ่เพราะมันผลิตโค้ดที่รันได้จริงและต้องใช้คำแนะนำและทรัพยากรของซีพียู (โปรดทราบว่า bytecode ของ. NET IL หรือ JVM จะพิจารณาชุดคำสั่งของ CPU เสมือน ในมุมมองนี้) นี่คือเหตุผลที่คุณต้องรวบรวมรหัสแยกต่างหากสำหรับx86และARMตัวอย่างเช่น

เครื่องมือเชื่อมโยงนั้นต้องใช้ข้อมูลดิบและคำแนะนำทั้งหมดและวางไว้ในรูปแบบที่โหลดเดอร์ (วันนี้สิ่งนี้มักจะเป็นระบบปฏิบัติการ) สามารถเข้าใจได้เช่นเดียวกับการเชื่อมโยงไลบรารีที่เชื่อมโยงแบบสแตติกใด ๆ (ซึ่งรวมถึงรหัสที่จำเป็นสำหรับการเชื่อมโยงแบบไดนามิกการจัดสรรหน่วยความจำ ฯลฯ )

กล่าวอีกนัยหนึ่งคุณสามารถรวบรวมรหัสได้เพียงครั้งเดียวและใช้งานได้ทั้งบน Linux และ Windows - แต่คุณต้องเชื่อมโยงสองครั้งเพื่อสร้างสองโปรแกรมที่แตกต่างกัน ตอนนี้ในทางปฏิบัติคุณมักจะต้องให้ค่าเผื่อในโค้ดด้วย (นั่นคือที่คำสั่งคอมไพเลอร์ (pre-) เข้ามา) ดังนั้นแม้แต่การคอมไพล์ครั้งเดียวลิงก์สองครั้งก็ไม่ได้ใช้มากนัก ไม่ต้องพูดถึงว่าผู้คนกำลังทำการคอมไพล์และเชื่อมโยงเป็นขั้นตอนเดียวในระหว่างการสร้าง

ซอฟต์แวร์ยุคดอสนั้นมักเป็นแบบพกพามากกว่าไบนารี แต่คุณต้องเข้าใจว่ามันไม่ได้รวบรวมกับ DOS หรือ Unix แต่เทียบกับสัญญาบางข้อซึ่งเป็นเรื่องธรรมดาสำหรับพีซีสไตล์ IBM ส่วนใหญ่ การขัดจังหวะของซอฟต์แวร์ สิ่งนี้ไม่ต้องการการเชื่อมโยงแบบสแตติกเนื่องจากคุณต้องตั้งค่ารีจิสเตอร์ที่จำเป็นการโทรเช่นint 13hฟังก์ชั่นกราฟิกและซีพียูเพิ่งจะกระโดดไปยังตัวชี้หน่วยความจำที่ประกาศในตารางขัดจังหวะ แน่นอนอีกครั้งว่าการฝึกฝนนั้นมีความซับซ้อนมากเพราะการที่จะเหยียบคันเร่งกับโลหะคุณต้องเขียนวิธีการเหล่านั้นด้วยตัวคุณเอง และแน่นอนว่ามีบางสิ่งที่จำเป็นต้องมีการโต้ตอบกับ OS API - การยกเลิกโปรแกรม แต่ก็ยังถ้าคุณใช้รูปแบบที่ง่ายที่สุดที่มีอยู่ (เช่นCOMบน DOS ซึ่งไม่มีส่วนหัวเพียงแค่คำแนะนำ) และไม่ต้องการออกเลยโชคดีคุณ! และแน่นอนคุณสามารถจัดการการเลิกจ้างที่เหมาะสมในรันไทม์ได้เช่นกันดังนั้นคุณสามารถมีรหัสสำหรับการเลิกจ้าง Unix และการเลิกจ้าง DOS ในการปฏิบัติการเดียวกันและตรวจสอบที่รันไทม์ที่หนึ่งที่จะใช้ :)


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