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号进程,父进程与子进程是相对独立的(子进程会拷贝进程控制器和代码区,写时拷贝数据区),父进程退出,子进程不一定会退出
  • 相关阅读:
    1058 A+B in Hogwarts (20)
    1036. Boys vs Girls (25)
    1035 Password (20)
    1027 Colors in Mars (20)
    1009. Product of Polynomials (25)
    1006. Sign In and Sign Out
    1005 Spell It Right (20)
    1046 Shortest Distance (20)
    ViewPager页面滑动,滑动到最后一页,再往后滑动则执行一个事件
    IIS7.0上传文件限制的解决方法
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5814347.html
Copyright © 2011-2022 走看看