• 孤儿僵尸守护进程


    1. 孤儿进程:

    父进程退出,还没退出的子进程就变成了孤儿进程

    不要怕,还有爷爷进程init:
    孤儿进程将被init进程所收养,并由init进程对它们完成状态收集工作。
    省流:父先退出,但子还未退出

    想想我们如何模仿一个孤儿进程? 答案是: kill 父进程!

    杀死某个可执行文件全部的进程
    killall 可执行文件名
    
    干点这个进程号
    kill -9 进程号
    
    查看mp1.exe这个可执行文件有哪些进程正在执行
    ps -ef | grep mp1.exe
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    可以用下面这个程序进行模拟
    // 模拟孤儿进程
    #define _GNU_SOURCE
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    
    typedef void (*spawn_proc_pt)(void *data);
    static void worker_process_cycle(void *data);
    static void start_worker_processes(int n);
    pid_t spawn_process(spawn_proc_pt proc, void *data, char *name);
    
    int main(int argc, char **argv)
    {
        start_worker_processes(4); // 4核cpu
                                   // 管理子进程
        wait(NULL);
        // printf("parent is over!\n");
        // return 0;
    }
    
    void start_worker_processes(int n)
    {
        int i = 0;
        for (i = n - 1; i >= 0; i--)
        {
            spawn_process(worker_process_cycle, (void *)(intptr_t)i, "worker process");
        }
    }
    
    pid_t spawn_process(spawn_proc_pt proc, void *data, char *name)
    {
    
        pid_t pid;
        pid = fork();
    
        switch (pid)
        {
        case -1:
            fprintf(stderr, "fork() failed while spawning \"%s\"\n", name);
            return -1;
        case 0:
            proc(data);
            return 0;
        default:
            break;
        }
        printf("start %s %ld\n", name, (long int)pid);
        return pid;
    }
    
    static void worker_process_init(int worker)
    {
        cpu_set_t cpu_affinity; // cup亲人
        // worker = 2;
        // 多核高并发处理  4core  0 - 0 core 1 - 1  2 -2 3 -3
        CPU_ZERO(&cpu_affinity);
        CPU_SET(worker % CPU_SETSIZE, &cpu_affinity); // 0 1 2 3
        // sched_setaffinity
        if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_affinity) == -1)
        {
            fprintf(stderr, "sched_setaffinity() failed\n");
        }
    }
    
    void worker_process_cycle(void *data)
    {
        int worker = (intptr_t)data;
        // 初始化
        worker_process_init(worker);
    
        // 干活
        for (;;)
        {
            sleep(10);
            printf("pid %ld ,doing ...\n", (long int)getpid());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    2. 僵尸进程:

    一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
      省流:子先退出,父未调用wait或waitpid

    1. 怎么查看僵尸进程:
        利用命令ps,可以看到有标记为的进程就是僵尸进程。
      在这里插入图片描述
    2. 怎样来清除僵尸进程:
      干掉父进程,子进程会有init来回收
    eg:
    // 模拟僵尸进程
    #define _GNU_SOURCE
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    
    typedef void (*spawn_proc_pt)(void *data);
    static void worker_process_cycle(void *data);
    static void start_worker_processes(int n);
    pid_t spawn_process(spawn_proc_pt proc, void *data, char *name);
    
    int main(int argc, char **argv)
    {
        start_worker_processes(4); // 给虚拟机配置了2核
        // 管理子进程
        // wait(NULL);
        for (;;) // 父不退出,子退出时父不使用wait或waitpid进行回收=>僵尸进程
        {
            sleep(1);
        }
    
        return 0;
    }
    
    void start_worker_processes(int n)
    {
        int i = 0;
        for (i = n - 1; i >= 0; i--)
        {
            spawn_process(worker_process_cycle, (void *)(intptr_t)i, "worker process");
        }
    }
    
    pid_t spawn_process(spawn_proc_pt proc, void *data, char *name)
    {
    
        pid_t pid;
        pid = fork();
    
        switch (pid)
        {
        case -1:
            fprintf(stderr, "fork() failed while spawning \"%s\"\n", name);
            return -1;
        case 0:
            proc(data);
            return 0;
        default:
            break;
        }
        printf("start %s %ld\n", name, (long int)pid);
        return pid;
    }
    
    static void worker_process_init(int worker)
    {
        cpu_set_t cpu_affinity; // cup亲人
        // worker = 2;
        // 多核高并发处理  4core  0 - 0 core 1 - 1  2 -2 3 -3
        CPU_ZERO(&cpu_affinity);
        CPU_SET(worker % CPU_SETSIZE, &cpu_affinity); // 0 1 2 3
        // sched_setaffinity
        if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_affinity) == -1)
        {
            fprintf(stderr, "sched_setaffinity() failed\n");
        }
    }
    
    void worker_process_cycle(void *data)
    {
        int worker = (intptr_t)data;
        // 初始化
        // worker_process_init(worker);
        exit(1); // 子进程退出
        // 干活
        /*for (;;)
        {
            sleep(10);
            printf("pid %ld ,doing ...\n", (long int)getpid());
        }*/
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

    3. 守护进程:(重点)

    不与任何终端关联的进程,通常情况下守护进程在系统启动时就在运行,它们以root用户或者其他特殊用户(apache和postfix)运行,并能处理一些系统级的任务。守护进程脱离于终端,是为了避免进程在执行过程中的信息在任何终端上显示,并且进程也不会被任何终端所产生的终端信息所打断(比如关闭终端等)。

    那如何成为一个守护进程呢? 步骤如下:

    1. 调用fork(),创建新进程,它会是将来的守护进程.
    2. 在父进程中调用exit,保证子进程不是进程组长
    3. 调用setsid()创建新的会话区
    4. 将当前目录改成根目录(如果把当前目录作为守护进程的目录,当前目录不能被卸载他作为守护进程的工作目录)
    5. 将标准输入,标准输出,标准错误重定向到/dev/null.
      我们来看这个代码:
    //守护进程示例
    #include 
    #include 
    
    //生成一个守护进程,以后要生成一个守护进程直接复制这个函数daemon(0,0)
    int daemon(int nochdir, int noclose)//0 0
    {
        int fd;
    
        switch (fork()) {
        case -1://错误
            return (-1);
        case 0://子进程
            break;
        default://父进程
            _exit(0);
        }
    
        if (setsid() == -1)
            return (-1);
    
        if (!nochdir)//!0 = 1
            (void)chdir("/");//将当前目录改成根目录
    
    	//!0 = 1
        if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
            (void)dup2(fd, STDIN_FILENO);//将标准输入,标准输出,标准错误重定向到/dev/null.
            (void)dup2(fd, STDOUT_FILENO);
            (void)dup2(fd, STDERR_FILENO);
            if (fd > 2)
                (void)close (fd);//重定向之后就干掉fd
        }
        return (0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    eg:
    // 模拟守护进程
    #define _GNU_SOURCE
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    
    #include 
    #include 
    
    typedef void (*spawn_proc_pt)(void *data);
    static void worker_process_cycle(void *data);
    static void start_worker_processes(int n);
    pid_t spawn_process(spawn_proc_pt proc, void *data, char *name);
    
    // 生成一个守护进程
    int daemon(int nochdir, int noclose) // 0 0
    {
        int fd;
    
        switch (fork())
        {
        case -1: // 错误
            return (-1);
        case 0: // 子进程
            break;
        default: // 父进程
            _exit(0);
        }
    
        if (setsid() == -1)
            return (-1);
    
        if (!nochdir)         //! 0 = 1
            (void)chdir("/"); // 将当前目录改成根目录
    
        //! 0 = 1
        if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1)
        {
            (void)dup2(fd, STDIN_FILENO); // 将标准输入,标准输出,标准错误重定向到/dev/null.
            (void)dup2(fd, STDOUT_FILENO);
            (void)dup2(fd, STDERR_FILENO);
            if (fd > 2)
                (void)close(fd); // 重定向之后就干掉fd
        }
        return (0);
    }
    
    int main(int argc, char **argv)
    {
        start_worker_processes(4); // 4核cpu
                                   // 管理子进程
        wait(NULL);
        // printf("parent is over!\n");
        // return 0;
    }
    
    void start_worker_processes(int n)
    {
        int i = 0;
        for (i = n - 1; i >= 0; i--)
        {
            spawn_process(worker_process_cycle, (void *)(intptr_t)i, "worker process");
        }
    }
    
    pid_t spawn_process(spawn_proc_pt proc, void *data, char *name)
    {
        daemon(0, 0); // 成为守护进程//
        pid_t pid;
        pid = fork();
    
        switch (pid)
        {
        case -1:
            fprintf(stderr, "fork() failed while spawning \"%s\"\n", name);
            return -1;
        case 0:
            proc(data);
            return 0;
        default:
            break;
        }
        printf("start %s %ld\n", name, (long int)pid);
        return pid;
    }
    
    static void worker_process_init(int worker)
    {
        cpu_set_t cpu_affinity; // cup亲人
        // worker = 2;
        // 多核高并发处理  4core  0 - 0 core 1 - 1  2 -2 3 -3
        CPU_ZERO(&cpu_affinity);
        CPU_SET(worker % CPU_SETSIZE, &cpu_affinity); // 0 1 2 3
        // sched_setaffinity
        if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_affinity) == -1)
        {
            fprintf(stderr, "sched_setaffinity() failed\n");
        }
    }
    
    void worker_process_cycle(void *data)
    {
        int worker = (intptr_t)data;
        // 初始化
        worker_process_init(worker);
    
        // 干活
        for (;;)
        {
            sleep(10);
            printf("pid %ld ,doing ...\n", (long int)getpid());
        }
    }
    
    wxncom@wxncom-virtual-machine:~/shared_bike/demo/fork_demo$ gcc multip_process_3.c -o mp3.exe
    wxncom@wxncom-virtual-machine:~/shared_bike/demo/fork_demo$ ./mp3.exe
    wxncom@wxncom-virtual-machine:~/shared_bike/demo/fork_demo$ ps -ef | grep mp3.exe
    wxncom     3023      1  0 17:21 ?        00:00:00 ./mp3.exe
    wxncom     3025      1  0 17:21 ?        00:00:00 ./mp3.exe
    wxncom     3027      1  0 17:21 ?        00:00:00 ./mp3.exe
    wxncom     3028      1  0 17:21 ?        00:00:00 ./mp3.exe
    wxncom     3029   3028  0 17:21 ?        00:00:00 ./mp3.exe
    wxncom     3034   1646  0 17:23 pts/1    00:00:00 grep --color=auto mp3.exe
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
  • 相关阅读:
    Java中 创建不可变集合
    2022-11-11 myql Block Nested-Loop and Batched Key Access Joins
    makdown文法
    centos start ssh service
    暑假加餐|有钱人和你想的不一样(第16天)+基于蒙特卡罗的电力系统可靠地评估(Matlab代码实现)
    mysql-installer安装教程(详细图文)
    python+selenium自动化测试项目实战
    HTTP响应状态码
    Cholesterol-PEG-Thiol,CLS-PEG-SH,胆固醇-聚乙二醇-巯基改善胆固醇溶解度
    Linux篇16进程信号第一部分
  • 原文地址:https://blog.csdn.net/weixin_52668597/article/details/130902504