ทำไม Linux module API ไม่เข้ากันได้แบบย้อนหลัง?

Aug 18 2020

เหตุใด Linux module API จึงเข้ากันไม่ได้ ฉันผิดหวังที่พบไดรเวอร์ที่อัปเดตหลังจากอัปเดตเคอร์เนล Linux

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

คำตอบ

4 PhilipCouling Aug 18 2020 at 21:28

Greg Kroah-Hartman เขียนในหัวข้อนี้ที่นี่: https://www.kernel.org/doc/html/v4.10/process/stable-api-nonsense.html

นอกเหนือจากรายละเอียดทางเทคนิคบางอย่างเกี่ยวกับการรวบรวมรหัส C แล้วเขายังดึงประเด็นด้านวิศวกรรมซอฟต์แวร์พื้นฐานสองสามข้อมาใช้ในการตัดสินใจ


Linux Kernel คือมักจะเป็นงานในความคืบหน้า สิ่งนี้เกิดขึ้นจากหลายสาเหตุ:

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

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

เหตุใดจึงไม่ดูแลอินเทอร์เฟซเก่า

เพื่อให้แน่ใจว่าสามารถใช้งานร่วมกันได้แบบย้อนกลับจำเป็นต้องมีการบำรุงรักษาอินเทอร์เฟซเก่า (มักจะ "เสีย" และไม่ปลอดภัย) แน่นอนว่ามันเป็นไปได้ในทางทฤษฎีที่จะทำเช่นนี้ยกเว้นจะมีค่าใช้จ่ายจำนวนมาก

Greg Kroah-Hartman เขียน

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

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

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

เกี่ยวกับความสมดุล binning อินเตอร์เฟซที่เป็นจริงค่าใช้จ่ายที่มีประสิทธิภาพ(สำหรับนักพัฒนา kernel) หากคุณต้องการทราบว่าทำไมนักพัฒนาไม่ใช้เวลาหลายเดือนและหลายปีในการช่วยชีวิตคุณจากการจ่าย $ 10สำหรับอะแดปเตอร์ wifi ใหม่ ... นั่นคือเหตุผล จำไว้ว่าเวลา / คุ้มค่าสำหรับนักพัฒนาเคอร์เนลไม่จำเป็นต้องคุ้มทุนสำหรับคุณหรือผู้ผลิต

6 telcoM Aug 19 2020 at 21:11

แม้ว่าฉันจะสนับสนุนแพตช์ (เล็กน้อยมาก) ในเคอร์เนล Linux แต่ฉันก็ไม่นับว่าตัวเองเป็นนักพัฒนาเคอร์เนล อย่างไรก็ตามนี่คือสิ่งที่ฉันรู้:


โปรแกรมควบคุมที่เขียนขึ้นสำหรับเคอร์เนลเวอร์ชัน 2.6.0.0 ก่อนวันที่จะกำจัด Big Kernel Lock (BKL)ที่เกิดขึ้นในเคอร์เนลเวอร์ชัน 2.6.39

BKL ถูกสร้างขึ้นในตอนที่ Linux ยังคงเป็นระบบปฏิบัติการแบบ single-processor (single-core, single-thread) ทันทีที่มีการเพิ่มการรองรับ SMP นักพัฒนาก็รับรู้ว่า BKL กำลังจะกลายเป็นคอขวดขนาดใหญ่ในบางจุด แต่ตราบใดที่มีคอร์ / เธรดในระบบทั้งหมดเพียงไม่กี่คอร์มันก็ค่อนข้างทนได้ แต่สิ่งแรกกลายเป็นปัญหาที่แท้จริงสำหรับผู้ที่ใช้ Linux ในซูเปอร์คอมพิวเตอร์ดังนั้นงานจึงเริ่มแทนที่ทุกอย่างที่ต้องการ BKL ด้วยกลไกการล็อคที่ละเอียดยิ่งขึ้นหรือเมื่อใดก็ตามที่เป็นไปได้โดยใช้วิธีการแบบไม่ล็อค

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

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


เมื่อเร็ว ๆ นี้แพตช์ความปลอดภัย Spectre / Meltdown ได้ทำการเปลี่ยนแปลงครั้งใหญ่ในสิ่งที่ต้องเกิดขึ้นเมื่อมีการข้ามขอบเขตเคอร์เนล / พื้นที่ผู้ใช้ โมดูลใด ๆ ที่คอมไพล์ก่อนที่จะใช้โปรแกรมฟิกซ์ Spectre / Meltdown นั้นไม่สามารถเชื่อถือได้กับเคอร์เนล post-Specre / Meltdown

เมื่อสองสัปดาห์ก่อนฉันกำลังแก้ไขปัญหาเซิร์ฟเวอร์เก่าที่ต้องการการหมุนเวียนพลังงานด้วยตนเองเมื่อมีการใช้การอัปเดตความปลอดภัยโดยระบบอัตโนมัติ สิ่งนี้เคยเกิดขึ้นหลายครั้งก่อนหน้านี้และสามารถทำซ้ำได้ ฉันพบว่ามันมีmegasrไดรเวอร์หน่วยเก็บข้อมูลที่เป็นกรรมสิทธิ์เวอร์ชันเก่ามากก่อนแพตช์ Spectre / Meltdown ซึ่งไม่รวมอยู่ในการอัปเดตอัตโนมัติ หลังจากอัปเดตไดรเวอร์เป็นเวอร์ชันปัจจุบันปัญหาก็หายไป อย่างไรก็ตามนี่เป็นระบบ RHEL 6.10 ธรรมดา

ฉันยังเคยเห็นเซิร์ฟเวอร์หยุดทำงานเมื่อโหลดไดรเวอร์การตรวจสอบฮาร์ดแวร์ pre-Spectre / Meltdown ที่เป็นกรรมสิทธิ์ด้วยเคอร์เนล post-Spectre / Meltdown จากประสบการณ์นี้ฉันมั่นใจอย่างเต็มที่ว่าการแก้ไข Spectre / Meltdown จำเป็นต้องได้รับการปฏิบัติเป็นเหตุการณ์ลุ่มน้ำ: เคอร์เนลและโมดูลต้องเป็นเวอร์ชันก่อนการแก้ไขทั้งหมดหรือเวอร์ชันหลังการแก้ไขทั้งหมด การผสมและจับคู่จะนำไปสู่ความเศร้าโศกและการโทรปลุกเที่ยงคืนสำหรับระบบผู้ดูแลระบบที่กำลังโทร

และเนื่องจาก Spectre เป็นปัญหาระดับการออกแบบ CPUจึงเป็น "ของขวัญที่มอบให้": บางคนจะหาวิธีใหม่ ๆ ในการใช้ประโยชน์จากจุดอ่อนจากนั้นนักพัฒนาเคอร์เนลจะต้องหาวิธีปิดกั้นช่องโหว่


นี่เป็นเพียงปัญหาใหญ่สองประการที่ API โมดูลเคอร์เนลดั้งเดิมที่เข้ากันได้กับ 2.6.0.0 จะต้องแก้ไข ฉันมั่นใจว่ามีอีกหลายคน


แล้วก็มีด้านปรัชญามากขึ้น ลองคิดดู: อะไรทำให้ Linux เป็นไปได้?

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

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

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

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

ในความเป็นจริงความยุ่งยากพิเศษที่เกิดจากไดรเวอร์ไบนารีที่เป็นกรรมสิทธิ์ในการดีบักเคอร์เนลเป็นแรงจูงใจให้นักพัฒนาเคอร์เนลไม่สนใจเกี่ยวกับการพัฒนาไดรเวอร์ที่เป็นกรรมสิทธิ์: "พวกเขาทำให้งานของฉันยากขึ้นทำไมฉันควรทำอะไรเป็นพิเศษเพื่อให้ง่ายขึ้น?

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