zoukankan      html  css  js  c++  java
  • 第三季-第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 ");

             exit(0);

    }

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

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

    #include<unistd.h>

    void main()

    {

             pid_t pid;

             pid = fork();

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

             exit(0);

    }

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

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

    #include<unistd.h>

    void main()

    {

             pid_t pid;

             pid = fork();

             if(pid>0)

             {

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

                      exit(0);

             }

             else

             {

                      printf("son process! ");     //操作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! ");//操作1

                      exit(0);

             }

             else

             {

                      printf("son process! ");     //操作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 ",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 ",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! ");//操作1

                      exit(0);

             }

             else

             {

                      printf("child process! ");     //操作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! ");//操作1

                      exit(0);

             }

             else

             {

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

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

                      exit(0);

             }

    }

    运行结果:free test.txt work

              father process!

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

  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    fzu2020软工作业5
    [fiddler] 使用AutoResponder功能修改http响应
    [jest] 史莱姆也能学会的前端测试
    fzu2020软工作业3
    fzu2020软工作业4
    fzu2020软工作业2
    [python] 简易代码量统计脚本
  • 原文地址:https://www.cnblogs.com/free-1122/p/11345610.html
Copyright © 2011-2022 走看看