2009年3月7日 星期六

多線程程式設計 - fork()

#include <unistd.h>

pid_t fork(void);

只有呼叫fork一次,但是會return 2次
一次是parent process回傳的值是child process的identify
第二第是child process回傳的值是0

fork( )有兩個 return 值,大於 0 的是 parent (值不固定),等於 0 的是 child,兩個 process 在 fork( ) 成功後同時存在,並沒有什麼不一樣,可以說是完全一樣的process,fork( ) 之後的parent 與 child 會共同指向 fork() 以下的執行指令,也就是說,parent 和 child 都會執行 fork( ) 以下的程式碼,而且是各自執行,child 會符合 switch 中 pid == 0 的條件、 parent 則會符合 default 中的條件.

child process回傳值是0是有其原因的,
因為每一個process只有一個parent process,而且可以透過getppid得到parent process的identify

而parent process可以有很多child process,而且沒有函數可以取得child process的identify,因此若parent process要追蹤child process則必需記錄fork()回傳的id

在呼叫fork()前,一個file descriptor在父類別被指定,則此父類別可以與子類別共同分享這一個資源.

通常有兩種使用fork()的方式:
1. 一個程序複製它自己,產生另一個程序,使得兩個程序可以同時做事情,像是網路應用程式均是用這一個方法
2. 一個程序去執行另一個程序。同樣的,第一個程序先複製它自己,產生另一個程序。而這一個程序執行exec()來使另一個程序來取代這一個本身的子程序

另外必需注意的是,fork()回傳值的型態是pid_t,不能用int的變數去接

在web application的一個很好的例子是:

pid_t pid;
int listenfd,connfd;
listenfd = socket( ... );
// fill in sockaddr_in{} with server's well-known port
bind(listenfd, ...);
while(1) {
  connfd = accept(listenfd, ... );  // probably blocks
  if ((pid=fork())==0) {
    close(listenfd);  // child closes listening socket
    doit(connfd);     // process the request
    close(connfd);    // done with this client
    exit(0);
  }
  close(connfd);      // parent closes connected socket
}

就可以同時服務很多client端的程式啦~


參考資料:
行程關念
Process Control
Linux下的多進程編程(轉) - fork(),exec()等函數的使用
CS 360 - Internet Programming

沒有留言: