“ การเรียกของระบบ” มีความหมายอย่างไรหากไม่มีการใช้งานในภาษาโปรแกรม


14

ฉันต้องการที่จะเข้าใจคำว่า "การเรียกระบบ" ฉันคุ้นเคยกับการเรียกใช้ระบบเพื่อรับบริการเคอร์เนลจากแอปพลิเคชัน userspace

ส่วนที่ฉันต้องการชี้แจงด้วยคือความแตกต่างระหว่าง "การเรียกระบบ" และ "การใช้งาน C ของการเรียกระบบ"

นี่คือข้อความที่ทำให้ฉันสับสน:

บนระบบที่คล้าย Unix API นั้นมักจะเป็นส่วนหนึ่งของการใช้งาน C library (libc) เช่น glibc ซึ่งมีฟังก์ชั่น wrapper สำหรับการโทรของระบบซึ่งมักจะตั้งชื่อเหมือนกับการเรียกระบบที่พวกเขาเรียก

"การเรียกระบบที่พวกเขาเรียก" คืออะไร? แหล่งของพวกเขาอยู่ที่ไหน ฉันสามารถรวมพวกเขาโดยตรงในรหัสของฉัน?

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

บันทึกพื้นหลัง: /devฉันพยายามที่จะเข้าใจถ้าในท้ายที่สุดแต่ละฟังก์ชั่นคปลายขึ้นโต้ตอบกับอุปกรณ์จาก

คำตอบ:


21

สายระบบต่อ seเป็นแนวคิด พวกเขาแสดงถึงการกระทำที่กระบวนการสามารถขอเคอร์เนลเพื่อดำเนินการ

การเรียกระบบเหล่านั้นถูกนำไปใช้ในเคอร์เนลของระบบที่คล้าย UNIX การนำไปใช้งานนี้ (เขียนเป็น C และใน asm สำหรับชิ้นส่วนเล็ก ๆ ) ทำการดำเนินการในระบบ

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

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

ดังนั้นการเรียกระบบคือ:

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

1
คุณมีตัวอย่างของ "ฟังก์ชั่นเครื่องห่อหุ้ม" และการเรียกระบบจริงหรือไม่? (พา ธ ไฟล์ใน Linux หรือลิงก์ไปยังแหล่งที่มา)
TheMeaningfulEngineer

3
ตัวอย่างเช่นนี้คือการดำเนินงานของgetpidสายระบบในลินุกซ์เคอร์เนล: lxr.free-electrons.com/source/kernel/timer.c?v=2.6.35#L1337 และนี่คือฟังก์ชั่นเสื้อคลุมในห้องสมุดมาตรฐาน GNU C glibc-2.19: fossies.org/dox/glibc-2.19/...
lgeorget

@Igeorget: ลิงก์ของคุณไม่ทำงานอีกต่อไป การเชื่อมโยงการปรับปรุงสำหรับการดำเนินงานเคอร์เนล: github.com/torvalds/linux/blob/... ฉันไม่พบสิ่งที่ glibc ทำในวันนี้รหัสนั้นเป็นไปไม่ได้ที่จะนำทาง
rchard2scout

6

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

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

ระบบ Unixy เสนออินเตอร์เฟส POSIX มากกว่าหรือน้อยกว่าโดยตรงในขณะที่การเรียกระบบ โดยทั่วไปจะมีวิธีเรียกใช้การเรียกของระบบโดยตรงค้นหาsyscall(2)รายละเอียดเกี่ยวกับวิธีใช้สิ่งอำนวยความสะดวกนี้ใน Linux


1
คุณสัมผัสกับจุดสำคัญที่คำตอบอื่น ๆ แค่ขัดขืน ฟังก์ชั่นใด ๆ ที่เป็นโปรแกรมเมอร์ที่มีความสามารถพอสมควรสามารถเขียนให้กับตัวเอง (เช่นstrlen, strcpy, sqrtและqsort) สามารถและอาจจะอยู่ในพื้นที่ของผู้ใช้, โหลดจากห้องสมุด (ส่วนใหญ่ libc; ฟังก์ชั่นทางคณิตศาสตร์เช่นsqrtและฟังก์ชันตรีโกณมิติและไฮเปอร์โบลิอาจอยู่ใน libm, ห้องสมุดคณิตศาสตร์) ... (ต่อ)
สกอตต์

1
(ต่อ) ... แต่มีวิธีที่ผู้ใช้สามารถเขียนของตัวเองไม่fork, killหรือopenฟังก์ชั่นเพราะสิ่งเหล่านี้ต้องการการเข้าถึงพื้นที่เคอร์เนลของระบบปฏิบัติการหน่วยความจำ (เช่นตารางกระบวนการ) หรือคำแนะนำที่ได้รับการยกเว้น (เช่น I / O) ดังนั้นรหัสที่ทำหน้าที่เหล่านี้จะต้องอยู่ในเคอร์เนลระบบปฏิบัติการ ดังนั้นฟังก์ชั่นระบบหรือการเรียกระบบ
สกอตต์

5

แน่นอนว่าเรามาดูกันว่าวิธีนี้มีหลายทิศทางที่เราสามารถมองเห็นได้หรือไม่? สิ่ง.

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

เมื่ออยู่ในโค้ดของระบบปฏิบัติการแล้วจะมีภาพสะท้อนในกระจกที่คลี่คลายของสิ่งเฉพาะเครื่องที่ผู้ใช้รันไทม์ทำแล้วจึงเรียกรูทีนย่อยธรรมดาอย่างสมบูรณ์แบบ
หากคุณต้องการที่จะเห็นว่าวิธีการทำงานในระบบปฏิบัติการเต็มรูปแบบดึงแหล่งเคอร์เนล ( git clone https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/) git grep -i system\ callและทำเช่น ดึงแหล่ง glibc และทำเช่นเดียวกัน


จริง แต่คุ้ยหาไปรอบ ๆ ในลินุกซ์หรือ glibc เป็นบิตด้านหนัก ...
vonbrand

3

ใน Linux อย่างน้อยกลไกการโทรของระบบจะทำงานภายใต้สถาปัตยกรรมส่วนใหญ่โดยการวางข้อมูลที่จัดรูปแบบเฉพาะบางอย่าง

ปัญหาเกิดขึ้นจริง ๆ แล้วบังคับให้ CPU ทำการสลับเข้าไปในพื้นที่ของเคอร์เนลเพื่อให้สามารถเรียกใช้รหัสเคอร์เนลที่มีสิทธิพิเศษในการให้บริการการโทร สิ่งนี้ทำได้โดยการบังคับให้เกิดความผิดพลาดบางอย่าง (ความผิดพลาดจะถูกหารด้วย 0, โอเวอร์โฟลว์ที่ไม่ได้กำหนดหรือ segfault, ฯลฯ ) สิ่งนี้บังคับให้เคอร์เนลประมวลผลเพื่อจัดการข้อผิดพลาด

โดยปกติเคอร์เนลจะจัดการกับข้อผิดพลาดโดยการฆ่ากระบวนการที่เป็นสาเหตุหรือเรียกใช้ตัวจัดการที่ผู้ใช้ระบุ อย่างไรก็ตามในกรณีของ syscall มันจะทำการตรวจสอบรีจิสเตอร์และตำแหน่งหน่วยความจำที่กำหนดไว้ล่วงหน้าแทนและหากมีการร้องขอ syscall ก็จะเรียกใช้โดยใช้ข้อมูลที่ได้รับจากกระบวนการผู้ใช้ในโครงสร้างหน่วยความจำ สิ่งนี้มักจะต้องทำด้วยชุดประกอบที่ทำขึ้นด้วยมือบางอย่างและเพื่อความสะดวกในการใช้ syscall สำหรับผู้ใช้ไลบรารี C ของระบบจะต้องห่อเป็นฟังก์ชัน สำหรับอินเทอร์เฟซระดับต่ำกว่าโปรดดูhttp://man7.org/linux/man-pages/man2/syscall.2.htmlสำหรับข้อมูลบางอย่างเกี่ยวกับวิธีการทำงานของ syscalls และวิธีการเรียกใช้โดยไม่ใช้ตัวคลุม C

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

แก้ไข: หมายเหตุเกี่ยวกับความคิดเห็นของคุณเกี่ยวกับสิ่งต่าง ๆ ใน / dev / นี่เป็นอินเทอร์เฟซระดับที่สูงขึ้นกับเคอร์เนลไม่ใช่อันที่ต่ำกว่า อุปกรณ์เหล่านี้ใช้ syscalls (ประมาณ) 4 อันภายใต้ การเขียนถึงพวกเขาเหมือนกับการเขียน syscall การอ่านการอ่าน syscall เปิด / ปิดพวกเขาเทียบเท่ากับการเปิดและปิด syscalls และการเรียกใช้ ioctl ทำให้ ioctl พิเศษ iyscal ซึ่งในตัวเองเป็นอินเตอร์เฟซในการเข้าถึงหนึ่งใน ioctl หลายระบบ การโทร (พิเศษโดยปกติจะเป็นการโทรเฉพาะอุปกรณ์ที่มีการใช้งานแคบเกินไปที่จะเขียน syscall ทั้งหมดสำหรับพวกเขา)


1

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


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