进程及进程状态

1.PCB及task_struct

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
书上称之为 PCB process control block ), Linux 操作系统下的 PCB : task_struct。
task_struct是PCB的一种。
task_struct和PCB之间的关系,打个比方:
就如同王婆和媒婆一样,王婆是媒婆的一种,媒婆是对各种说媒的婆的统称。
在Linux中,描述进程信息的进程控制块,就叫做task_struct.
task_struct  里的内容分类:
标示符 : 描述本进程的唯一标示符,用来区别其他进程。
状态 : 任务状态,退出代码,退出信号等。
优先级 : 相对于其他进程的优先级。
程序计数器 : 程序中即将被执行的下一条指令的地址。
内存指针 : 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据 : 进程执行时处理器的寄存器中的数据 [ 休学例子,要加图 CPU ,寄存器 ]
I O 状态信息 : 包括显示的 I/O 请求 , 分配给进程的 I O 设备和被进程使用的文件列表。
记账信息 : 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息

如何理解进程

进程=对应的代码和数据+对应的task_struct结构 

1.如何查看进程

进程的信息可以通过 /proc 系统文件夹查看 

大多数进程信息同样可以使用top和ps这些用户级工具来获取
TOP命令:

PS命令:

 

PID和PPID可通过系统调用来获取

 

可通过fork来创建子进程

fork的使用:(一般要进行if分流)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
 int ret = fork();
 if(ret < 0){
     perror("fork");
     return 1;
 }
 else if(ret == 0){ //child
     printf("I am child : %d!, ret: %d\n", getpid(), ret);
 }else{ //father
     printf("I am father : %d!, ret: %d\n", getpid(), ret);
 }
 sleep(1);
 return 0;
}

2.进程状态

我个人对进程状态的理解:

运行:task_struct 结构体在运行队列中排队

阻塞:等待非CPU资源就绪

挂起:当内存不足的时候,OS通过适当地调整进程的代码和数据到磁盘,此时进程被OS展示转移到磁盘时的状态,就是挂起状态

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 */
};
R运行状态(running) : 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping) : 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠
interruptible sleep ))。
D磁盘休眠状态(Disk sleep) 有时候也叫不可中断睡眠状态( uninterruptible sleep ),在这个状态的进程通常会等待IO 的结束。
T停止状态(stopped) : 可以通过发送 SIGSTOP 信号给进程来停止( T )进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X死亡状态(dead) :这个状态只是一个返回状态,你不会在任务列表里看到这个状态
Z僵尸状态(zombie)

认识进程状态

 

上面的STAT列就是进程状态,R代表它是运行进程,R后面的+号代表它是前台进程 

观察不难看出来,上面./myproc进程的状态变成了R,没有了+号,此时它是变成了后台进程。

如何理解Z僵尸状态(zombie)

当父进程通过fork来创建子进程后,当子进程退出后,但是还没有被父进程读取,此时子进程就是僵尸进程。

下面通过代码来进程实验:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

int main()
{
	pid_t id = fork();
	if (id < 0)
	{
		perror("fork");
		return 1;
	}
	else if (id > 0)
	{ // parent
		printf("parent[%d] is sleeping...\n", getpid());
		sleep(30);
	}
	else
	{
		printf("child[%d] is begin Z...\n", getpid());
		sleep(5);
		exit(1);
	}
	return 0;
}

结果为:(通过while :; do ps aux | head -1 && ps aux | grep myproc; sleep 1; echo "###########################" ;done;来查看) 

僵尸进程的危害

  1. 资源占用:虽然僵尸进程本身不占用CPU时间,并且它们所占用的内存是微乎其微的,但是它们会保持进程ID。由于Linux系统对进程数有严格的限制,当僵尸进程数量达到一定数目时,会导致系统中无法再产生新的进程,因为新的进程无法使用已经被僵尸进程占用的进程ID。
  2. 系统性能影响:如果系统中存在大量的僵尸进程,会占用一部分系统资源,这可能会影响到服务器的性能,尤其是在高并发或资源密集型的应用场景中。
  3. 系统稳定性问题:僵尸进程的存在可能引发一些潜在的系统稳定性问题。例如,如果父进程因为某种原因(如崩溃或挂起)未能正确清理其僵尸子进程,这些僵尸进程可能会在系统中长时间存在,对系统稳定性构成威胁。

如何避免僵尸进程的产生

父进程应该通过调用waitwaitpid等函数来等待子进程的结束,并获取其退出状态信息。这样,子进程在退出后,其相关资源可以被系统及时释放,避免形成僵尸进程。同时,对于可能产生大量子进程的应用,也需要注意合理管理子进程的生命周期,避免因为子进程管理不当而导致僵尸进程的产生。 

如何理解孤儿进程

当父进程通过fork来创建子进程后,但是父进程先于子进程退出,此时子进程就是孤儿进程,不过此时该进程会被1号 init 进程所领养。

下面通过代码来进程实验:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

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

结果为:通过( while :; do ps ajx | head -1 && ps ajx | grep myproc; sleep 1; echo "###########################" ;done;)来查看

通过上图,我们看到子进程(孤儿进程)被1号 Init 进程领养了。

相关推荐

  1. Linux进程状态

    2024-03-16 04:26:02       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-16 04:26:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-16 04:26:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-16 04:26:02       82 阅读
  4. Python语言-面向对象

    2024-03-16 04:26:02       91 阅读

热门阅读

  1. 力扣131分隔回文串

    2024-03-16 04:26:02       43 阅读
  2. Docker部署ruoyi前后端分离项目 补充

    2024-03-16 04:26:02       50 阅读
  3. asan 使用

    2024-03-16 04:26:02       42 阅读
  4. 电脑上同时安装多个版本的cuda

    2024-03-16 04:26:02       46 阅读
  5. js计算百分比

    2024-03-16 04:26:02       42 阅读
  6. Spring: SpringBoot MybatisPlus框架动态数据源

    2024-03-16 04:26:02       50 阅读
  7. LLM(大语言模型)常用评测指标-MAP

    2024-03-16 04:26:02       45 阅读
  8. 自然语言处理(NLP)技术

    2024-03-16 04:26:02       44 阅读
  9. 总结写力扣题中C++常用的方法

    2024-03-16 04:26:02       43 阅读
  10. TCP的可靠传输

    2024-03-16 04:26:02       51 阅读