目录
前言
本文章简单介绍了fork()、vfork()、wait()、waitpid()函数,以及相应实例。
一、函数fork
现有进程可以调用fork函数创建一个新进程,父进程和子进程的执行顺序不定,由内核调度决定。
#include <unistd.h>
pid_t fork(void); //其中pid_t类型实际上是int类型
父进程和子进程之间的具体区别如下:
>fork的返回值不同
>进程ID不同
>两个进程的父进程ID不同
>子进程不继承父进程设置的文件锁
>子进程的未处理闹钟被清除
>子进程的未处理信号集设置为空集
二、函数vfork
vfork函数的调用序列和返回值与fork相同,但是两者的语义不同。
vfork的函数创建一个新进程,该新进程的目的是exec一个新程序,子进程调用exec或者exit之前,它运行在父进程的空间中。
vfork保证子进程先运行,在它调用exec或者exit之后父进程才能被调度运行。
三、函数wait
#include<sys/wait.h>
pid_t wait(int *statloc);
一个进程在终止前,wait使其阻塞,如果子进程已经终止,并且是一个僵死进程,则wait立刻返回并取得改子进程的状态,否则wait使其调用者阻塞,直到一个进程终止。因为wait返回终止进程的ID,所有它总能了解是哪一个子进程终止了。
四、函数waitpid
#include<sys/wait.h>
pid_t waitpid(pid_t pid,int *statloc,int options);
waitpid函数中pid函数不同值代表不同意义
>pid == -1 等待任一子进程
>pid > 0 等待进程ID与pid相等的子进程
>pid == 0 等待组ID等于调用进程组ID的任一子进程
>pid < -1 等待组ID等于pid绝对值的任一子进程
waitpid函数中options可以去值0、WCONTINUED、WNOHANG、WUNTRACED;支持非阻塞和作业控制。
五、函数实例
1.fork()
代码如下(示例):
int globvar = 6;
char buf[] = "a write to stdout\n";
void unix_8_1_fork(void)
{
int var;
pid_t pid;
var = 88;
if(write(STDOUT_FILENO,buf,sizeof(buf)-1) != sizeof(buf)-1)
err_sys("write error");
printf("befor fork\n");
if((pid = fork()) < 0)
err_sys("fork error");
else if(pid == 0){
var++;
globvar++;
}else{
sleep(2);
}
printf("pid=%ld,glob=%d,var=%d\n",(long)getpid(),globvar,var);
exit(0);
}
结果如下:
2.vfork()
代码如下(示例):
void unix_8_3_vfork()
{
int var;
pid_t pid;
var = 88;
printf("before vfork\n");
if((pid=vfork()) < 0)
err_sys("vfork error");
else if(pid==0){
globvar++;
var++;
_exit(0);
}
printf("pid=%ld,glob=%d,var=%d\n",(long)getpid(),globvar,var);
exit(0);
}
运行结果如下:
3.wait()
代码如下(示例):
void pr_exit(int status)
{
if(WIFEXITED(status))
printf("normal termination,exit status = %d\n",WEXITSTATUS(status));
else if(WIFSIGNALED(status))
printf("abnormal termination,signal number = %d\n",WTERMSIG(status));
else if(WIFSTOPPED(status))
printf("child stopped,signal number = %d\n",WSTOPSIG(status));
}
void unix_8_6_wait()
{
pid_t pid;
int status;
if((pid = fork()) < 0)
err_sys("fork error");
else if(pid == 0)
exit(7);
if(wait(&status) != pid)
err_sys("wait error");
pr_exit(status);
if((pid = fork()) < 0)
err_sys("fork error");
else if(pid == 0)
abort();
if(wait(&status) != pid)
err_sys("wait error");
pr_exit(status);
if((pid = fork()) < 0)
err_sys("fork error");
else if(pid == 0)
status/=0;
if(wait(&status) != pid)
err_sys("wait error");
pr_exit(status);
exit(0);
}
运行结果如下:
4.waitpid()
代码如下(示例):
void unix_8_8_waitpid(void)
{
pid_t pid;
if((pid = fork()) < 0)
err_sys("fork error");
else if(pid == 0){
if((pid = fork()) < 0)
err_sys("fork error");
else if(pid > 0)
exit(0);
sleep(2);
printf("second child,parent pid = %ld\n",(long)getppid());
exit(0);
}
if(waitpid(pid,NULL,0) != pid)
err_sys("waitpid error");
exit(0);
}
运行结果如下:
5.main函数
代码如下(示例):
#define UNIX_8_1_FORK
#define UNIX_8_3_VFORK
#define UNIX_8_6_WAIT
#define UNIX_8_8_WAITPID
int main(int argc, char *argv[])
{
#ifdef UNIX_8_1_FORK
unix_8_1_fork();
#endif
#ifdef UNIX_8_3_VFORK
unix_8_3_vfork();
#endif
#ifdef UNIX_8_6_WAIT
unix_8_6_wait();
#endif
#ifdef UNIX_8_8_WAITPID
unix_8_8_waitpid();
#endif
printf("MAIN END\n");
return 0;
}
总结
本章主要介绍了进程控制中的fork函数、vfork函数、wait函数、waitpid函数以及代码例程。