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);
    }
    
  • 相关阅读:
    Windows批处理方式实现MySQL定期自动备份多个数据库
    MySQL数据库中库、表名、字段的大小写问题
    使用modbus4j通过串口解析modbus协议(java)
    mybatis —— 动态sql之if条件判断各种使用方式
    Mysql 获取表的comment 字段
    [转载]如何判断数据库,表或字段是否存在
    设计模式目录
    图片上传及访问
    实现第一个API
    ListView 源码解析
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/11991481.html
Copyright © 2011-2022 走看看