ปัจจัยทางสังคมหรือทางเทคนิคใดที่นำไปสู่การเพิ่มขึ้นของความคิดของ CIY?
สาเหตุสวยอย่างเห็นได้ชัดด้วยเหตุผลทางเทคนิค: Binary พกพาเป็นหนักกว่าแหล่งพกพา นอกเหนือจากแพ็คเกจ distro ซอฟต์แวร์ฟรีส่วนใหญ่ยังคงมีให้ในรูปแบบซอร์สเท่านั้นเพราะสะดวกกว่าสำหรับผู้เขียน / ผู้ดูแล
จนกว่า Linux distros จะเริ่มทำสิ่งต่าง ๆ ที่คนส่วนใหญ่ต้องการใช้ตัวเลือกเดียวของคุณคือการรับแหล่งข้อมูลและรวบรวมสำหรับระบบของคุณเอง ผู้ค้า Unix เชิงพาณิชย์มักจะไม่รวมเนื้อหาที่เกือบทุกคนต้องการ (เช่น shell ที่ดีอย่าง GNU bash
หรือคล้ายกัน) เพียงแค่ใช้งานsh
และ / หรือcsh
ดังนั้นพวกเขาจึงจำเป็นต้องสร้างสิ่งต่าง ๆ ด้วยตัวคุณเองถ้าคุณต้องการเป็น sys-admin เพื่อจัดเตรียมสภาพแวดล้อม Unix ที่ดีให้กับผู้ใช้ของคุณสำหรับการใช้แบบโต้ตอบ
สถานการณ์ตอนนี้ผู้คนส่วนใหญ่เป็นผู้ดูแลระบบเพียงคนเดียวและผู้ใช้เครื่องเดียวที่นั่งอยู่บนเดสก์ท็อปของพวกเขานั้นต่างจากรุ่น Unix ทั่วไปอย่างมาก ดูแลระบบดูแลซอฟต์แวร์บนระบบส่วนกลางและบนเดสก์ท็อปของทุกคน (บ่อยครั้งที่มีเวิร์กสเตชันของผู้คนเพียงแค่เมาท์ NFS /opt
และ/usr/local/
จากเซิร์ฟเวอร์กลางและติดตั้งสิ่งต่าง ๆ ที่นั่น)
ก่อนที่สิ่งต่าง ๆ เช่น. NET และ Java ความสามารถในการพกพาไบนารีจริงผ่านสถาปัตยกรรมซีพียูที่แตกต่างกันเป็นไปไม่ได้ วัฒนธรรม Unix ได้รับการพัฒนาด้วยความสามารถในการ source-portability ซึ่งเป็นค่าเริ่มต้นด้วยเหตุนี้ด้วยความพยายามเพียงเล็กน้อยในการพยายามเปิดใช้งาน binary-portability ยกตัวอย่างเช่นPOSIX ( Unix มาตรฐานหลัก) เพียงความพยายามที่จะสร้างมาตรฐานแหล่งพกพาแม้ในรุ่นล่าสุด
ปัจจัยทางวัฒนธรรมที่เกี่ยวข้อง: AT&T Unix เชิงพาณิชย์ก่อนกำหนดมาพร้อมกับซอร์สโค้ด (บนเทป) คุณไม่ต้องสร้างระบบจากแหล่งที่มามันมีอยู่ในกรณีที่คุณต้องการดูว่ามีอะไรบางอย่างที่ใช้งานได้จริงเมื่อเอกสารไม่เพียงพอ
Wikipedia พูดว่า :
"นโยบาย Unix ของเอกสารออนไลน์ที่กว้างขวางและ (เป็นเวลาหลายปี) การเข้าถึงซอร์สโค้ดของระบบทั้งหมดทำให้เกิดความคาดหวังของโปรแกรมเมอร์และสนับสนุนการเปิดตัวซอฟต์แวร์เสรีในปี 1983"
ฉันไม่แน่ใจว่าสิ่งใดกระตุ้นการตัดสินใจนี้เนื่องจากการให้ลูกค้าสามารถเข้าถึงซอร์สโค้ดของซอฟต์แวร์เชิงพาณิชย์นั้นไม่เคยได้ยินมาก่อน เห็นได้ชัดว่ามีอคติทางวัฒนธรรมยุคแรก ๆ ในทิศทางนี้ แต่อาจเติบโตมาจากรากของ Unix ในฐานะที่เป็นระบบปฏิบัติการพกพาที่เขียนส่วนใหญ่ใน C (ไม่ใช่ภาษาแอสเซมบลี) ที่สามารถรวบรวมสำหรับฮาร์ดแวร์ที่แตกต่างกัน ฉันคิดว่าหลาย OS ก่อนหน้านี้มีโค้ดที่เขียนเป็น asm สำหรับ CPU ที่เฉพาะเจาะจงดังนั้นการพกพาระดับซอร์สจึงเป็นจุดแข็งจุดหนึ่งของ Unix ในช่วงต้น (ฉันอาจจะผิดเกี่ยวกับเรื่องนี้ฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับ Unix ยุคแรก แต่ Unix และ C เกี่ยวข้องกัน)
การกระจายซอฟต์แวร์ในรูปแบบของแหล่งกำเนิดเป็นวิธีที่ง่ายที่สุดในการทำให้ผู้คนปรับตัวเข้ากับระบบใดก็ได้ที่พวกเขาต้องการให้ทำงาน (ไม่ว่าจะเป็นผู้ใช้หรือผู้ใช้บรรจุภัณฑ์สำหรับ Linux distro) หากซอฟต์แวร์ได้รับการบรรจุโดย / เพื่อจำหน่ายผู้ใช้ขั้นปลายสามารถใช้ซอฟต์แวร์นั้นได้
แต่มันมากเกินไปที่จะคาดหวังว่าผู้เขียนแพ็คเกจส่วนใหญ่จะสร้างไบนารีสำหรับทุกระบบที่เป็นไปได้ โครงการสำคัญบางโครงการมีไบนารีสำหรับกรณีทั่วไปบางกรณี (โดยเฉพาะอย่างยิ่ง x86 / windows ที่ระบบปฏิบัติการไม่ได้มาพร้อมกับสภาพแวดล้อมการสร้างและผู้จำหน่ายระบบปฏิบัติการได้ให้ความสำคัญกับการกระจายตัวติดตั้งแบบไบนารีเท่านั้น)
ได้รับชิ้นส่วนของซอฟต์แวร์ที่จะทำงานในระบบที่แตกต่างจากที่ผู้เขียนนำมาใช้ก็อาจจะต้องมีการเปลี่ยนแปลงเล็ก ๆ น้อย ๆ ซึ่งเป็นเรื่องง่ายที่มีแหล่งที่มา โปรแกรมที่ใช้ครั้งเดียวขนาดเล็กที่มีคนเขียนถึงรอยขีดข่วนคันของตัวเองอาจไม่เคยทดสอบในระบบที่คลุมเครือมากที่สุด การมีแหล่งที่มาทำให้สามารถทำการเปลี่ยนแปลงดังกล่าวได้ ผู้เขียนดั้งเดิมอาจมองข้ามบางสิ่งบางอย่างหรือเขียนโค้ดแบบพกพาน้อยลงเพราะช่วยประหยัดเวลาได้มาก แม้แต่แพ็คเกจใหญ่ ๆ อย่างInfo-ZIPก็ยังไม่มีผู้ทดสอบในทุกแพลตฟอร์มในทันทีและต้องการคนที่จะส่งแพตช์พกพาของพวกเขาเนื่องจากปัญหาถูกค้นพบ
(มีชนิดอื่น ๆ ของปัญหาการพกพาระดับแหล่งที่เกิดขึ้นเพียงเพราะความแตกต่างในการสร้าง env และไม่ได้จริงๆที่เกี่ยวข้องกับปัญหาที่นี่. ด้วย Java แบบพกพาไบนารีอัตโนมัติเครื่องมือ (มีautoconf
/ auto-make
) และสิ่งที่คล้ายกันเช่นcmake
wouldn ไม่จำเป็นและเราจะไม่มีสิ่งต่าง ๆ เหมือนบางระบบที่ต้องการการรวม<netinet/in.h>
แทนที่จะ<arpa/inet.h>
เป็นntohl(3)
(และบางทีเราอาจไม่มีntohl()
หรือสั่งไบต์อื่น ๆ ในตอนแรก!)
ฉันพัฒนาเป็นภาษา. NET เป็นประจำดังนั้นฉันจึงไม่รู้คอมพิวเตอร์
รวบรวมหนึ่งครั้งรันที่ใดก็ได้เป็นหนึ่งในเป้าหมายสำคัญของ. NET และ Java ดังนั้นจึงเป็นธรรมที่จะกล่าวว่าภาษาทั้งหมดได้รับการคิดค้นในความพยายามที่จะแก้ปัญหานี้และประสบการณ์ dev ของคุณอยู่กับหนึ่งในนั้น ด้วย .NET, วิ่งไบนารีของคุณในสภาพแวดล้อมรันไทม์แบบพกพา (CLR) Java เรียกมันว่าสภาพแวดล้อมรันไทม์โปรแกรม Java Virtual Machine คุณจะต้องแจกจ่ายหนึ่งไบนารีที่จะทำงานบนระบบใด ๆ (อย่างน้อยระบบใด ๆ ที่มีคนนำ JVM หรือ CLR ไปใช้แล้ว) คุณยังสามารถมีปัญหาการพกพาเช่น/
VS \
แยกเส้นทางหรือวิธีการพิมพ์หรือ GUI รูปแบบรายละเอียดของหลักสูตร
จำนวนมากของซอฟต์แวร์ที่เขียนในภาษาที่มีการรวบรวมอย่างเต็มที่ในรหัสพื้นเมือง ไม่มี.net
หรือ java bytecode เพียงรหัสเครื่องพื้นเมืองสำหรับซีพียูที่จะทำงานในการจัดเก็บในรูปแบบไฟล์ปฏิบัติการที่ไม่ใช่แบบพกพา C และ C ++ เป็นตัวอย่างที่สำคัญของเรื่องนี้โดยเฉพาะในโลกของ Unix เห็นได้ชัดว่านี่หมายความว่าต้องมีการรวบรวมไบนารีสำหรับสถาปัตยกรรม CPU เฉพาะ
รุ่นห้องสมุดมีปัญหาอื่น ไลบรารีสามารถและทำให้ API ระดับต้นทางคงที่ในขณะที่เปลี่ยน ABI ระดับไบนารี (ดูความแตกต่างระหว่าง API และ ABI ) ตัวอย่างเช่นการเพิ่มสมาชิกรายอื่นไปstruct
ยังทึบแสงยังคงเปลี่ยนขนาดของมันและต้องมีการคอมไพล์ใหม่ด้วยส่วนหัวสำหรับเวอร์ชันไลบรารี่ใหม่สำหรับรหัสใด ๆ ที่จัดสรรพื้นที่สำหรับโครงสร้างดังกล่าว ), สแตติก (โกลบอล) หรืออัตโนมัติ (โลคัลบนสแต็ก)
ระบบปฏิบัติการก็มีความสำคัญเช่นกัน รสชาติที่แตกต่างกันของระบบปฏิบัติการยูนิกซ์สำหรับซีพียูสถาปัตยกรรมเดียวกันอาจมีรูปแบบไฟล์ไบนารีที่แตกต่างกัน ABI ที่แตกต่างกันสำหรับการโทรระบบและค่าตัวเลขที่แตกต่างกันสำหรับค่าคงที่เช่น'sfopen(3)
,O_RDONLY
O_APPEND
O_TRUNC
,
หมายเหตุว่าแม้ไบนารีเชื่อมโยงแบบไดนามิกยังคงมีรหัสเริ่มต้น OS main()
เฉพาะบางอย่างที่วิ่งก่อน บน Windows crt0
นี้เป็น Unix และ Linux มีสิ่งเดียวกันโดยที่โค้ด C-Runtime Startup บางตัวเชื่อมโยงแบบคงที่กับทุกไบนารี ฉันเดาในทางทฤษฎีว่าคุณสามารถออกแบบระบบที่โค้ดนั้นถูกเชื่อมโยงแบบไดนามิกเช่นกันและเป็นส่วนหนึ่งของ libc หรือตัวเชื่อมโยงแบบไดนามิกตัวเอง แต่นี่ไม่ใช่วิธีการที่สิ่งต่าง ๆ ใช้งานได้จริงในระบบปฏิบัติการใด ๆ ที่จะแก้ปัญหาการเรียกระบบ ABI ไม่ใช่ปัญหาของค่าตัวเลขสำหรับค่าคงที่สำหรับฟังก์ชันไลบรารีมาตรฐาน (โดยปกติการเรียกระบบจะทำผ่านฟังก์ชั่น libc wrapper: ไบนารี x86-64 Linux ปกติสำหรับแหล่งที่ใช้mmap()
จะไม่รวมsyscall
คำสั่งเพียงcall
คำสั่งฟังก์ชั่น libc wrapper ในชื่อเดียวกัน
นี่เป็นส่วนหนึ่งของสาเหตุที่คุณไม่สามารถเรียกใช้ไบนารี i386-FreeBSD บน i386-Linux เคอร์เนล Linux มีเลเยอร์ความเข้ากันได้กับการเรียกใช้ระบบฉันคิดว่าอย่างน้อยหนึ่ง BSD สามารถเรียกใช้ Linux ไบนารีด้วยเลเยอร์ที่คล้ายกัน แต่แน่นอนว่าคุณต้องมีไลบรารีของ Linux)
หากคุณต้องการที่จะแจกจ่ายไบนารีที่คุณจะต้องให้แยกหนึ่งสำหรับการรวมกันของ CPU
ย้อนกลับไปในยุค '80s /' 90s มี CPU หลายประเภทที่ใช้กันทั่วไปสำหรับระบบ Unix (MIPS, SPARC, POWER, PA-RISC, m68k, ฯลฯ ) และ Unix (IRIX, SunOS) Solaris, AIX, HP-UX, BSD, ฯลฯ )
และนี่เป็นเพียงUnixระบบ ซอร์สแพ็กเกจจำนวนมากจะคอมไพล์และทำงานบนระบบอื่นเช่น VAX / VMS, MacOS (m68k และ PPC), Amiga, PC / MS-DOS, Atari ST เป็นต้น
ยังคงมีสถาปัตยกรรมซีพียูและระบบปฏิบัติการจำนวนมากแม้ว่าตอนนี้เดสก์ท็อปส่วนใหญ่จะมี x86 ที่รันหนึ่งในสามระบบปฏิบัติการหลัก
ดังนั้นจึงมีการรวมกันของ CPU / OS มากกว่าที่คุณสามารถสั่นคลอนได้แม้กระทั่งก่อนที่คุณจะเริ่มคิดถึงการพึ่งพาไลบรารีของบุคคลที่สามที่อาจเป็นเวอร์ชั่นที่แตกต่างกันในระบบที่แตกต่างกัน (สิ่งใดก็ตามที่ไม่ได้จัดทำโดยผู้จำหน่ายระบบปฏิบัติการจะต้องถูกติดตั้งด้วยมือ)
พา ธ ใด ๆ ที่รวบรวมไว้ในไบนารี่นั้นเป็นระบบเฉพาะเช่นกัน (สิ่งนี้จะช่วยประหยัด RAM และเวลาเมื่อเทียบกับการอ่านจากไฟล์กำหนดค่าเมื่อเริ่มต้น) ระบบปฏิบัติการ Unix โรงเรียนเก่ามักจะมีจำนวนมากของสิ่งที่มือที่กำหนดเองเพื่อให้มีวิธีการที่คุณสามารถทำให้สมมติฐานที่ถูกต้องเกี่ยวกับสิ่งที่ไม่มี
การกระจายไบนารีนั้นเป็นไปไม่ได้อย่างสมบูรณ์สำหรับ Unix โรงเรียนเก่ายกเว้นโครงการเชิงพาณิชย์ที่สำคัญที่สามารถสร้างและทดสอบกับชุดค่าผสมที่สำคัญทั้งหมด
แม้แต่การสร้างไบนารีเพื่อความยุติธรรมi386-linux-gnu
และamd64-linux-gnu
ยาก เวลาและความพยายามมากได้รับการใช้จ่ายในสิ่งที่ต้องการLinux ฐานมาตรฐานที่จะทำให้ไบนารีแบบพกพาไปได้ แม้แต่การเชื่อมโยงไบนารีแบบคงที่ก็ไม่ได้แก้ปัญหาทุกอย่าง (เช่นโปรแกรมประมวลผลคำควรพิมพ์บนระบบ RedHat กับระบบ Debian อย่างไรการติดตั้งควรเพิ่มผู้ใช้หรือกลุ่มสำหรับ daemon และจัดการสคริปต์เริ่มต้นให้ทำงานหลังจากรีบูตทุกครั้งหรือไม่) ตัวอย่างเนื่องจากการคอมไพล์ซ้ำจากแหล่งที่มาไม่สามารถแก้ปัญหาได้
นอกจากนั้นในความทรงจำของวันกลับมีค่ามากกว่าตอนนี้ การออกคุณสมบัติเสริมที่รวบรวมเวลาสามารถสร้างไบนารีที่เล็กลง (ขนาดรหัสน้อยลง) ซึ่งใช้หน่วยความจำน้อยกว่าสำหรับโครงสร้างข้อมูลของพวกเขา หากคุณสมบัติต้องการสมาชิกพิเศษในทุก ๆ อินสแตนซ์ของบางอย่างclass
หรือstruct
เพื่อติดตามบางสิ่งบางอย่างการปิดใช้งานคุณลักษณะนั้นจะลดขนาดอ๊อพเจ็กด้วย 4 ไบต์ (ตัวอย่าง) ซึ่งดีมากถ้าเป็นวัตถุที่โปรแกรมจัดสรร 100k
คุณสมบัติรวบรวมเวลาที่เป็นตัวเลือกวันนี้ส่วนใหญ่มักจะใช้เพื่อทำให้ไลบรารีเพิ่มเติมเป็นทางเลือก เช่นคุณสามารถรวบรวมffmpeg
ด้วยหรือไม่libx264
, libx265
, libvorbis
และห้องสมุดอื่น ๆ อีกมากมายสำหรับเฉพาะวิดีโอ / เข้ารหัสเสียงการจัดการคำบรรยาย, ฯลฯ เป็นต้นมากกว่าปกติหลายสิ่งที่สามารถรวบรวมโดยมีหรือไม่มีlibreadline
ถ้ามันใช้ได้เมื่อคุณเรียกใช้./configure
การ ผลไบนารีจะขึ้นอยู่กับห้องสมุดและให้แก้ไขบรรทัดแฟนซีเมื่ออ่านจาก terminal หากไม่เป็นเช่นนั้นโปรแกรมจะใช้การสนับสนุนการถอยกลับเพื่ออ่านบรรทัดจาก stdin ด้วยfgets()
หรือบางอย่าง)
บางโครงการยังคงใช้ฟีเจอร์เสริมเพื่อไม่ให้ใช้โค้ดที่ไม่ต้องการด้วยเหตุผลด้านประสิทธิภาพ เช่นลีนุกซ์เคอร์เนลสามารถสร้างได้โดยไม่รองรับ SMP (เช่นสำหรับระบบฝังตัวหรือเดสก์ท็อปโบราณ) ซึ่งในกรณีนี้การล็อคจำนวนมากนั้นง่ายกว่า หรือมีจำนวนมากคุณสมบัติเสริมอื่น ๆ ที่ส่งผลกระทบต่อบางส่วนของรหัสหลักไม่เพียงออกจากไดรเวอร์หรือคุณลักษณะฮาร์ดแวร์อื่น ๆ (แม้ว่าโค้งที่เฉพาะเจาะจงและตัวเลือกการกำหนดค่าฮาร์ดแวร์เฉพาะบัญชีสำหรับจำนวนมากของรหัสที่มาทั้งหมด. ดูทำไมลินุกซ์เคอร์เนล 15+ ล้านบรรทัดของรหัส? )