进程状态 | 僵尸进程 | 孤儿进程 | 前台后台进程 | 守护进程

2024-02-08 04:04

本文主要是介绍进程状态 | 僵尸进程 | 孤儿进程 | 前台后台进程 | 守护进程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

        • 1.进程的三种基本状态
        • 2.Linux中进程状态查看
          • 2.1.进程检测脚本
          • 2.2.各种状态查看
        • 3.孤儿进程
        • 4.前台、后台、守护进程

1.进程的三种基本状态

进程的在系统当中是走走停停的,「运行 - 暂停 - 运行」的活动规律;进程在活动期间的三种状态:运行状态、就绪状态、阻塞状态

在这里插入图片描述

  • 运行状态(Running):该时刻进程占用 CPU;
  • 就绪状态(Ready):可运行,由于其他进程处于运行状态而暂时停止运行;
  • 阻塞状态(Blocked):该进程正在等待某一事件发生(或等待非CPU资源,如等待输入/输出IO操作的完成)而暂时停止运行,这时,即使给它CPU控制权,它也无法运行;

PCB是描述进程信息的结构体,它是通过链表的方式组织的。如果处于就绪状态的进程链在一起的是运行队列;而处于阻塞状态的进程链在一起的是阻塞队列!在Linux中,就绪和运行态都是R状态。来看看kernel源代码对进程状态的定义:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {"R (running)", /* 0 */"S (sleeping)", /* 1 */"D (disk sleep)", /* 2 */"T (stopped)", /* 4 */"t (tracing stop)", /* 8 */"X (dead)", /* 16 */"Z (zombie)", /* 32 */
};
2.Linux中进程状态查看
2.1.进程检测脚本
while :; do ps axj | head -1 && ps axj | grep mytest;sleep 1;echo "------------------";done更加干净!
while :; do ps axj | head -1 && ps axj | grep mytest | grep -v grep;sleep 1;echo "------------------";done
2.2.各种状态查看

R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队里。测试代码:

#include <stdio.h>
#include <unistd.h>int main()
{while(true){printf("hello world\n");sleep(1);}return 0;
}

测试结果:R+后面的进程代表是一个前台进程

在这里插入图片描述

S睡眠状态(sleeping): 进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep)

#include<stdio.h>
int main()    
{       int a = 0;    printf("请输入一个整数:");                                            scanf("%d",&a);    return 0;    
} 

测试结果:

在这里插入图片描述

D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束,不能被叫醒!

可以使用dd命令来,测试dd命令在处理数据时非常强大,但同时也具有一定的风险性。如果使用不当,可能会导致数据丢失或损坏(建议是不用测试这个状态)

T停止状态(stopped): 可以通过发送 SIGSTOP (kill -19 pid)信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT(kill -18 pid) 信号让进程继续运行。**典型应用:调试!断点能停下来,是因为进程的T状态!**测试代码:

使用命令:kill -19 pid;将进程暂停

使用命令:kill -18 pid;将进程运行

#include <stdio.h>
#include <unistd.h>int main()
{while(true){printf("hello world\n");sleep(1);}return 0;
}

测试结果:

在这里插入图片描述

Z状态:僵尸(死)状态: 当子进程退出,但是父进程没调用waitwaitpid去获取子进程的状态信息,没有检测到子进程返回状态的代码时,子进程就会处于一个被检测的状态,就是僵尸状态。测试代码:

#include<stdio.h>
#include<unistd.h>int main()
{                pid_t ret = fork();if(ret < 0){perror("fork faile\n");return 1;}else if(ret == 0){int cnt = 5;while(cnt){printf("I am child pid = %d\n",getpid());cnt--;sleep(1);}}else    {      while(1)                                                               {    printf("I am father  pid = %d\n",getpid());    sleep(1);}    }    return 0;
}

测试结果:

在这里插入图片描述

僵尸进程的危害:子进程被创建出来,是为了完成父进程交给它的任务,父进程需要读取子进程的返回状态,但是父进程先退出,那么子进程就要一直维护Z状态;系统要一直维护子进程的PCB,那么就会造成内存泄漏。

父进程通过调用wait waitpid进程等待的方式解决僵尸进程问题。

3.孤儿进程

孤儿进程:父进程结束了,而它的一个或多个子进程还在运行,那么这些子进程就成为孤儿进程(father died)。子进程的资源由init进程(进程号PID = 1)回收。

测试代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{pid_t id = fork();if (id < 0){perror("fork");return 1;}else if (id == 0){printf("I am child, pid : %d\n", getpid());sleep(10);}else{ printf("I am parent, pid: %d\n", getpid());sleep(3);exit(0);}return 0;
}

测试结果:

在这里插入图片描述

4.前台、后台、守护进程

前台进程通常是用户正在交互的进程,本质是谁占有键盘资源谁就是前台进程!

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{while(true){printf("hello world\n");sleep(1);}return 0;
}

启动前台进程:./mytest 或输入指令 启动后台进程:./mytest &,从下图可以看到我启动一个前台进程之后,通过键盘输入的 ll cd指令都不管用了。

在这里插入图片描述

启动后台进程:我们程序也在显示器上打印,但是输入的 ll cd 指令可以执行。

在这里插入图片描述

前台进程可以使用信号的方式终止,将程序启动为后台进程发现 ctrl + c 发送信号不能终止进程!使用jobs查看系统运行的任务 使用 fg + 任务号将后台进程转成前台进程,再通过 ctrl + c终止进程!

[xiyan@hecs-34711 ~]$ jobs
[1]+  Running                 ./mytest &  (wd: ~/code/test)
[xiyan@hecs-34711 ~]$ fg 1

任务和进程的关系(一个任务,可以一个人完成,也可多个人完成!)

一个任务可以是一个进程执行也可以是多个进程执行,多个进程组成进程组以第一个进程的进程pid为任务号,一个进程可以自成进程组!通过查看PGID属性字段就能验证。

[xiyan@hecs-34711 test]$ sleep 1000 | sleep 2000 | sleep 3000 &
[1] 6114
[xiyan@hecs-34711 test]$ mytest >> log.txt &
[2] 6141
[xiyan@hecs-34711 test]$ jobs
[1]-  Running                 sleep 1000 | sleep 2000 | sleep 3000 &
[2]+  Running                 ./mytest >> log.txt &
[xiyan@hecs-34711 test]$ ps axj | head -1 && ps xj | grep 'sleep'PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND4559  6112  6112  4559 pts/4     6267 S     1000   0:00 sleep 10004559  6113  6112  4559 pts/4     6267 S     1000   0:00 sleep 20004559  6114  6112  4559 pts/4     6267 S     1000   0:00 sleep 3000
[xiyan@hecs-34711 test]$ ps axj | head -1 && ps xj | grep 'mytest'PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND4559  6141  6141  4559 pts/4     6285 S     1000   0:00 ./mytest

会话的概念

在这里插入图片描述

Linux操作系统中,当一个用户登录的时候会分配一个会话,一个会话期间可以创建多个进程组,退出登录,会话会销毁;会话中前台进程终止,后台进程可能不会终止,但是会受一定的影响。

一个会话有多个进程,但是前台进程只有一个,系统会让bash来,充当前台进程,如果启动一个前台进程,就会将bash替换,当我们自己启动的前台进程退出,又将bash换上来!

退出登录后再登录 , 我的Linux机器是直接就终止了我们程序!如何解决——进程守护化

