zoukankan      html  css  js  c++  java
  • Linux 进程创建二(execve和wait)

    三:execve系统调用
    int execve(const char *filename, char *const argv[],char *const envp[]);
    fork创建了一个新的进程,产生一个新的PID
    execve用被执行的程序完全替换了调用进程的映像。
    execve启动一个新程序,替换原有进程,所以被执行进程的PID不会改变。
    execve函数接受三个参数
    --path    要执行的文件完整路径
    --argv    传递给程序完成参数列表,包括argv[0],它一般是执行程序的名字,最后一个参数一般是NULL
    --envp    是指向执行execed程序的环境指针,一般设为NULL
    //execve函数的定义
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    
    int main(int arg, char * args[])
    {
        /*
          第一个参数是程序的名字,第二个参数是被调用程序的参数,最后一个参数必须是NULL
          这个跟main函数的参数args数组很相似
         */
        char * argv[]={"/bin/ls","-l",NULL};
        execve("/bin/ls",argv,NULL);
        /*
         execve函数是替换原来的程序代码,但是进程PID不会变,文件描述符不会变,只是程序代码被替换了
         所以execve函数后面的语句都不会被执行
         */
        printf("program is end!
    ");
        return 0;
    }
    wait和waitpid函数可以收集子进程的退出状态
    pid_t wait(int *status);
    pid_t waitpid(pid_t pid, int *status, int options);
    stauts保存子进程的退出状态(本质上就是子进程的返回值,但是我们不能直接查看这个返回值,必须用宏定义转化一下)
    在waitpid函数中,参数pid是等待进程的PID,他能够接受一下四种值
        "<-1"    等待任何PGID等于PID的绝对值子进程
        "-1"    等待任何子进程(这个进程创建的子进程)
        "0"    等待任何PGID等于调用进程的子进程
        ">0"    等待PID等于pid的子进程    
    //wait函数的定义
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    int main(int arg, char * args[])
    {
        pid_t child=0;
        int status=0;
        child=fork();
        if(child==-1)
        {
            printf("system is game over!
    ");
            return -1;
        }
        if(child==0)
        {
            //in child process
            printf("child is begining!
    ");
            sleep(3);
            printf("child is end , now is your turn!
    ");
        }else{
            //in parent process
            printf("parent is begining , i am wait my son!
    ");
            wait(&status);
            printf("child status=%d
    ",WEXITSTATUS(status));
            printf("my son is end , now i am go !
    ");
        }
        printf("all is end!
    ");
        return 10;
    }

     

    用fork或者execve函数创建一个新进程,为了收集新进程的退出状态并且防止出现僵死进程(zombie process),父进程应该调用wait或者waitpid函数等待进程终止。
    僵死进程
    一个僵死进程是在父进程退出之前就终止的子进程(子进程在父进程之前终止,此时因为父进程还没有退出,所以系统会保留子进程的pid,退出
    状态,返回给父进程有wait函数,如果父进程没有wait函数,系统就会一直保持子进程的PID等信息,直到父进程退出)
    之所以被称为僵死进程是因为他虽然死掉了,但依然在进程表中存在。
    子进程退出后分配给他的内存和其他资源都被释放,但是子进程还在内核进程表保留一条,内核在父进程回收子进程的退出状态前一直保留它。
    有一个两个僵死进程不算什么问题,但一旦一个程序频繁执行fork或者execv却又不能手机退出状态,那么最终将会填满进程表(内核进程表是有上限的),这会影响性能,可能导致系统重启

    孤儿进程
    孤儿进程是一个父进程在调用wait或者waitpid之前就已经退出了(即父进程在子进程之前退出)。此时init进程成为子进程的父进程。
    init进程成为子进程的父进程,收集子进程的退出状态,从而避免出现僵死进程。
    注意:任何一个进程都必须有父进程,init的父进程是0号进程,父进程与子进程是相对独立的(子进程会拷贝进程控制器和代码区,写时拷贝数据区),父进程退出,子进程不一定会退出
  • 相关阅读:
    大数据基本概念及Hadoop技术基础
    基于 ReliefF和K-means算法的应用
    利用Hadoop和Spark处理用户心跳周期数据
    Java线程池源码解析及高质量代码案例
    muleESB的第一个开发实例-HelloWorld(二)
    [USACO11JAN]道路和飞机Roads and Planes
    CH6101 最优贸易
    POJ3662 Telephone Lines
    扫描线+线段树例题(HDU1542)
    关于Dinic算法的几点讨论
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5814347.html
Copyright © 2011-2022 走看看