fork()函数
打算開始寫apue的系列內容,及時更新
文章目錄
- 前言
- 一、fork()函數
- 一個簡單的例子
- 2.子進程是父進程的一個副本
- 總結
前言
從處理方式來分類的話,上一節中講到的網絡sokcet通訊屬于迭代服務器,該服務器每次只能處理一個客戶的請求,實現簡單,但是效率很低下,今天要講的是多進程編程,屬于并發服務器,可以同時處理多個客戶的請求,相較而言,效率很高但是實現復雜。
在學習多進程編程之前我們首先需要知道的是一下內容
一、fork()函數
在Linux下有兩個基本的系統調用可以用于創建子進程:fork()和vfork(),當一個進程正在運行的時候,使用了fork()函數之后就會創建另一個進程。與一般函數不同的是,fork()函數會有兩次返回值,一次返回給父進程(該返回值是子進程的PID(Process ID)),第二次返回是給子進程,其返回值為0.所以在調用該函數以后,我們需要通過返回值來判斷當前的代碼時父進程還是子進程在運行:
- 返回值大于0 -> 父進程在運行
- 返回值等于0 -> 子進程在運行
- 返回值小于0 -> 函數系統調用出錯
通常系統調用出錯的原因有兩個:①已存在的系統進程已經太多;②該實際用戶ID的進程總數已經超過了限制。
一個簡單的例子
代碼如下(示例):
#include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h>int main(int argc,char **argv) {pid_t pid;printf("parent process PID[%d] start running!!!\n",getpid());pid = fork();if(pid < 0){printf("\n\n");printf("fork() create child process failure: %s\n",strerror(errno));return -1;}else if(pid == 0){printf("\n");printf("child process PID[ %d ] start running,my parent PID is [ %d ]\n",getpid(),getppid());return 0;}else //if(pid > 0){printf("\n");sleep(2);printf("parent process PID[%d] continue running,and child process PID is [ %d ]\n",getpid(),pid);printf("\n");return 0;} }其運行結果如圖所示:
該示例代碼中,使用了fork()函數了之后,下面通過pid的返回值來判斷是父進程還是子進程在被調用,或者是系統調用失敗(pid < 0 時)。其父子進程的運行順序并不是一定的,這個系統的調度策略有關系。
2.子進程是父進程的一個副本
當fork()系統調用時,創建了一個新的子進程,這個子進程時父進程的一個副本,系統在創建了這個新的子進程了之后,會將父進程的文本段、數據段、堆棧都復制一份給子進程,子進程擁有自己獨立的空間,對自己內存的修改并不會影響父進程相應的內存空間
代碼如下(示例):
#include <stdio.h> #include <errno.h> #include <unistd.h> #include <string.h>int g_var = 6; char g_buf[] = "a string write to stdout\n";int main(int argc,char **argv) {int var = 88;pid_t pid;if( write(STDOUT_FILENO,g_buf,sizeof(g_buf) -1) < 0){printf("\n\n");printf("write string to stdout error: %s\n",strerror(errno));return -1;}printf("before fork\n");if( (pid = fork()) < 0 ){printf("\n");printf("fork() error: %s\n",strerror(errno));return -2;}else if(0 == pid){printf("\n");printf("child process PID[%d] running!!!\n",getpid());g_var++;var++;}else{printf("\n");printf("parent process PID[%d] waiting!!!\n",getpid());sleep(1);}printf("PID = %ld,g_var = %d,var = %d\n",(long)getpid(),g_var,var);return 0; }其運行結果如圖所示:
由運行結果可知,當在子進程對全局變量和局部變量進行自加的時候,并不會影響到父進程中全局變量和局部變量的值。在該代碼中,當pid>0,也就是執行父進程部分代碼的時候,使用了休眠函數sleep(),在這里的目的是想讓子進程先執行,但是這并不一定能夠奏效,當系統負載較大的時候一秒的時間內操作系統可以沒調度到子進程運行。
總結
這篇文章只是多進程編程的一個小開始,真正在多進程編程中也會用到fork()函數,它的使用思路是:每來一個客戶端向服務器端連接的時候,就創建一個子進程為客戶端進行服務。后續會繼續更新噠。
總結
- 上一篇: 机器人学导论——操作臂运动学
- 下一篇: Windows API函数大全(精心总结