การเรียกระบบ Linux คืออะไร?

What Is Linux System Call



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

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







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



ฝ่าอุปสรรคด้วย Linux System Calls

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



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





เนื่องจากลินุกซ์ปฏิบัติตามปรัชญาของ UNIX ว่าทุกอย่างคือไฟล์ ฟังก์ชันมากมายสามารถทำได้โดยการเปิดและอ่านหรือเขียนไปยังไฟล์ ซึ่งอาจเป็นอุปกรณ์ ตัวอย่างเช่น บน Windows คุณอาจใช้ฟังก์ชันที่เรียกว่า CryptGenRandom เพื่อเข้าถึงไบต์แบบสุ่ม แต่บน Linux สามารถทำได้โดยเพียงแค่เปิดไฟล์ /dev/urandom และอ่านไบต์จากไฟล์นั้นโดยใช้การเรียกระบบอินพุต/เอาท์พุตไฟล์มาตรฐาน ความแตกต่างที่สำคัญนี้ช่วยให้อินเทอร์เฟซการเรียกระบบง่ายขึ้น

Wafer-Thin Wrapper

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



เบื้องหลัง

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

โมฆะหลัก() {
}

นี่อาจเป็นโปรแกรม C ที่ไม่สำคัญที่สุดเท่าที่คุณเคยเห็น มันเพียงได้รับการควบคุมผ่านจุดเข้าหลักแล้วออกจาก มันไม่คืนค่าด้วยซ้ำเนื่องจาก main ถูกกำหนดให้เป็นโมฆะ บันทึกไฟล์เป็น ctest.c แล้วมาคอมไพล์กัน:

gcc ทดสอบ -thectest

เมื่อคอมไพล์แล้วเราจะเห็นขนาดไฟล์เป็น 8664 ไบต์ อาจแตกต่างกันเล็กน้อยในระบบของคุณ แต่ควรอยู่ที่ประมาณ 8k นั่นเป็นรหัสจำนวนมากเพียงเพื่อเข้าและออก! เหตุผลที่เป็น 8k คือมีการรวมรันไทม์ libc แม้ว่าเราจะถอดสัญลักษณ์ออก แต่ก็ยังมากกว่า 6k เล็กน้อย

ในตัวอย่างที่ง่ายกว่านี้ เราสามารถเรียกระบบ Linux เพื่อออก แทนที่จะขึ้นอยู่กับรันไทม์ C เพื่อทำสิ่งนั้นให้เรา

โมฆะ_เริ่ม() {
asm('ย้าย $1,%eax;'
'xorl % ebx,% ebx;'
'int $0x80');
}

ที่นี่เราย้าย 1 ไปที่การลงทะเบียน EAX ล้างการลงทะเบียน EBX (ซึ่งอาจมีค่าส่งคืน) จากนั้นเรียกระบบ Linux ขัดจังหวะ 0x80 (หรือ 128 เป็นทศนิยม) การขัดจังหวะนี้เรียกเคอร์เนลเพื่อประมวลผลการโทรของเรา

หากเรารวบรวมตัวอย่างใหม่ของเราที่เรียกว่า asmtest.c และแยกสัญลักษณ์ออกและไม่รวมไลบรารีมาตรฐาน:

gcc-NS-nostdlib asmtest -o asmtest

เราจะสร้างไบนารีที่น้อยกว่า 1k (ในระบบของฉัน มันให้ผลตอบแทน 984 ไบต์) รหัสส่วนใหญ่เป็นส่วนหัวที่สามารถเรียกใช้งานได้ ตอนนี้เรากำลังเรียกการเรียกระบบ Linux โดยตรง

เพื่อวัตถุประสงค์ในทางปฏิบัติทั้งหมด

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

วิธีการตั้งโปรแกรมบทช่วยสอนการโทรระบบ

รายการเรียกระบบทั้งหมด

หากคุณต้องการดูรายการการเรียกระบบที่มีอยู่ทั้งหมดสำหรับ Linux คุณสามารถตรวจสอบหน้าอ้างอิงเหล่านี้: รายการการเรียกระบบทั้งหมดบน LinuxHint.com, filippo.io/linux-syscall-table/ และหรือ syscalls.kernelgrok.com