Vietnamese Developers’ Blog

fork()

Posted in C/C++, Unix/Linux/BSD by Hoang Tran on August 29, 2007

Một trong thứ hay nhất của *NIX mà M$Windows không có chính là system calls: fork(). Fork tạo ra một process con (child process) là copy (nhân bản) của chính process tạo ra nó (parent process) (làm mình nhớ đến clone() để tạo copy một object trong OOP). Để phân biệt giữa parent process và child process chính là giá trị trả về của hàm fork. Ở parent process thì hàm fork sẽ trả về chính là processID của tiến trình con, còn ở child process thì fork sẽ trả về 0. Fork sẽ trả về 2 lần ở tiến trình cha và tiến trình con.

#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);

Ngay khi hàm fork được gọi thì ngay lập tức phải suy nghĩ song song 2 process. Tất cả những instruction tiếp theo sau lệnh fork đều được thực hiện ở cả hai process (parent and child). Nghĩa là mã lệnh thực thi của cả 2 tiến trình là giống nhau. Hai tiến trình này có không gian địa chỉ riêng rẽ (virtual memory 4G bộ nhớ), stack riêng rẽ, vùng dữ liệu riêng mà. Ở tiến trình con thì sẽ có thêm PPID (parent processID) chính là processID của tiến trình cha.

pid_t childpid;
childpid = fork();
switch (childpid) {
    case -1: // Can not fork new process
                 break;
    case  0: // Child process
                 break;
    default: // Parent process
                 break;
}

Thế nếu muốn nhân bản nhiều child process thì làm thế nào. Khi ấy sẽ không thể suy nghĩ rằng hãy đặt các lệnh fork liên tiếp( fork(); fork() ). Vì ngay sau khi thực hiện lệnh fork thì tiến trình cha đã được nhân bản và tiến trình con cũng sẽ thực hiện lệnh fork tiếp và nhân bản chính tiến trình con đó. Khi ấy ta sẽ có một cây nhị phân tăng theo cấp số nhân 2. Thay vì đó ta hãy đặt lệnh fork tạo process con tiếp theo ở đoạn mã của tiến trình cha.

switch (childpid) {
      . . .
    default: // Parent process
        newchildpid = fork(); // Tạo new child process của tiến trình cha ở đây
        switch ( newchildpid )
        . . .
        break;
}

Tạo các con theo cùng bậc thì chúng ta lại code theo “chiều dọc” (các đoạn switch lồng nhau).

Phần tiếp theo về các vấn đề liên quan đến fork() như khi nào cần sử dụng fork, hay việc chờ đợi tiến trình con hay IPC (inter process communication) và multi-process programming sẽ được đề cập khi nào có dịp.

Reference:

  • Man Page
  • http://www2.cs.uregina.ca/~hamilton/courses/330/notes/unix/fork/fork.html
  • Linux Programming – Wrox Press
Tagged with:

3 Responses

Subscribe to comments with RSS.

  1. kiennguyen said, on August 30, 2007 at 9:23 am

    Hay đấy. Nhưng em có thắc mắc: Ứng dụng của fork là gì? Tại sao lại cần 1 tiến trình giống hệt tiến trình cha? Nếu đồ M$ không có cái này thì phải có cái gì đó na ná như vậy chứ?

  2. hoangtran said, on August 30, 2007 at 10:01 am

    Một ví dụ điển hình nhất chính là việc running một command trong shell trong background (chạy với dấu & ở cuối). Ví dụ:
    $cp a b &
    Bản thân shell cũng là một tiến trình. Khi thực hiện một lệnh thì shell sẽ tạo ra một tiến trình con chạy độc lập với tiến trình cha nhưng vẫn sử dụng dữ liệu (như biến môi trường) và stack của tiến trình cha. Bình thường nếu không đưa tiến trình con vào hậu cảnh (background) hay không sử dụng dấu ‘&’ thì tiến trình cha (shell) sẽ đợi tiến trình con chạy xong và trả về giá trị rồi mới thực hiện tiếp. Còn nếu đưa vào hậu cảnh tiến trình con, thì tiến trình cha sẽ không đợi tiến trình con và 2 tiến trình sẽ chạy độc lập.
    Ở trên Windows không có fork nhưng có spawn() (dùng spawn cho portibility) hoặc CreateProcess() để tạo process mới (khác với fork là tạo copy của tiến trình cha). Tuy nhiên để chạy được như fork thì sẽ phức tạp hơn (từ từ rồi sẽ giải quyết câu hỏi này)

    Một số bài tập và các example mẫu cho việc sử dụng fork.

    http://www.acmesystems.it/?id=270
    http://www.linuxforums.org/forum/linux-programming-scripting/101809-process-creation-using-fork.html
    http://www.osix.net/modules/article/?id=87
    http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

    Các hàm liên quan nên đọc: exec(), wait(), clone(), fork vs vfork, …

  3. hoangtran said, on August 30, 2007 at 10:37 am

    Một số bài tập và các example mẫu cho việc sử dụng fork.

    http://www.acmesystems.it/?id=270
    http://www.linuxforums.org/forum/linux-programming-scripting/101809-process-creation-using-fork.html
    http://www.osix.net/modules/article/?id=87
    http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

    Các hàm liên quan nên đọc: exec(), wait(), clone(), fork vs vfork, …


Leave a Reply