Thursday, August 30, 2012

UNIX Programing

The Life Cycle of A Process (ต่อ)


เรามาว่ากันเรื่องนี้ต่อจากตอนที่ค้างอยู่ ในตอนใหม่นี้เลย น่ะครับ
ขอท้าวความเดิมที่ทิ้งไว้ตรงย่อหน้าสุดท้าย ความว่า

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

และนี่คือส่วนที่ทั้ง ๒ โปรเซส สามารถแยกระหว่างกันและกันออกได้ ในภาษา C ที่พอยกมาให้เห็นกันตอนนี้ง่ายๆ

/*
 * fork()
 */

#include <sys/types.h>
#include <unistd.h> 

int main(int argc, char *argv[])
{

pid_t proc_id;

proc_id = fork();

if (proc_id == 0) {
    /* อันนี้เป็นส่วนของ child โปรเซส ก็จะมีพฤติกรรมแบบทารกทั่วๆไป */
} else {
    /* ตรงนี้ เป็นส่วนของ parent */
}
}


Control of Processes

จักขอกล่าว พอได้สาระในส่วนของ child ก่อนแต่พอสังเขปดังนี้

ภายหลัง fork() โปรเซสใหม่มักจะเรียกใช้บริการของ system calls ในตระกูล exec ดังได้กล่าวมาแล้วนั้นเสมอ ซึ่งเมื่อดำเนินการเสร็จสิ้นแล้วก็ ตายไปตามกาล ส่วนของ parent นั้นหากไม่มีอะไรมาก ก็มักจะยกภาระแลทรัพย์สินทั้งมวล (หน่วยความจำ) ให้กับ ลูก ที่เกิดขึ้นแล้วตัวเองก็ ตายเมื่องานสร้างทารกจบสิ้นลงด้วยดี


เป็นเช่นนี้แล้ว ใครจะเป็นผู้ดูแล โปรเซส ของทารกที่เกิดใหม่นี้

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

ดังนี้แล้วเมื่อโปรเซสใดโปรเซสหนึ่ง พร้อมที่จะตาย คือจบงานแล้วนั่นแหละ   โปรเซสนั้นจะเรียกรูทีน _exit เพื่อแจ้ง kernel ว่าพร้อมแล้ว และก็มี  exit code เป็นของฝาก  มาให้ พ่อ-แม่ที่สร้างโปรเซสนั้นๆ เอาไปดูผลงานด้วย (exit code = 0 ถือว่า ทำงานสำเร็จ)

ข้างฝ่าย kernel เมื่อได้รับแจ้ง
  1. ก็จะจับเก็บ exit code นี้เอาไว้ จนกว่าจะมีรายการทวงของฝาก จากพ่อ-แม่ ผ่านทาง system call ที่ชื่อ wait  
  2. หน่วยความจำที่โปรเซสที่แจ้งตายนั้นใช้อยู่ ก็จะถูกเรียกกลับคืนมาสู่ส่วนกลาง

โปรเซส นั้นจะไม่ได้รับเจียดเวลา แม้ สักส่วนเสี้ยว ของ หน่วยเวลา จาก cpu อีกต่อไป  แต่ก็ยัง คงสถานะเอาไว้ จนกว่าพ่อ-แม่ จะมาจับไป ให้รางวัล หรือ ลงโทษลงทัณฑ์ อย่าใดอย่าหนึ่งนั่นแหละ   ถึงจะถูกลบสถานะออกจากระบบโปรเซส

โปรเซส ที่อยู่ระหว่างการแจ้งตายนี้ เรียกว่า zombie
พอมาถึงตรงนี้ กะคงพอมองเห็นเค้าลางของ อนาคตของโปรเซส ที่ถามานั้นได้

ที่เล่ามาก็ดูว่า OK น่ะ ในกรณีที่พ่อ-แม่ผู้สร้าง โปรเซส นั้นไม่ตายก่อนและยังเรียกหาโปรเซสลูก ด้วย wait() ในแบบนี้จะไม่มี zombie เกิดขึ้น  ตัวอย่างของ C codes ข้างล่างนี้แสดง process control ในแนวนี้

/*
 * parents wait  

 */

#include <sys/types.h>

#include <sys/wait.h>
#include <unistd.h> 

int main(int argc, char *argv[])
{    
    pid_t proc_id; 
    int status;

   proc_id = fork();

   if (proc_id == 0) {
        /* อันนี้เป็นส่วนของ child โปรเซส ก็จะมีพฤติกรรมแบบทารกทั่วๆไป */
        execl("/bin/sh", "sh",  NULL);
    } else {
        wait(&status); 
            /* สาระของงานที่ต้องทำต่อ เช่น ตรวจดูว่า จบงานลักษณะไหน 
             * stopped, terminated, continue, หรือโดยวิธีอื่น
             */
    }
}

wait() จะดูว่า ทารกจบงานอย่างไร ถ้าจบงานด้วย stopped, continued, terminated เหล่านี้ wait() จะได้ส่งค่า process id ของ ทารกนั้นให้กับ main() เพื่อเคลียร์งานต่อไป

ถ้าพ่อ-แม่ผู้สร้าง โปรเซส ขึ้นมานั้นชิงตายหนีไปก่อน ในกรณีนี้ kernel ก็ไม่รู้จะเก็บ exit code นั้นเอาไว้ทำไม เพราะไม่มีคิวคำขอ exit code นั้นจาก wait()    ดังนี้แล้ว kernel จึงได้แต่บริจาค zombie นั้นให้กับ init ไปอย่างเดียว เท่านั้น

ตัวอย่าง C codes ในส่วนนี้ ก็คล้ายกับส่วนแรก เพียงไม่ต้อง wait(&status); เท่านั้นเอง ดังนี้

/*
 * parents die first

 */
 
#include <sys/types.h>
#include <unistd.h> 

int main(int argc, char *argv[])
{

     pid_t proc_id; 

    proc_id = fork();

    if (proc_id == 0) {
        /* อันนี้เป็นส่วนของ child โปรเซส ก็จะมีพฤติกรรมแบบทารกทั่วๆไป */
        execl("/bin/sh", "sh",  NULL);
     }


กะคงพอให้สาระในเรื่องของ process control กันบ้างน่ะครับ

อย่างไรก็ดี คราวนี้ต้องยอมรับสภาพร่างกายจริงๆครับ เลยทำให้ชะงักไปร่วมเดือน  และแม้แต่ครั้งนี้ ก็เร่งรีบอยู่น่ะ  มะฃาม ต้องขอตรวจรายละเอียดของเรื่อง main function ให้ชัดๆอีกหนก่อนละกัน

ขอขอบคุณมากครับ ที่สละเวลามาอ่านข้อเขียนในชุดนี้

No comments:


View My Stats