zoukankan      html  css  js  c++  java
  • OSLab多进程

    日期:2019/3/23

    内容:Linux下与多进程相关的函数。

    进程基本知识

    • 定义

    应用程序关于某数据集合上的一次运行活动。

    • 特点

    ·操作系统进行资源分配和调度的基本单位

    ·进程是程序的一次执行过程。进程是动态的,程序是静态的。

    ·同一程序同时运行于若干个数据集合上,该程序将对应与若干个不同的进程。

    ·每个进程拥有独立的地址空间。地址空间包括代码段、数据段和堆栈段。

    ·进程之间的地址空间是隔离的。一个进程崩溃不会影响另一个进程,一个进程崩溃不会影响到操作系统。(一个程序开了多个进程,全局变量也不会共享)

    fork函数

    • 作用:创建一个子进程
    • 返回值:

    在父进程中,fork返回新创建子进程的进程PID;

    在子进程中,fork返回0;

    如果出现错误,fork返回一个负值;

    • 实现细节

    ·OS为子进程创建一个PCB(Process Control Block, 进程控制块,其实质是一个结构体)

    ·复制代码和数据到子进程的地址空间(PID不复制)

    • 获取PID

    当前进程

    获取子进程PID

    获取父进程PID

    子进程

    getpid()

    getppid()

    父进程

    pid=fork()

    getpid()

    获取PID代码样例

    /*************************************************************************

        > File Name: testfork.c

        > Author: sinkinben

        > E-mail: sinkinben@qq.com

        > Created Time: Sat 23 Mar 2019 08:13:00 AM CST

    ************************************************************************/

     

    #include <stdio.h>

    #include <unistd.h>

    #include <sys/types.h>

    #include <sys/wait.h>

    int main()

    {

        //pid_t pid = fork();

        pid_t pid;

        pid = fork();

        //sleep(3); //3sec

        if (pid == 0)

            printf("In child process: child pid = %d, parent pid = %d ", getpid(), getppid());

        else

            printf("In parent process: parent pid = %d, child pid = %d ", getpid(), pid);

        wait(NULL);

        return 0;

    }

     

    /*

    * 父进程先于子进程退出

    * init是1号进程,接管子进程

    * 所以in child process, getppid()总是返回1

    * 解决办法:父进程调用sleep

    * 正解:调用wait,让父进程等待子进程结束

    */

     

    • 并发特性与隔离特性

    并发

    ·二者并发运行,输出交织。

    ·代码段相同:父进程从fork返回处执行(返回值为子进程PID);子进程从fork返回处执行(返回值0)

    隔离

    ·地址空间隔离,仅能访问自己的地址空间

    ·出现非法访存,只影响当前进程

    ·全局变量也不共享

    并发和隔离样例代码

    /*************************************************************************

        > File Name: concurrency.c

        > Author: sinkinben

        > E-mail: sinkinben@qq.com

        > Created Time: Sat 23 Mar 2019 08:38:19 AM CST

    ************************************************************************/

     

    #include <stdio.h>

    #include <unistd.h>

    #include <stdlib.h>

    static int global = 0;

    void child()

    {

        int i = 0;

        for (i = 0; i < 5; i++)

        {

            puts("child");

            printf("global = %d ", global++);

            sleep(1);

        }

    }

    void parent()

    {

        int i = 0;

        for (i = 0; i < 5; i++)

        {

            puts("parent");

            printf("global = %d ", global++);

            sleep(1);

        }

    }

     

    int main()

    {

        pid_t pid = fork();

        if (pid)

            parent();

        else

            child();

        return 0;

    }

     

    运行结果

    exec系列

    名词解析:

    exec:execute

    l:list,表示参数是列表形式

    v:vector,表示参数是数组形式

    p:path,允许exec系列函数使用系统环境变量PATH下的路径

    全家桶如下。

    头文件:unistd.h

    返回值:成功无返回值,失败-1.

    函数

    原型

    描述

    execl

    int execl(const char *path, const char *arg, ...

    ·当前进程地址空间清空

    ·将path指定的可执行程序的代码和数据装入当前地址空间

    ·参数可变,最后一个必须NULL

    ·可以是相对/绝对路径

    ·失败原因存于errno(一个Linux全局变量)中,可通过perror()打印。

    ·execl成功的话,会执行另外的程序,因此成功无返回值。

    ·参数格式:路径+程序名+参数1,2,3...,NULL

    execv

    int execv(const char *path, char *const argv[]);

    ·argv数组最后一项必须为NULL

    ·argv[]={程序名,参数1,2,3...,NULL}

    ·参数格式:路径+argv

    execlp

    int execlp(const char *file, const char *arg, ...

    ·允许使用PATH环境变量作为参数file

    execvp

    int execvp(const char *file, char *const argv[]);

    execl样例代码

    /*************************************************************************

        > File Name: testexecl.c

        > Author: sinkinben

        > E-mail: sinkinben@qq.com

        > Created Time: Sat 23 Mar 2019 08:52:03 AM CST

    ************************************************************************/

     

    #include <stdio.h>

    #include <unistd.h>

    int main()

    {

        puts("before execl");

        int error_code = execl("/bin/echo", "echo", "sin", "cos", NULL);

        if (error_code < 0)

            perror("error execl");

        puts("after execl");

        return 0;

    }

     

    execv样例代码

    /*************************************************************************

        > File Name: testexecv.c

        > Author: sinkinben

        > E-mail: sinkinben@qq.com

        > Created Time: Sat 23 Mar 2019 08:59:16 AM CST

    ************************************************************************/

     

    #include <stdio.h>

    #include <unistd.h>

    int main()

    {

        puts("before execv(p)");

        char *argv[] = { "ls", "-a", NULL};

        //int error = execv("/bin/ls",argv);

        int error = execvp("ls", argv);

        if(error == -1)

            perror("error");

        puts("after execv(p)");

        return 0;

     

    }

     

    exit

    ·头文件:stdlib.h

    ·原型:void exit(int status);

    ·功能

    >>正常退出当前进程

    >>将status & 0XFF作为退出码返回给父进程

    ·预定义常量

    >>EXIT_SUCCESS, 为0,表示正常退出

    >>EXIT_FAILURE,为非0,表示异常退出

    >>在Linux shell中,$?可以获取程序的退出码

    ·main与exit

    >>return 0 相当于exit(SUCCESS)

    >>return !0 相当于exit(FAILURE)

    >>start.asm(计算机组成原理知识:main返回的上一层是start.asm)

    global _start

    extern main

    extern exit

    _start:

    call main

    add esp,

    push eax //作为参数eax->[ebp+8]传给exit

    call exit

    add esp, 4

    hlt

    exit与$?代码实例

    #include <stdio.h>

    #include <stdlib.h>

    int main()

    {

        exit(233);

    }

    运行结果

    atexit

    ·头文件:stdlib.h

    ·原型:int atexit(void (*function)(void)); (参数是函数指针)

    ·功能

    >>注册回调函数,进程正常结束时,function被调用

    >>如果注册多个,以与注册相反的顺序调用

    wait

    ·头文件:sys/types.h, sys/wait.h

    ·原型:pid_t wait(int *status);

    ·功能

    >>等待子进程结束

    >>如果status非空,子进程退出码保存在status

    ·退出码

    进程可能由于不同原因退出。主动调用exit退出,或接收信号退出。

    查询退出原因的宏

    WIFEXITED(status)

    当子进程exit(0)时,为真。

    WEXITSTATUS(status)

    当子进程exit(!0)时,返回退出码

    WIFSIGNALED(status)

    当子进程接收信号后退出,为真

    WTERMSIG(status)

    当子进程接收信号后退出,返回导致退出的信号码

  • 相关阅读:
    listView控件演示程序
    猪悟能淘宝商品下载专家v3版开发手记
    c# WebClient类
    分隔控件splitter演示程序
    C#中SESSIONID的获取
    工具栏toolBar演示程序
    Cookie总结
    C#获取网页源码并且自动判断网页字符集编码
    如何在Google Code上建立私有代码版本库
    iOS应用程序生命周期(前后台切换,应用的各种状态)详解
  • 原文地址:https://www.cnblogs.com/sinkinben/p/10584478.html
Copyright © 2011-2022 走看看