这次的主角是fork。相信每个unix的学习者都绕不过这个函数。此函数创建一个子进程,与父进程共享代码区,但是有自己单独的数据区和栈区。此函数在父进程中返回子进程的pid,而在子进程中却返回0。这恐怕是最让初学者们难以理解的地方了。正是因为这个性质,fork在使用是总是出现在if else块中;以区分父进程和子进程需要执行的代码。
1,小试牛刀,在使用fork的前后打印出当前进程的pid(getpid)和ppid(getppid)。结果很容易发现子进程中的ppid即为父进程的pid
#include<unistd.h>
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include <stdlib.h>
void main( int argc, char ** argv )
{
int val_fork;
printf("PID = %d\n", getpid());
printf("PPID = %d\n", getppid());
printf("No° de propriétaire = %d\n", getuid());//sb.st_uid);
printf("No° de groupe = %d\n", sb.st_gid);
if( (val_fork=fork())==0)
{
//section fils
printf("Section fils : val_fork = %d\n", val_fork);
printf("Section fils : PID = %d\n", getpid());
printf("Section fils : PPID = %d\n", getppid());
exit(0);
}else {
printf("Section pere : val_fork = %d\n", val_fork);
printf("Section pere : PID = %d\n", getpid());
printf("Section pere : PPID = %d\n", getppid());
return;
}
}
2,写程序证明父子进程是同时执行的;即会出现交替的输出(使用sleep来把执行机会让给对方);使用wait使父进程在子进程之后结束。
#include<unistd.h>
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include <stdlib.h>
void main( int argc, char ** argv )
{
int val_fork;
int i;
printf("PID = %d\n", getpid());
printf("PPID = %d\n", getppid());
if( (val_fork=fork())==0)
{
//section fils
for ( i=0; i<10; i++)
{
printf("Section fils : PID = %d\n", getpid());
printf("Section fils : PPID = %d\n", getppid());
}
exit(0);
}else {
for ( i=0; i<10; i++)
{
printf("Section pere : PID = %d\n", getpid());
printf("Section pere : PPID = %d\n", getppid());
}
wait();
printf("Stop waiting!!!\n");
return;
}
}
3,多任务。计算(a + b) * (c + d) / (e + f)。其中
a + b 由儿子1计算
c + d 由儿子1计算
e + f 由儿子1计算
* 和 / 由父亲计算。
这个就稍微有点意思了,只允许实使用最简单的进程间通讯方式。
- 变量的传入不是问题,因为子进程本来就有一份父进程的数据拷贝。
- 子进程计算完的结果如何返回给父进程?可以利用waitpid函数。父进程分别等待相应的子进程结束,并提取收到的返回值。详细使用方法需阅读man wait
代码
#include<unistd.h>
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include <stdlib.h>
int main( int argc, char ** argv )
{
int val_fork1, val_fork2, val_fork3;
int i, res_fils1, res_fils2, res_fils3, res;
int a = atoi(argv[1]);
int b = atoi(argv[2]);
int c = atoi(argv[3]);
int d = atoi(argv[4]);
int e = atoi(argv[5]);
int f = atoi(argv[6]);
if( (val_fork1=fork())==0)
{
res = a+b;
printf("Fils 1 : a + b = %d\n", res);
return(res);
}
else
{
if( (val_fork2=fork())==0)
{
res = c+d;
printf("Fils 2 : c + d = %d\n", res);
exit(res);
}
if( (val_fork3=fork())==0)
{
res = e+f;
printf("Fils 3 : e + f = %d\n", res);
exit(res);
}
waitpid(val_fork1, &res_fils1, 0);
waitpid(val_fork2, &res_fils2, 0);
waitpid(val_fork3, &res_fils3, 0);
//printf("%d, %d, %d\n\n", WEXITSTATUS(res_fils1) , res_fils2 , res_fils3);
printf("Résultat final = %d\n", WEXITSTATUS(res_fils1) *WEXITSTATUS(res_fils2) / WEXITSTATUS(res_fils3));
return;
}
}
先到这,有时间继续!
本文通过三个实例探讨了fork函数在Unix系统中的应用:展示父子进程的PID与PPID关系、验证父子进程并行执行特性及利用多进程进行简单数学运算。
3万+

被折叠的 条评论
为什么被折叠?



