程式分歧fork()
fork()會産生一個與父程式相同的子程式,唯一不同之處在於其process
id(pid)。
如果我們要撰寫守護神程式,或是例如網路伺服器,需要多個行程來同時提供
多個連線,可以利用fork()來産生多個相同的行程。
函數宣告
pid_t fork(void);
pid_t vfork(void);
傳回值:
-1 : 失敗。
0 : 子程式。
>0 : 将子程式的process id傳回給父程式。
在Linux下fork()及vfork()是相同的東西。
範例一: fork.c
在這個範例中,我們示範fork()的标準用法。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main(void)
{
pid_t pid;
printf("hello/n");
pid = fork();
switch (pid) {
case -1: printf("failure!/n"); break;
case 0: printf("I am child!/n"); break;
default: printf("my child is %d/n",pid); break;
}
for (;;) { }
}
編譯:
gcc -o ex1 fork.c
執行結果:
./ex1 &
hello
my child is 8650
I am child!
我們可以見到,使用fork(),可将一個程式分岐成兩個。在分歧之前的程式碼
隻執行一次。
檢驗行程:
ps | grep ex1
8649 p0 R 0:40 ./ex1
8650 p0 R 0:40 ./ex1
8649是父程式的pid,8650則為子程式的pid。
您會需要用到"killall ex1"來殺掉兩個行程。
範例二: daemon.c
在UNIX中,我們一般都利用fork(),來實作所謂的"守護神程式",也就是DOS中
所謂的"常駐程式"。一般的技巧是将父程式結束,而子程式便成為"守護神"。
這個範例中,示範一般标準的daemon寫法。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main(void)
{
pid_t pid;
pid = fork();
if (pid>0) {
printf("daemon on duty!/n");
exit(0);
} else
if (pid<0) {
printf("Can't fork!/n");
exit(-1);
}
for (;;) {
printf("I am the daemon!/n");
sleep(3);
}
}
編譯:
gcc -o ex2 daemon.c
執行結果:
./ex2
daemon on duty!
I am the daemon!
接下來每三秒鐘,都會出現一個"I am the daemon!"的訊息,這表示您的程式
已經"長駐"在系統中了。
檢驗行程:
ps | grep ex2
8753 p0 S 0:00 ./ex2
注意到在範例一中,我們下的指令為"./ex1 &",而在範例二中為"./ex2",沒
有"&"符号。
範例三:Perl Script
my @subpid;
my $rtpid = $$;
foreach my $file (@file){
chomp $file;
my($file, $dir, $ext) = fileparse($file);
if (1 == 1) {
my $exec_cmd = "$cmp_cmd ${rsyncTgtDir}${file} ${rsyncTmpDir}${file}";
my $pid = fork();
if ($pid == 0){
setpgrp(0, $rtpid);
exec($exec_cmd);
print "fail to execute $exec_cmd/n";
exit(1);
}
else{
push(@subpid, $pid);
}
}
}
if($$ == $rtpid ){
foreach my $pid (@subpid){
if(getpgrp($pid) == $rtpid ){
waitpid($pid, 0);
}
}
}