zoukankan      html  css  js  c++  java
  • 3.进程

    一.fork()

    fork()用来创建一个子进程,子进程复制父进程的0-3G空间和父进程内核中的PCB,但子进程和父进程的id号不同。

    fork()调用一次,返回两次

    在父进程中返回子进程的PID,在子进程中返回0。

    例:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    int main()
    {
        pid_t pid;
            
        pid = fork();
        if (pid > 0) {
            printf("cur process is parent
    ");
            printf("cur pid is: %d
    ", getpid());
            printf("cur parent pid is: %d
    ", getppid());
            while(1);
        } else if (pid == 0) {
            printf("cur process is child
    ");
            printf("cur pid is: %d
    ", getpid());
            printf("cur parent pid is: %d
    ", getppid());
            while(1);
        } else {
            perror("fork");
        }
        
        return 0;
    }

    运行结果:

    cur process is parent
    cur pid is: 5924
    cur parent pid is: 2736
    cur process is child
    cur pid is: 5925
    cur parent pid is: 5924

    二.execl()&execv()&execle()&execve()&execlp()&execvp()

    char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
    char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};
    execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
    execv("/bin/ps", ps_argv);
    execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);
    execve("/bin/ps", ps_argv, ps_envp);
    execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
    execvp("ps", ps_argv);

    PS:

    1.只有execve是真正的系统调用,其它五个函数最终都调用execve

    2.由于exec函数只有错误返回值,只要返回了一定是出错了,所以不需要判断它的

    返回值,直接在后面调用perror即可

    例:

    #include <unistd.h>
    #include <stdlib.h>
    
    int main()
    {
        
        // execl("/bin/ls", "ls", "-l", NULL);
        char *const ps_argv[] = {"ps", "aux", NULL};
        //execvp("ps", ps_argv);
        execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
        perror("exec ps");
        exit(1);
        return 0;
    }

    运行结果:

    PID PPID PGRP SESS TPGID COMMAND
    2699 2693 2699 2699 3926 bash
    3926 2699 3926 2699 3926 ps

    三.wait()&waitpid()

    ◆ wait()

    僵尸进程: 子进程退出,父进程没有回收子进程资源(PCB),则子进程变成僵尸进程(Z+)(当子进程运行结束后,其用户空间已被释放,但它的PCB没有被立即释放,等待父进程将其释放)
    孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为1号进程init进程,称为init进程领养孤儿进程

    可使用wait()函数除去僵尸进程

    PS:

    1.wait()函数是一个阻塞函数,等待回收子进程资源,如果没有子进程,wait返回-1
    2.waitpid()函数则是一个非阻塞函数

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    
    int main()
    {
        
        pid_t pid;
        pid = fork();
    
        if (pid > 0) {
            while (1) {
                printf("I am parent process
    ");
                printf("wait for child: %d
    ", wait(NULL));
                sleep(1);
            }
        } else if (pid ==0) {
            printf("I am child process
    ");
            printf("My pid is: %d
    ", getpid());
            sleep(10);
        } else {
            perror("fork");
        }
        
        return 0;
    }

    运行结果:

    I am parent process
    I am child process
    My pid is: 5308
    wait for child: 5308
    I am parent process
    wait for child: -1
    I am parent process
    wait for child: -1
    I am parent process
    wait for child: -1
    I am parent process
    wait for child: -1
    I am parent process
    wait for child: -1
    I am parent process
    wait for child: -1

    ◆ waitpid()

    pid_t waitpid(pid_t pid, int *status, int options);


    < -1 回收指定进程组内的任意子进程
    -1 回收任意子进程
    0 回收和当前调用waitpid一个组的所有子进程
    > 0 回收指定ID的子进程

    WNOHANG 如果没有子进程退出立即返回,这样就实现了非阻塞的wait

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    
    int main()
    {
        pid_t pid;
        pid = fork();
        
        if (pid > 0) {
            while (1) {
                printf("I am parent process
    ");
                pid_t pid_c = waitpid(0, NULL, WNOHANG);
                printf("go to next...
    ");
            }    
        
        } else if (pid == 0) {
            printf("I am child process
    ");
            sleep(10);
        } else {
            perror("fork");
        }
        return 0;
    }

    运行结果:

    I am parent process
    go to next...
    I am parent process
    go to next...
    I am parent process
    go to next...
    I am parent process
    go to next...
    I am parent process
    go to next...
    I am parent process
    go to next...
    I am parent process
    go to next...
    I am parent process
    go to next...

  • 相关阅读:
    10000000000
    vue生命周期
    react基础
    第一个react
    vuex状态管理2
    vue配合UI组件
    vuex
    vue-router配合vue-cli的实例
    vue-router2.0
    父子组件2.0
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/7892553.html
Copyright © 2011-2022 走看看