[xiyan@hecs-34711 test]$ ./mytest >> log.txt &
[1] 12130
[xiyan@hecs-34711 test]$ jobs
[1]+  Running                 ./mytest >> log.txt &
[xiyan@hecs-34711 test]$ ps axj | head -1 && ps axj | grep 'mytest'PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
12035 12130 12130 12035 pts/3    12153 S     1000   0:00 ./mytest
12035 12154 12153 12035 pts/3    12153 R+    1000   0:00 grep --color=auto mytest
[xiyan@hecs-34711 ~]$ ps axj | head -1 && ps axj | grep 'mytest'PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
12181 12214 12213 12181 pts/3    12213 R+    1000   0:00 grep --color=auto mytest

什么是守护进程

将自成进程组自成会话的进程,称为守护进程,他的本质也是孤儿进程;

让会话1创建一个守护进程,当会话1退出守护进程不受影响!

在这里插入图片描述

[xiyan@hecs-34711 ~]$ man 2 setsid
[xiyan@hecs-34711 ~]$ man daemon	# 系统自带的方法

参考代码:

#pragma once#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>const std::string nullfile = "/dev/null";void Daemon(const std::string &cwd = "")
{// 1. 忽略其他异常信号signal(SIGCLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);signal(SIGSTOP, SIG_IGN);// 2. 将自己变成独立的会话if (fork() > 0)exit(0);setsid();// 3. 更改当前调用进程的工作目录if (!cwd.empty())chdir(cwd.c_str());// 4. 标准输入,标准输出,标准错误重定向至/dev/nullint fd = open(nullfile.c_str(), O_RDWR);if(fd > 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}
}

这篇关于进程状态 | 僵尸进程 | 孤儿进程 | 前台后台进程 | 守护进程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/689845

相关文章

Linux中的进程间通信之匿名管道解读

《Linux中的进程间通信之匿名管道解读》:本文主要介绍Linux中的进程间通信之匿名管道解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基本概念二、管道1、温故知新2、实现方式3、匿名管道(一)管道中的四种情况(二)管道的特性总结一、基本概念我们知道多

Linux进程终止的N种方式详解

《Linux进程终止的N种方式详解》进程终止是操作系统中,进程的一个重要阶段,他标志着进程生命周期的结束,下面小编为大家整理了一些常见的Linux进程终止方式,大家可以根据需求选择... 目录前言一、进程终止的概念二、进程终止的场景三、进程终止的实现3.1 程序退出码3.2 运行完毕结果正常3.3 运行完毕

Windows命令之tasklist命令用法详解(Windows查看进程)

《Windows命令之tasklist命令用法详解(Windows查看进程)》tasklist命令显示本地计算机或远程计算机上当前正在运行的进程列表,命令结合筛选器一起使用,可以按照我们的需求进行过滤... 目录命令帮助1、基本使用2、执行原理2.1、tasklist命令无法使用3、筛选器3.1、根据PID

Flutter监听当前页面可见与隐藏状态的代码详解

《Flutter监听当前页面可见与隐藏状态的代码详解》文章介绍了如何在Flutter中使用路由观察者来监听应用进入前台或后台状态以及页面的显示和隐藏,并通过代码示例讲解的非常详细,需要的朋友可以参考下... flutter 可以监听 app 进入前台还是后台状态,也可以监听当http://www.cppcn

linux本机进程间通信之UDS详解

《linux本机进程间通信之UDS详解》文章介绍了Unix域套接字(UDS)的使用方法,这是一种在同一台主机上不同进程间通信的方式,UDS支持三种套接字类型:SOCK_STREAM、SOCK_DGRA... 目录基础概念本机进程间通信socket实现AF_INET数据收发示意图AF_Unix数据收发流程图A

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.

MySQL 中的服务器配置和状态详解(MySQL Server Configuration and Status)

《MySQL中的服务器配置和状态详解(MySQLServerConfigurationandStatus)》MySQL服务器配置和状态设置包括服务器选项、系统变量和状态变量三个方面,可以通过... 目录mysql 之服务器配置和状态1 MySQL 架构和性能优化1.1 服务器配置和状态1.1.1 服务器选项

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例