[UNIX] การ fork process และโปรแกรม shell

Thanwa Jindarattana
2 min readSep 13, 2020

--

TL;DR : โปรแกรม shell เป็นโปรแกรมที่ทำงานอยู่ใน forever loop โดยเมื่อ user พิมพ์คำสั่ง โปรแกรม shell จะทำการ fork process เพื่อไปทำงานโปรแกรมนั้น ๆ

อย่างที่เราทราบกันดีว่าการ fork process เป็นการแยก process ออกจาก parent process เพื่อวัตถุประสงค์ เช่น ต้องการทำงานแบบ parallel

ก่อนอื่นเรามาทำความเข้าใจเกี่ยวกับการ fork process กันก่อน ซึ่งในที่นี้จะยกตัวอย่างเป็นภาษาซี

ตัวอย่างที่ 1

จะเห็นว่าเมื่อรันโปรแกรม จะ print คำว่า hello world แล้วตามด้วย process id ของ process ที่กำลังรันอยู่ โดยใช้คำสั่ง getpid()

หาก fork สำเร็จจะ return ค่ามากกว่าหรือเท่ากับศูนย์ โดยหากผลลัพธ์เป็น 0 แสดงว่าโค้ดบรรทัดนั้นรันอยู่ใน child process แต่หากผลลัพธ์มีค่ามากกว่า 0 แสดงว่าเป็น parent process ส่วนสาเหตุของการ fork ไม่สำเร็จอาจเกิดได้จากหลายปัจจัย เช่น memory ในขณะนั้นไม่เพียงพอ

ผลลัพธ์

ผลลัพธ์ของตัวอย่างที่ 1

คราวนี้ลอง advance ขึ้นอีกหน่อยโดยให้มีการรอ child process ให้ทำงานเสร็จก่อน แล้วค่อย callback มาที่ parent process โดยใช้คำสั่ง wait()

ตัวอย่างที่ 2

ผลลัพธ์

ผลลัพธ์ของตัวอย่างที่ 2

จะเห็นว่า child process ใช้เวลาในการทำงาน 1 วินาที (เป็นผลจากคำสั่ง sleep(1)) ก่อนจะปรากฎผลลัพธ์ในฝั่งของ parent process

พอจะเข้าใจคอนเซ็ปต์คร่าว ๆ ของการ fork process แล้วใช่มั้ยครับ คราวนี้มันเกี่ยวอะไรกับโปรแกรม shell ล่ะ? ลองมาดูตัวอย่างที่ 3 กัน

ตัวอย่างที่ 3

จากตัวอย่างที่ 3 พบว่าเราเปลี่ยนจากการให้ child process ทำการ sleep เป็นรันโปรแกรมจริง ๆ โดยเราจะให้รันโปรแกรม word count (ใช้คำสั่ง wc อย่าสับสนกับ wait system call นะ) เมื่อรันเสร็จแล้วให้ parent process แสดงผล pid ของตัวมันเองดังเช่นตัวอย่างอื่น ๆ ก่อนหน้า

ผลลัพธ์

ผลลัพธ์ของตัวอย่างที่ 3

จะเห็นว่าใน child process ได้ทำการแสดงค่าของจำนวนบรรทัด (number of lines) จำนวนของคำ (number of words) และจำนวนไบต์ (number of bytes) ตามลำดับ

เริ่มเอะใจแล้วใช่ไหมครับ เฉลยก็คือ โปรแกรม shell เป็นโปรแกรม forever loop (while(1)) ที่มีการ fork process เพื่อรันโปรแกรมอื่น ๆ (ที่ไม่ใช่ built-in command) โดยมีข้อควรระวังคือ

  • คุณสมบัติต่าง ๆ ของ parent process จะถูกตกทอดไปยัง child process ด้วย
  • address space จะถูก child process override

จากตรงนี้จะเห็นว่าหาก parrent process ถูกรันโดย root แล้ว child process ที่อยู่ภายใต้ parent process จะเป็น root ด้วย ดังนั้นต้องตระหนักเรื่องความปลอดภัยตรงนี้ด้วย

แล้วถ้าเป็น built-in commands ล่ะ จะเกิดอะไรขึ้น?

คำตอบก็คือ จะไม่มีการ fork process ขึ้นมาใหม่ (ใช้ pid เดิม) ตัวอย่างของ built-in commands คือ echo ซึ่ง source code ของ shell จะ implement คำสั่งพวกนี้ไว้ในตัว

มาดูโปรแกรม shell ที่ใกล้เคียงของจริงว่าหน้าตามันเป็นยังไง

http://csapp.cs.cmu.edu/2e/ics2/code/ecf/shellex.c

บทความหน้าจะพูดถึงการใช้ช่องโหว่ต่าง ๆ ในการโจมตีระบบคอมพิวเตอร์ในอดีต สามารถติดตามโดยกด Follow ได้เลยครับ

อ้างอิง

[01204554] Data Encryption & Security by Paruj Ratanaworabhan

--

--