Linux OS Architecture
Linux Kernel และ Shell Architecture
Last updated
Linux Kernel และ Shell Architecture
Last updated
Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University
ตั้งแต่ที่ Andrew Tanenbaum ได้สร้าง Microkernel (อ่านรายละเอียดของ Linux Kernel เพิ่มเติม) version of UNIX® ที่เรียกขานกันว่า "MINIX" (for minimal UNIX) สำหรับให้สามารถใช้งานได้บนเครื่องคอมพิวเตอร์ส่วนบุคคลขนาดเล็ก ทำให้ Linus Torvalds เริ่มปล่อย kernel source codes ตั้งแต่นั้นมา (early 1990s)
โครงสร้างพื้นฐานภายในระบบปฏิบัติการลีนุกซ์ซึ่งมีเคอร์เนลเป็นตัวเชื่อมโยงกลางระหว่างโปรแกรมระบบ และระบบฮาร์ดแวร์ ซึ่งเคอร์เนลนั้นจะถูกห่อหุ้มโดยเชลล์ (Shell) ที่มีด้วยกัน 2 ส่วนคือ CLI (Command Line Interface) และ GUI (Graphic User Interface) ส่วนชั้นนอกสุดจะเป็นส่วนโปรแกรมสำหรับผู้ใช้ดังแสดงในรูปข้างล่าง
จากรูปโครงสร้างสถาปัตยกรรมของระบบปฏิบัติการลีนุกซ์ข้างล่าง ส่วนของชั้นบนสุดจะเป็นส่วนของโปรแกรมประยุกต์ต่างๆสำหรับให้ผู้ใช้ได้เรียกใช้งานได้ ซึ่งสามารถเรียกไปยังเคอร์เนลได้ 2 ทางคือผ่าน GNU C Library และเรียกตรงไปยัง System Call Interface (SCI) โดยที่โปรแกรมสำหรับผู้ใช้ และ GNU C Library นั้นจะอยู่ในพื้นที่ส่วนของผู้้ใช้ที่เรียกว่า User Space
ในส่วนของพื้นที่ที่สำคัญมากอีกส่วนคือ Kernel Space ซึ่งประกอบไปด้วย SCI, เคอร์เนล และส่วนเคอร์เนลที่ขึ้นอยู่กับชนิดของสถาปัตยกรรมนั้นๆ เรียกกันว่า Board Support Package (BSP) โดยตัว SCI จะมีบทบาทสำคัญที่เป็นตัวกลางให้กับโปรแกรมประยุกต์ต่างๆ รวมทั้ง C Library ทั้งหมดเพื่อรองรับการเรียกใช้เคอร์เนลของระบบในการขอเข้าถึงระบบฮาร์ดแวร์ต่างๆ
ตัวอย่างการทำงานเช่นเมื่อผู้ใช้ต้องการจะเปิดอ่านไฟล์ที่ถูกเก็บอยู่ใน USB Storage ผู้ใช้ก็จะทำการเรียกใช้โปรแกรมประยุกต์ตัวหนึ่งขึ้นมา โดยภายในโปรแกรมประยุกต์นั้นจะต้องเรียกใช้ฟังก์ชัน read/write ไฟล์ที่เป็นฟังก์ชันภายใน GNU C Library ซึ่งจะเรียกตรงไปยังฟังก์ชันภายใน System Call อีกต่อนึง เมื่อต้องการเปิดไฟล์ที่ถูกเก็บอยู่ใน USB Storage ตัวเคอร์เนลก็ต้องรู้วิธีการเข้าถึงระบบไฟล์ (File System) ที่ USB Storage นั้นใช้อยู่ เช่น FAT32 ดังนั้นตัวคอร์เนลจะต้องใช้ฟังก์ชันไดรเวอร์ภายในเคอร์เนลเพื่อเข้าถึงไฟล์ตามรูปแบบมาตราฐานโปรโตคอลของในระบบไฟล์ชนิด FAT32
จากโครงสร้างข้างต้น แต่ละชั้นมีรายละเอียดดังนี้
Hardware Layer - อุปกรณ์ฮาร์ดแวร์ภายในบอร์ด ตัวอย่างเช่น หน่วยประมวลผลขนาด 32 บิตขึ้นไป หน่วยจัดการหน่วยความจำ (MMU - Memory Management Unit) หน่วยความจำขนาดเล็ก (RAM) หน่วยความจำแบบอ่านได้อย่างเดียว (ROM) ตัวบันทึกข้อมูลประเภทแฟลต เช่น MMC/SD Card เป็นต้น
Linux Kernel Layer (Kernel-space) - ทำหน้าที่ควบคุมจัดการอุปกรณ์ฮาร์ดแวร์ทั้งหมด จัดการการจัดคิวของโปรเซสต่างๆ จัดเตรียมฟังก์ชันสำคัญ (System Calls) ให้กับโปรแกรมประยุกต์ เป็นต้น ซึ่งจะมีองค์ประกอบภายในที่มีหน้าที่สำคัญๆ ได้แก่
Low-level interfaces
จัดเตรียมชุด APIs (Application Programming Interface) สำหรับการติดต่อกับฮาร์ดแวร์ แบบที่ไม่ขึ้นอยู่กับรุ่นของฮาร์ดแวร์
เป็นส่วนดูแลและจัดการฮาร์ดแวร์ต่างๆเช่น การทำงานของหน่วยประมวลผลกลาง การทำงานของหน่วยความจำ ติดต่อกับพอร์ตสื่อสาร และ I/O Devices เป็นต้น
High-level abstractions
จะจัดเตรียมฟังก์ชันให้โปรแกรมประยุกต์สามารถสื่อสารระหว่างกันได้ และทำงานแบบ multi-tasking ได้ เช่น IPC, Threading, Socket, Signalling เป็นต้น
โค้ดโปรแกรมส่วนใหญ่สามารถนำไปใช้ต่อได้เกือบทุกสถาปัตยกรรม
Filesystems
สามารถรองรับระบบ filesystems ต่างๆที่มีอยู่ในปัจจุบันได้ไม่น้อยกว่า 40 ชนิด
จะมี Virtual Filesystem layer ที่ทำให้การเรียกใช้ filesystems ที่แตกต่างเหล่านั้นง่ายและสะดวกขึ้นโดยที่ไม่ต้องเขียนโค้ดใหม่
Networking protocols
รองรับโปรโตคอลมาตราฐานต่างๆที่ใช้กันอยู่ในปัจจุบันได้ไม่น้อยกว่า 50 ชนิด
มีฟังก์ชัน Socket APIs ที่ใช้ในการจัดการและกำหนดการเชื่อมต่อในแต่ละแบบของระบบเครือข่ายนั้นๆ
Libraries (User-space) - ไลบรารีที่อยู่ในระดับของ user space ที่มีความหลากหลายมากกว่าที่มีอยู่ในเคอร์เนล ไม่ว่าจะเป็นไลบรารีทางด้านการคำนวณ การแสดงผลกราฟฟิก การประมวลผลข้อมูลดิจิตอล การสื่อสารข้อมูลผ่านระบบเครือข่าย การเข้ารหัส/ถอดรหัส และ การติดต่อกับอุปกรณ์ฮาร์ดแวร์ที่มาเชื่อมต่อกับบอร์ด เป็นต้น ดังนั้นถ้าโปรแกรมประยุกต์ต้องการจะติดต่อกับเคอร์เนลจะเรียกผ่านไลบรารีชื่อว่า glibc (ซึ่งประกอบไปด้วยตัวย่อยคือ uClibc และ eglibc)
Shells หรือตัวแปลคำสั่ง มีประวัติอันยาวนาน แต่ในเนื้อหานี้เราจะเริ่มต้นด้วย shell แรกของ UNIX® ที่ Ken Thompson (จาก Bell Labs) พัฒนาขึ้นเรียกว่า V6 shell
ในปี 1971 ซึ่งเหมือนกับลำดับก่อนหน้าใน Multics shell นี้ (/bin/sh
) เป็นโปรแกรมผู้ใช้ที่เป็นอิสระที่ดำเนินการอยู่นอกเคอร์เนล แนวคิดเช่น Globbing เป็นเทคนิคที่ใช้ในการระบุหนึ่งหรือหลายไฟล์ด้วยแพทเทิร์น ส่วนใหญ่ใช้ในกรณีที่ผู้ใช้ไม่ต้องการหรือไม่สามารถระบุแต่ละไฟล์ได้โดยตรง สัญลักษณ์ที่ใช้ในการ globbing สามารถแตกต่างกันไปตามระบบปฏิบัติการ แต่ในระบบปฏิบัติการที่ใช้ Unix เช่น Linux หรือ macOS ประกอบด้วย:
*
(ดาว): ตรงกับศูนย์หรือมากกว่ารายการที่มีอยู่
?
(เครื่องหมายคำถาม): ตรงกับตัวอักษรเดียว
[]
(สแควร์บราเก็ต): ตรงกับตัวอักษรใดตัวอักษรหนึ่งที่อยู่ในสแควร์บราเก็ต
ตัวอย่างการใช้ globbing:
*.txt
: สั่งให้ระบบทำงานกับไฟล์ทั้งหมดที่มีนามสกุล .txt
data?
: สั่งให้ระบบทำงานกับไฟล์ที่ชื่อขึ้นต้นด้วย "data" และตามด้วยตัวอักษรอื่นๆ ตัวเดียว
data[0-9]
: สั่งให้ระบบทำงานกับไฟล์ที่ชื่อขึ้นต้นด้วย "data" และตามด้วยตัวเลข 0-9 อันใดอันหนึ่ง
การใช้ globbing ทำให้การจัดการไฟล์ต่างๆ ที่มีลักษณะที่คล้ายคลึงกันเป็นเรื่องง่ายขึ้นโดยสามารถระบุเป็นกลุ่ม ทำให้ไม่จำเป็นต้องระบุชื่อไฟล์ที่แน่นอนทุกครั้ง ทำให้การทำงานมีความรวดเร็วและมีประสิทธิภาพมากขึ้น โดยแนคิดนี้จึงถูก implement ในโปรแกรม utility ที่เรียกว่า glob
เช่นเดียวกับคำสั่ง if
สำหรับการประเมินนิพจน์เงื่อนไข การแยกส่วนนี้ทำให้ shell มีขนาดเล็ก ที่เขียนด้วยภาษา C ต่ำกว่า 900 บรรทัด
Shell นำเสนอไวยากรณ์ที่สั้นกระชับสำหรับการเปลี่ยนทาง (< > และ >>) และการท่อ (| หรือ ^) ที่ยังคงมีอยู่ใน shell สมัยใหม่ คุณยังพบการสนับสนุนการเรียกใช้คำสั่งที่ต่อเนื่อง (ด้วย ;) และคำสั่งที่ไม่ประสานกัน (ด้วย &)
สิ่งที่ขาดหายไปใน shell ของ Thompson คือความสามารถในการเขียนสคริปต์ จุดประสงค์เดียวของมันคือเป็น shell แบบโต้ตอบ (ตัวแปลคำสั่ง) เพื่อเรียกใช้คำสั่งและดูผลลัพธ์
ตั้งแต่ที่ Thompson Shell เกิดขึ้น แต่คนก็พยายามหา shell ยุคสมัยใหม่อย่าง Bourne shell ที่เกิดขึ้นใน คศ. 1977 ซึ่งถูกสร้างโดย Stephen Bourne ที่ AT&T Bell Labs สำหรับ V7 UNIX และยังเป็น shell ที่มีประโยชน์ในปัจจุบัน (บางกลุ่มเรียกว่า root shell) ไวยากรณ์ (syntax) ของ Bourne shell จะมีความคล้ายคลึงกับ Algorithmic Language (ALGOL) มากกว่า shell อื่น ๆ
Bourne shell มีสองเป้าหมายหลักคือทำหน้าที่เป็นตัวแปลคำสั่งเพื่อใช้ในการเรียกใช้คำสั่งของระบบปฏิบัติการแบบโต้ตอบและสำหรับสคริปต์ (เขียนสคริปต์ที่สามารถใช้ซ้ำและเรียกใช้ผ่าน shell) นอกจากการแทนที่ shell ของ Thompson แล้ว Bourne shell ยังมีหลายข้อดีเหนือตัวอื่น ๆ โดยได้นำเสนอ control flows, loops, และ variables ลงในสคริปต์ ให้ภาษามีประสิทธิภาพมากขึ้นในการโต้ตอบกับระบบปฏิบัติการได้
สถาปัตยกรรมพื้นฐานของ hypothetical shell นั้นเรียบง่าย (ตามที่แสดงให้เห็นโดย shell ของ Bourne ในรูปข้างล่าง) โดยสถาปัตยกรรมพื้นฐานดูคล้ายกับ pipeline ที่ทำการวิเคราะห์และแยกส่วนข้อมูลที่ป้อนเข้ามา, สัญลักษณ์ (symbols) จะนำมาถูกขยายความ (เช่น การขยายและการแทนที่ brace, tilde, variable และ parameter, และการสร้างชื่อไฟล์) และในที่สุดคำสั่งจะถูกดำเนินการ (โดยใช้คำสั่งที่ต่อติดใน shell, หรือคำสั่งภายนอก)