第三季-第12课-多进程程序设计

第12课-多进程程序设计

 

1. 创建进程

(1) 函数名

fork

(2) 函数原形

pid_t fork(void)

(3) 函数功能

创建一个子进程

(4) 所属头文件

#include<unistd.h>

(5) 返回值

成功:在父进程中返回子进程的pid,在子进程中返回的是0.

失败:-1

(6) 参数说明

无参数

(7) 范例程序

#include<unistd.h>

void main()

{

         fork();

         printf("program is end\n");

         exit(0);

}

当我们运行这段程序的时候,我们发现program is end被打印了两次,下面我们来分析一下原因:

我们把上面的程序可以看成是父进程,当父进程运行到fork()函数的时候。会出现一个子进程,子进程的代码与父进程的一样。但是子进程并不是从代码的开头去运行,而是从fork()函数后面的代码开始运行。于是printf()函数一共被调用了两次。我们现在将程序做如下的修改:

#include<unistd.h>

void main()

{

         pid_t pid;

         pid = fork();

         printf("pid is %d\n",pid);

         exit(0);

}

程序被打印了两次,一次打印的是父进程的pid(是个数),一次打印的是子进程的pid(是0)。

这里面也出现了一个问题。那就是,既然父程序和子程序代码是一样的,我们怎么能让一样的代码去执行不一样的程序呢。实际我们只需要一个if语句就行,程序如下:

#include<unistd.h>

void main()

{

         pid_t pid;

         pid = fork();

         if(pid>0)

         {

                  printf("father process!\n");//操作1

                  exit(0);

         }

         else

         {

                  printf("son process!\n");     //操作2

                  exit(0);

         }

}

打印的结果是:father process!

              son process!

2. 创建进程2

(1) 函数名

vfork

(2)函数原形

pid_t vfork(void)

(3)函数功能

创建一个子进程并且阻塞父进程

(4)所属头文件

#include<sys/types.h>

#include<unistd.h>

(5)返回值

成功:在父进程中返回子进程的pid,在子进程中返回的是0.

失败:-1

(6)参数说明

无参数

(7)范例程序

#include<unistd.h>

void main()

{

         pid_t pid;

         pid = vfork();

         if(pid>0)

         {

                  printf("father process!\n");//操作1

                  exit(0);

         }

         else

         {

                  printf("son process!\n");     //操作2

                  exit(0);

         }

}

打印的结果是:son process!

father process!

我们发现这里的程序和fork()的程序是一样的,但是产生的结果却是相反的。下面我们来分析一下:当我们创建了一个子进程后,到底是父进程还是子进程先运行呢?;而vfork()的作用是让子进程先运行;fork(()函数的作用不一定让那个程序先运行。

下面我们来分析一下fork()函数和vfork()函数的区别:

(1)父进程和子进程运行的顺序不同。

(2)我们来看一下下面两组程序的运行结果

#include<unistd.h>

#include<sys/types.h>

void main()

{

         pid_t pid;

         int count = 0;

         pid = fork();

         count++;

         printf("count = %d\n",count);

         exit(0);

运行结果:count = 1;

          count = 1;

#include<unistd.h>

#include<sys/types.h>

void main()

{

         pid_t pid;

         int count = 0;

         pid = vfork();

         count++;

         printf("count = %d\n",count);

         exit(0);

}        

运行结果:count = 1;

          count = 2;

分析:count是存放在栈中的,当我们执行fork()时,我们将父进程中的栈也复制过来了,也就是子进程拥有自己独立的数据段和堆栈;在我们使用vfork()的时候,子进程是和父进程共享数据段和堆栈的。

 

 

3. 进程退出

我们在父进程中退出,可以使用return 0,也可以使用exit(),(exit(0)表示正常退出,exit(1)表示非正常退出);在子进程中我们只能使用exit()进行退出。

(1) 函数名

exit()

(2) 函数原形

exit()

(3) 函数功能

退出进程

(4) 所属头文件

#include<unistd.h>

(5) 返回值

(6) 参数说明

 

4. 进程等待

(1) 函数名

wait

(2) 函数原形

pid_t wait(int *status);

(3) 函数功能

挂起调用它的进程,直到其子进程结束。

(4) 所属头文件

#include<sys/types.h>

#include<ysy/wait.h>

(5) 返回值

成功:返回终止的那个子进程的id

失败:-1

(6)参数说明

status:记录子进程的退出状态

(7)范例程序

#include<unistd.h>

#include<sys/types.h>

#include<sys/wait.h>

void main()

{

         pid_t pid;

         pid = fork();

         if(pid>0)

         {

                  wait(NULL);

                  printf("father process!\n");//操作1

                  exit(0);

         }

         else

         {

                  printf("child process!\n");     //操作2

                  exit(0);

         }

}

结果显示:chlid process!

          father process!

分析:在运行到父进程的时候进入wait(NULL)函数,直到子进程运行结束再运行父进程。

 

 

5. 执行程序

执行程序是一个exec族,其中包含:execl,execv,execle,execve,execlp,execvp。我们现在只对其中一个做介绍,因为它们的功能都是差不多的。我们可以自学system这个函数,它的功能和exec类似。

(1) 函数名

execl

(2) 函数原形

int execl(const char *pathname,const char *arg,...);

(3) 函数功能

运行可执行文件

(4) 所属头文件

#include<unistd.h>

(5) 返回值

成功:不返回

失败:有返回

(6) 参数说明

pathname:要运行的可执行文件的路径

arg(包括后面的参数):可执行文件运行需要的参数。

(7) 范例程序

#include<unistd.h>

#include<sys/types.h>

#include<sys/wait.h>

void main()

{

         pid_t pid;

         pid = fork();

         if(pid>0)

         {

                  wait(NULL);

                  printf("father process!\n");//操作1

                  exit(0);

         }

         else

         {

                  execl("/bin/ls","ls","/home",NULL);

                  printf("child process!\n");     //操作2

                  exit(0);

         }

}

运行结果:free test.txt work

          father process!

在子进程中的运行结果和我们直接运行ls命令是一样的。但是子进程中的打印程序没有被显示出来。原因是,当我们运行execl()命令时,我们会保留原有的进程,它后面的内容会被覆盖。这也是它和fork()函数的区别。

 

posted @ 2019-08-13 14:15  free-锻炼身体  阅读(136)  评论(0编辑  收藏  举报