(本節筆記接上一節的程序控制,繼續學習多程序的程式設計函數,詳細的實驗代碼在這裡)
1. 建立程序
函數名:
fork
函數原型:
pid_t fork ( void );
函數功能:
建立一個子程序
所屬頭檔案:
<unistd.h>
傳回值:
成功:在父程序中傳回子程序的pid,在子程序中傳回0 失敗:傳回1
參數說明:
void
範例代碼:(touch myfork.c)
#include <unistd.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
fork();
printf("Program is end!\n");
exit(0);
}
輸出結果:Program is end!
Program is end!
分析:當父程序調用fork建立一個代碼與父程序一樣的子程序是,子程序由printf開始執行!(重要)
pid的傳回值代碼:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
pid_t pid = fork();
printf("pid is %d!\n");
exit(0);
}
輸出結果:pid is 19112!
pid is 0
讓父程序執行分支的方法:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
pid_t pid = fork();
if ( pid > 0)
{
printf("here is parent process!\n");
}
else
{
printf("here is child process.\n");
}
exit(0);
}
2. 建立程序的另一種方式
函數名:
vfork
函數原型:
pid_t vfork ( void );
函數功能:
建立一個子程序,并阻塞父程序
所屬頭檔案:
<sys/types.h> <unistd.h>
傳回值:
成功:在父程序傳回子程序的ID,在子程序傳回0
參數說明:
void
範例代碼:(touch myvfork.c)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main ( int argc, char ** argv)
{
pid_t pid = vfork();
if ( pid > 0)
{
printf("father\n");
exit(0);
}
else
{
printf("child\n);
exit(0);
}
}
程式輸出的結果:child
father
分析——fork與fork的差別:vfork會阻塞父程序,子程序優先運作,而fork的父子程序的運作順序是随機的
範例代碼2:(touch forkcount.c)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main ( int argc, char ** argv)
{
int count = 0;
pid_t pid = vfork();
count++;
printf("%d\n", count);
exit(0);
}
程式輸出的結果:1
1
分析——在調用fork()建立的子程序中的棧是完全複制了父程序的棧,而且與父程序的棧互相獨立。而vfork()建立的子程序與父程序共享同一個棧。
3. 程序的退出
父程序:可用return 0 , 也可用exit(0);
子程序:隻能使用exit(0);
4. 程序等待
函數名:
wait
函數原型:
pid_t wait ( int *status);
函數功能:
挂起調用它的程序,直到其子程序結束
所屬頭檔案:
<sys/types.h> <sys/wait.h>
傳回值:
成功:傳回中止的那個程序的PID 失敗:傳回-1
參數說明:
status:記錄子程序的退出狀态。
範例代碼:(touch mywait.c)
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main( int argc, char ** argv)
{
pid_t pid = fork();
if ( pid > 0)
{
wait ( NULL );
printf( "father\n");
exit(0);
}
else
{
printf("child\n");
exit(0);
}
}
4. 程式執行
函數名:(execl、execv、execle、execve、execlp、execvp)
execl
函數原型:
int execl ( const char *path, const char *arg, ...);
函數功能:
運作可執行檔案
所屬頭檔案:
<unistd.h>
傳回值:
成功:無傳回 失敗:傳回-1 (關于execl的傳回值問題,可參考以下這裡)
參數說明:
path:要運作的可執行程式的路徑
arg:作為該可執行程式的參數,直接以NULL為參數結束标志
範例代碼:
..........
execl("/bin/ls", "ls", "/home", NULL);
..........
(一旦調用了execl(),原程序代碼段将被execl建立的可執行程式鎖替換,例如以下兩行代碼:
execl(......);
printf(......);
printf的操作始終不會被執行)