孤儿僵尸守护进程

news2024/11/29 8:57:58

孤儿僵尸守护进程

  • 1. 孤儿进程:
  • 2. 僵尸进程:
  • 3. 守护进程:==(重点)==

1. 孤儿进程:

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

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

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

杀死某个可执行文件全部的进程
killall 可执行文件名

干点这个进程号
kill -9 进程号

查看mp1.exe这个可执行文件有哪些进程正在执行
ps -ef | grep mp1.exe
可以用下面这个程序进行模拟
// 模拟孤儿进程
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#include <sys/types.h>
#include <sys/wait.h>

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());
    }
}

2. 僵尸进程:

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

  1. 怎么查看僵尸进程:
      利用命令ps,可以看到有标记为的进程就是僵尸进程。
    在这里插入图片描述
  2. 怎样来清除僵尸进程:
    干掉父进程,子进程会有init来回收
eg:
// 模拟僵尸进程
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#include <sys/types.h>
#include <sys/wait.h>

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());
    }*/
}

3. 守护进程:(重点)

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

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

  1. 调用fork(),创建新进程,它会是将来的守护进程.
  2. 在父进程中调用exit,保证子进程不是进程组长
  3. 调用setsid()创建新的会话区
  4. 将当前目录改成根目录(如果把当前目录作为守护进程的目录,当前目录不能被卸载他作为守护进程的工作目录)
  5. 将标准输入,标准输出,标准错误重定向到/dev/null.
    我们来看这个代码:
//守护进程示例
#include <fcntl.h>
#include <unistd.h>

//生成一个守护进程,以后要生成一个守护进程直接复制这个函数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);
}

eg:
// 模拟守护进程
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#include <sys/types.h>
#include <sys/wait.h>

#include <sys/stat.h>
#include <fcntl.h>

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/576465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

认识HTTP协议---2

hi,大家好,今天继续为大家带来HTTP协议相关的知识 认识请求报头 &#x1f440;1.header &#x1f440;2.Content-Type,Content-Length &#x1f440;3.User-Agent &#x1f440;4.Referer &#x1f440;5.Cookie机制 小复习 进入正题之前我们先回忆一下之前的知识 http报…

牛客小白月赛73

A&#xff1a;最小的数字 A-最小的数字_牛客小白月赛73 (nowcoder.com) #include<bits/stdc.h> #define endl \n #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define int long long using namespace std; int n, m, k, A, B, N, M, K; const int ma…

22种transforms数据预处理方法

来源&#xff1a;投稿 作者&#xff1a;阿克西 编辑&#xff1a;学姐 建议搭配视频学习↓ 视频链接&#xff1a;https://ai.deepshare.net/detail/p_5df0ad9a09d37_qYqVmt85/6 1.数据增强&#xff08;data augmentation&#xff09; 数据增强又称为数据增广&#xff0c;数据…

docker安装单机nacos、rocketmq、reids、xxl-job、minio、elasticsearch、kibana、gogs、nginx

目录在右侧中部 启动容器报错 直接删除那个name后边的就可以 安装nacos 首先需要拉取对应的镜像文件&#xff1a;docker pull nacos/nacos-server 挂载目录&#xff1a; mkdir -p /mydata/nacos/logs/ #新建logs目录mkdir -p /mydata/nacos/init.d/ …

最小二乘估计心得

基本思想 存在一组观察值 ( x i , y i ) (x_i, y_i) (xi​,yi​)&#xff0c;其中 y i y_i yi​和 x i x_i xi​之间满足一定的线性关系&#xff0c;如 y a 0 f 0 ( x ) a 1 f 1 ( x ) . . . a m − 1 f m − 1 ( x ) y a_0 f_0(x) a_1 f_1(x) ... a_{m-1} f_{m-1}(x…

改进YOLOv5/YOLOv8:结合华为诺亚VanillaNet Block模块:深度学习中极简主义的力量

YOLOv5结合华为诺亚VanillaNet Block模块 介绍核心代码加入YOLOv5yaml文件:运行结果论文: VanillaNet: the Power of Minimalism in Deep Learning 代码: https://link.zhihu.com/?target=https%3A//github.com/huawei-noah/VanillaNet 介绍 基础模型的核心是 "更多…

Terra-Luna归零一年后:信任重建、加密未来路在何方?

本月既是Terra-Luna归零的一周年&#xff0c;也是FTX崩溃的第六个月&#xff0c;而这两个事件分别代表着2022年加密市场连环爆的开始与高潮&#xff0c;引发了加密行业15年历史上最可怕的生存危机。 尽管今年市场行情有所回暖&#xff0c;比特币开年至今涨幅70%&#xff0c;以太…

【办公类-19-04】办公中的思考——幼儿姓名笔画数统计(单字、全名字)

结果展示--笔画数统计 背景需求 中6班幼儿都能够书写学号&#xff08;基本没有镜像了&#xff09;&#xff0c;于是我开始尝试让幼儿熟悉自己的“姓氏”&#xff0c;并书写姓氏&#xff08;单字&#xff09;。4位幼儿能够默写全名&#xff0c;3位幼儿可以默写名字中的某一个字…

3*5差值结构参照1分类迭代次数比较

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入有3个节点&#xff0c;训练集AB各由5张二值化的图片组成&#xff0c;让A中有6个1&#xff0c;B中全是1&#xff0c;排列组合A &#xff0c;统计迭代次数并排序。共收集到了181个不同的迭代次数&#xff0c;其中有4个 A-B 迭…

创建web后端程序(servlet程序搭建)

目录 一、Servlet概述 二、创建servlet程序 1.创建类继承HttpServlet 2.重写HttpServlet类中 service、destroy、init方法 3.重新启动服务器 一、Servlet概述 Server Applet的简称&#xff0c;用Java编写的服务器端的程序。它运行在web服务器中&#xff0c;web服务器负责…

路径规划算法:基于回溯搜索优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于回溯搜索优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于回溯搜索优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

Android逆向学习之Frida逆向与抓包实战学习笔记(持续更新中)

学习资料:《安卓Frida逆向与抓包实战》陈佳林/著 文章目录 基础环境第三章 Frida逆向入门之Java层hook3.1 frida基础3.1.3frida基础知识frida存在两种操作模式frida操作App的方式有两种 3.1.4Frida IDE配置 3.2 frida脚本入门3.2.1 frida脚本的概念3.2.2 Java层hook基础1.hook…

续---初识HTML!!!(结束篇)

续———初识HTML&#xff01;&#xff01;&#xff01; 一、表单 1.表单的作用 关于表单的作用&#xff1a;表单最大的作用就是收集用户的信息&#xff0c;用户填写表单&#xff0c;点击提交数据给服务器。 2.如何画出表单&#xff1f; 在HTML中我们采用form标签来画一个…

2023 (ICPC) Jiangxi Provincial Contest -- Official Contest

A. Drill Wood to Make Fire 输出即可 #include<bits/stdc.h> #define int long long #define x first #define y second using namespace std; const int N1100; typedef pair<int,int>pii;int m,n; int a[N][N];void solve() {int s,v,n;cin>>n>>s&…

Kali-linux Arpspoof工具

Arpspoof是一个非常好的ARP欺骗的源代码程序。它的运行不会影响整个网络的通信&#xff0c;该工具通过替换传输中的数据从而达到对目标的欺骗。本节将介绍Arpspoof工具的 使用。 9.8.1 URL流量操纵攻击 URL流量操作非常类似于中间人攻击&#xff0c;通过目标主机将路由流量注…

腾讯T4大牛整理的SpringBoot文档,覆盖你认知中的所有操作

SpringBoot目前的使用已经很普遍了&#xff0c;实际的项目中&#xff0c;我们需要集成各种的插件支持&#xff0c;不仅如此&#xff0c;还有很多可能我们平时不知道&#xff0c;但是很方便的操作。pdf里面的东西还是比较全面的。 1、关于文档 2、获得帮助 3、第一 步 4、使…

【Docker】Docker最近这么火,它到底是什么

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

RMP软件管理、YUM源、磁盘管理。

1、RPM软件管理 1> 通过rpm安装vsftpd软件。 去官网找到xsftpdx86的链接。 2> 查询vsftpd软件包的信息。 3> 卸载软件包vsftpd。 2、YUM软件管理 1> 挂载本地光盘&#xff0c;配置yum源为rhel.repo。 2> 通过yum来安装traceroute。 3> 使用yum查询ifconfig命…

详解如何使用LAMP架构搭建论坛

文章目录 1.LAMP概述2.编译安装Apache httpd服务1.关闭防火墙&#xff0c;将安装Apache所需软件包传到/opt目录下2.安装环境依赖包 3.配置软件模块4.编译及安装5.优化配置文件路径&#xff0c;并把httpd服务的可执行程序文件放入路径环境变量的目录中便于系统识别6.添加httpd系…

位图,布隆过滤器,哈希分割

文章目录 &#x1f680;位图&#x1f4a1;概念&#x1f4a1;接口操作 &#x1f680;布隆过滤器&#x1f4a1;思想&#x1f4a1;实现代码&#x1f4a1;实际应用 &#x1f680;哈希分割 &#x1f680;位图 学习位图前&#xff0c;我们先来看一道题 用哈希表存储每个整数&#…