zoukankan      html  css  js  c++  java
  • 进程控制


    title: 进程控制
    date: 2019/11/30 15:13:40
    toc: true

    进程控制

    fork后的资源

    1. 缓冲区,比如printf等资源没有fflush,缓冲区会被复制到子进程中

    2. 父进程重定向后,子进程也被重定向.父进程的文件描述符都被复制到子进程,类似dup,共享文件表项

      mark

    mark

    1. 子进程继承的属性

      mark

    2. 子进程不继承的属性

      mark

    fork的后续操作

    1. 类似网络服务器多进程,子进程对应一个客户端
    2. 执行exec,执行另外的函数,这种情况下进入exec后原来的文件表项我们用不到了,所以一般会在文件描述符设置标志close-on-exec,也就是这个文件描述符在进入exec后被关闭,但在forkexec间依然可用

    vfork

    https://www.cnblogs.com/1932238825qq/p/7373443.html

    vfork的诞生就是给exec使用,也就是创建一个全新的进程用的

    • fork 是 创建一个子进程,并把父进程的内存数据copy到子进程中。
    • vfork是 创建一个子进程,并和父进程的内存数据share一起用。保证子进程先执行。当子进程调用exit()或exec()后,父进程往下执行

    注意

    结束子进程的调用是exit()而不是return,如果你在vfork中return了,那么,这就意味main()函数return了,注意因为函数栈父子进程共享,所以整个程序的栈就跪了。

    总结

    不用就好了,哈哈

    exit

    mark

    退出状态与终止状态

    • 退出状态: main或者exit,_exit,_Exit的返回值,在最后调用_exit时转换退出状态为终止状态

    • 终止状态,异常终止的原因

    为什么需要僵死进程

    子进程退出,父进程还没处理的.如果父进程先挂,则子进程(孤儿进程)被init收养了

    父进程可能需要了解子进程的退出状态信息,因此系统必须提供这样的服务或者功能

    当一个进程终止时,内核会检查所有的活动进程,也会检查所有的僵尸

    孤儿进程不会变成僵尸进程,因为init会用wait函数来获得其状态也就是如果子进程终止 但是父进程不处理,那么僵死进程就一直存在如果父先于子挂了,子会变为孤儿进程,由init处理

    https://www.cnblogs.com/sinpo828/p/10913249.html

    写代码看看

    #demo1
    # 刚开始两个进程都在
    reallin@ubuntu:/work/pan/apue/study$ ps -ef | grep exe
    reallin    4029   2610  0 19:17 pts/2    00:00:00 ./exe
    reallin    4030   4029  0 19:17 pts/2    00:00:00 ./exe
    # 父进程退出,子进程变成孤儿进程,由init 接管
    reallin@ubuntu:/work/pan/apue/study$ ps -ef | grep exe
    reallin    4030      1  0 19:17 pts/2    00:00:00 ./exe
    
    #demo2 子进程先退出
    # 刚开始两个进程都在
    reallin@ubuntu:/work/pan/apue/study$ ps aux | grep exe
    reallin    4479  0.0  0.0   1048     4 pts/2    S+   19:25   0:00 ./my_tets_exe
    reallin    4480  0.0  0.0   1048    56 pts/2    S+   19:25   0:00 ./my_tets_exe
    # 僵尸进程产生 Z+
    reallin@ubuntu:/work/pan/apue/study$ ps aux | grep exe
    reallin    4479  0.0  0.0   1048     4 pts/2    S+   19:25   0:00 ./my_tets_exe
    reallin    4480  0.0  0.0      0     0 pts/2    Z+   19:25   0:00 [my_tets_exe] <defunct>
    
    
    
    extern "C" { 
        #include "apue.h" 
    }   
    
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #include <sys/types.h>
    #include <unistd.h>
    
    
    
    
    
    void together(void)
    {
        int i=0;
        printf("-------parrent_exit_first-------
    ");
        printf("I am parrent
    ");
        pid_t pid; 
        if((pid=fork())==0) //child
        {
            while(1)
            {
                printf("%4d: I am child,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(5);
            }
        }
        else
        {
            while(1)
            {
                printf("%4d: I am parrent_exit_first,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(5);
            }
        }
    
    }
    
    
    
    void parrent_exit_first(void)
    {
        int i=0;
        printf("-------parrent_exit_first-------
    ");
        printf("I am parrent
    ");
        pid_t pid; 
        if((pid=fork())==0) //child
        {
            while(1)
            {
                printf("%4d: I am child,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(3);
            }
        }
        else
        {
            while(1)
            {
                static int num=0;
                if(num++ >10)
                {
                    printf("parrent_exit_first,pid=%d,ppid=%d
    ",getpid(),getppid());
                    return ;
                }
                printf("%4d: I am parrent_exit_first,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(3);
            }
        }
    
    }
    
    void child_exit_first(void)
    {
        int i=0;
        printf("-------child_exit_first-------
    ");
        printf("I am parrent
    ");
        pid_t pid; 
        if((pid=fork())==0) //child
        {
            while(1)
            {
                static int num=0;
                if(num++ >10)
                {
                    printf("childt_exit_first,pid=%d,ppid=%d
    ",getpid(),getppid());
                    return ;
                }
                printf("%4d: I am child,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(3);
            }
        }
        else
        {
            while(1)
            {
                printf("%4d: I am parrent_exit_first,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(3);
            }
        }
    
    }
    
    
    
    int main(int argc, char const *argv[])
    {
    
        ///together();
        //parrent_exit_first();
        child_exit_first();
        return 1;
    }
    
    

    消除这个僵尸进程

    怎么清理这个僵尸进程呢? 使用wait系列的函数,这个函数就不会看到僵尸状态的子进程了

    void child_exit_first_but_wait(void)
    {
        int i=0;
        printf("-------child_exit_first-------
    ");
        printf("I am parrent
    ");
        pid_t pid; 
        if((pid=fork())==0) //child
        {
            while(1)
            {
                static int num=0;
                if(num++ >5)
                {
                    printf("childt_exit_first,pid=%d,ppid=%d
    ",getpid(),getppid());
                    return ;
                }
                printf("%4d: I am child,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(3);
            }
        }
        else
        {
            while(1)
            {
                pid_t pp=wait(NULL);
                if(pp==pid)
                {
                    printf("I am parent, I know my child has gone
    ");
                }
    
                printf("%4d: I am parrent_exit_first,pid=%d,ppid=%d
    ",i++,getpid(),getppid());
                sleep(3);
            }
        }
    
    }
    

    子进程先结束,但是父进程不去管也不产生僵尸进程

    1. 子进程先结束,父进程需要wait才能避免僵尸进程
    2. 父进程先结束,没有问题,只是孤儿进程
    3. 但是如何让父进程和子进程独立?

    这里fork了两次,实际的子进程由第一个child创建,第一个child立马退出,第二个child由init接管

    #include "apue.h"
    #include <sys/wait.h>
    int
    main(void)
    {
        pid_t pid;
        if ((pid = fork()) < 0)
        {
            err_sys("fork error");
        }
        else if (pid == 0)     /* first child */
        {
            if ((pid = fork()) < 0)
                err_sys("fork error");
            else if (pid > 0)
                exit(0); /* parent from second fork == first child */
            /*
            * We’re the second child; our parent becomes init as soon
            * as our real parent calls exit() in the statement above.
            * Here’s where we’d continue executing, knowing that when
            * we’re done, init will reap our status.
            */
            sleep(2);//-----这里确保first child 先结束
            printf("second child, parent pid = %ld
    ", (long)getppid());
            exit(0);
        }
        if (waitpid(pid, NULL, 0) != pid) /* wait for first child */
            err_sys("waitpid error");
        /*
        * We’re the parent (the original process); we continue executing,
        * knowing that we’re not the parent of the second child.
        */
        exit(0);
    }
    
  • 相关阅读:
    CSS中position小解
    position
    mac默认安装postgresql, 如何让postgresql可以远程访问
    The data directory was initialized by PostgreSQL version 9.6, which is not compatible with this version 10.0.
    active admin gem error
    psql 无法添加超级用户
    ubuntu 15.04 安装Balsamiq Mockups 3
    Rails html 写public里图片的路径
    rails c 历史命令
    undefined local variable or method `per' for []:ActiveRecord::Relation
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/11991481.html
Copyright © 2011-2022 走看看