并发任务处理:fork,vfork,wait函数的使用,及详解

来源:互联网 发布:安卓版全球网络电视apk 编辑:程序博客网 时间:2024/05/16 14:22

这两天在复习进程,把笔记上传上去,一来保存笔记,二来和大家分享一下,不多说,入主题。。。。

+++++++++++++++++++++++++++++++++++++++++++++++++++
进程(process):
函数:fork
语法:pid_t fork(); 
功能:创建子进程;父进程和子进程都会执行,子进程相当于是父进程的克隆体,主要用PID来区分,进程也会分配新的内存空间,。此函数调用一次,返回两次,在父进程中的返回值为子进程的PID,在子进程中的返回值为0。


++++++++++++++++++++++++++++++++++++++++++++++++++++

函数:vfork
语法:pid_t vfork();
功能:vfork()会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码,组代码,环境变量,已打开的文件代码,工作目录和资源限制等;
返回值:如果成功则在父进程会返回新建立的子进程代码PID,而在新建立的子进程则返回0.如果失败则返回-1.失败原因存在errno中(内存不足;内存不足,无法配置核心所需的数据结构空间);

用getpid()获取子进程的PID,getppid()获取父进程的PID;


fork函数与vfork函数的区别:
前者,父子进程并发执行;后者,子进程先运行,父进程挂起,直到子进程调用exec或exit;
fork函数用于创建一个新进程。由fork()创建的子进程是父进程的副本。即子进程获取父进程数据空间,堆和栈的副本。父子进程之间不共享这些存储空间的部分。而vfork()创建的进程并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exit于是也就不会存放该地址空间。相反,在子进程调用exit之前,它在父进程的空间进行。
vfork保证子进程先运行,在调用exit之前与父进程数据是共享的,在它调用exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致锁死。

+++++++
fork函数:创建子进程返回0,父进程返回子进程id,父和子进程数据不共享;

vfork函数:返回值同上;子进程在执行exit(-1)函数之前会把父进程挂起来,然后父和子进程数据共享。

+++++

相同点:两者被调用一次,但是返回两次。两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程PID;

+++++++++++++++++++++++++++++++++++++++++++++++++++++

函数:wait;
语法:pid_t wait(int* status);
参数:status时一个整数指针,是该子进程退出的状态。若不为空,则通过它可以获得子进程的结束状态。另外,子进程的结束状态可由Linux中一些特定的宏来测试;(一般为NULL,当status为NULL时,只要有子进程退出,wait()退出阻塞(且返回值为退出的子进程的进程号),否则一直阻塞直到有子进程退出。当调用wait()函数的进程没有子进程时,返回-1。如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中,这是一个整数值(int),指出了子进程是正常退出还是非正常结束的(一个进程也可以被其他进程用信号结束),以及正常结束时返回值,或被哪一个信号结束的等信息。由于这些信息被存放在一个整数的不同二进制位中,所以用常规的方法读取会非常麻烦,人们就设计了一套专门的宏(macro)来完成这项工作。1、WIFEXITED(status):这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。(请注意,虽然名字一样,这里的参数status并不同意wait唯一的参数——指向整数的指针status,而是那个指针指向的整数,切记不要搞混了。)
2、WEXITSTATUS(status):当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status)就会返回5;如果子进程调用exit(7)退出,WEXITSTATUS(status)就会返回7。请注意,如果进程不是正常退出,也就是说,WIFEXITED返回0,这个值就毫无意义了。)

功能:用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或该进程接收到一个指定的信号为止。如果该父进程没有子进程或它的子进程已经结束,则wait()就会立即返回。

上代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void 1_child_process()
{
int count = 0;
int pid;
int status;
pid = fork();

if(pid < 0)
{
perror("first_child_process fail");
exit(-1);
}
else if(pid == 0)
{
printf("I am first child process ,the count is %d,my process id is %d  ",count,getpid());
printf("ppid = %d\n",getppid());
exit(9);
}
else 
{
printf("wait(&status) = %d\n",wait(&status));
printf("WEXITSTATUS(status) = %d\n",WEXITSTATUS(status));
printf("I am first father process ,the count is %d,my process id is %d,son id %d\n",++count,getpid(),pid);
}
}


void 2_child_process()
{
int count = 0;
int status;
pid_t pid;
pid = vfork();

if(pid < 0)
{
perror("second_child_process fail");
exit(-1);

}
else if(pid == 0)
{
printf("I am second child process, the count is %d ,my process id is %d\n",++count,getpid());
exit(5);
}
else
{
printf("wait(&status) = %d\n",wait(&status));
printf("WEXITSTATUS(status) = %d\n",WEXITSTATUS(status));
printf("I am second father process ,the count is %d,my process id is %d,son id %d\n",count,getpid(),pid);
}

}

int main()
{
// 1_child_process();
2_child_process();

return 0;
}

执行结果奉上:见图片1,2。。。。
图1

图2






#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
pid_t pid;
pid = fork();
int status,i;

if(pid < 0)
{
perror("fail");
exit(-1);
}
else if(pid == 0)
{
printf("child process pid = %d\n",getpid());
exit(10);
}
else
{
sleep(1);
printf("father process ,wait for child...\n");
// wait(&status);
// wait(NULL);


printf("father:child pid = %d\n",pid);
/*
  wait函数功能:用于阻塞父进程,直到一个子进程结束,或该进程收到一个指定的消息位置;
printf("wait(NULL) = %d\n",wait(NULL));   //如果wait函数的参数为NULL,则此函数返回子进程的ID;
printf("WIFEXITED(status) = %d\n",WIFEXITED(status));  //相对应的,这个宏用来指出子进程是否正常退出,如果wait函数参数为NULL,则此宏返回值为0;否则为非零值; 
printf("WEXITSTATUS(status) = %d\n",WEXITSTATUS(status));   //那么返回这个宏就没什么意义;
*/
printf("wait(&status) = %d\n",wait(&status));   //如果wait函数不为空,同样的也会返回子进程的ID,并且把子进程的退出的状态取出并存入其中,用下面的宏返回;
printf("WIFEXITED(status) = %d\n",WIFEXITED(status));   //如果wait函数参数不为NULL,返回非零值;
printf("WEXITSTATUS(status) = %d\n",WEXITSTATUS(status));  //此宏返回子进程退出的状态,例如exit(7),就返回7;


}


return 0;
}

执行结果:见图片3,4.。。。。



感谢CSDN各大神!!









原创粉丝点击