0
点赞
收藏
分享

微信扫一扫

#FPGA(基础知识)



在这里插入图片描述


目录


1.进程排队

#include<stdio.h>
int main()
{
	int a;
	scanf("%d",&a);
	printf("%d\n",a);
	return 0;
}

我们执行了文件,但是不输入a的值,那么这个进程一直都会存在,因为它在等待我们输入数据

那为什么我们在Linux系统里写死循环都不会出现程序挂掉的情况呢?
这里我们引入一个概念叫时间片

所谓进程排队,就是进程在等待一个资源
进程 = task_stuct + 可执行程序
那么是task_stuct在排队
还是可执行程序在排队呢?


2.进程状态

进程是一个动态的实体,所以它是有生命的,从创建到消亡,是一个进程的整个生命周期。一般有三个状态。

在这里插入图片描述

  • 事实上所谓的状态,本质是一个整形变量,在task_struct中的一个整形变量
#define New 1   //创建状态
#define Ready 2   //就绪状态
#define running 3    //执行状态
#define block 4   //阻塞状态
  • 状态决定了什么?

状态决定了你的后续动作

运行状态

阻塞状态

结论:状态的变迁,引起的是PCB会被OS变迁到不同的队列中,不同的队列(cpu运行队列,磁盘资源等待队列等等)对应着队列里的进程不同的状态

挂起状态

挂起状态通常发生在系统资源有限,如内存不足的情况下。此时,操作系统会合理地安排内存中的程序,有些进程可能会被暂时调离内存。当系统资源变得充足时,之前被挂起的进程可以再次被调入内存,并恢复到等待执行的就绪状态。挂起状态通常用于以下几种情况:

  1. 终端用户请求。当用户发现程序运行中存在问题,希望暂停程序以便研究或修改时,可以将程序挂起。
  2. 父进程请求。父进程有时希望挂起某个子进程,以便对其进行修改或协调子进程间的活动。
  3. 负荷调节的需要。在实时系统中,当工作负荷较重,可能会影响对实时任务的控制时,系统可能会挂起一些不重要的进程,以确保系统正常运行。
  4. 操作系统的需要。操作系统有时会挂起某些进程,以便检查资源使用情况或进行记账。

需要注意的是,挂起状态与阻塞状态不同。挂起状态是进程主动选择的一种状态,而阻塞状态通常发生在进程等待某些事件(如IO操作)时。

3.Linux下的进程状态

linux系统中,将各种状态进行了重新组织,得到了5种状态。

  1. 运行态-R:正在运行的,以及拿到时间片就能运行的(RUNNING)。
  1. 不可中断休眠态-D(disk IO):不可被打断的阻塞状态(UNINTERRUPTABLE)
  1. 可中断休眠态-S(shallow):可以被打断的阻塞状态(INTERRUPTABLE)
  1. 停止态-T:停止运行(STOPPED)
  1. 僵尸态-Z:程序退出后的中间等待处理状态(ZOMBIE)

状态在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 */
};

查看状态

写一个myprocess.c,并运行

  • 情况一
    在这里插入图片描述
    在这里插入图片描述
    可以看到进程在运行但是右边显示处于S状态,也就是休眠状态,这是为什么?
  • 情况二
    在这里插入图片描述
    在这里插入图片描述
    左边程序疯狂进行输出,但是状态依然是S休眠状态,这又是为什么?
  • 情况三
    在这里插入图片描述
    在这里插入图片描述
    终于可以看到,进程为R状态了,因为这是个死循环

结论:

初遇前台进程和后台进程

在这里插入图片描述
在这里插入图片描述
我们普通运行的进程就是前台进程,可以看到我们在进程运行的时候输入指令是没有用的,并且进程是可以用【Ctrl+C】结束进程的
我们在运行的可执行程序后面加上&

在这里插入图片描述
我们可以看到进程运行过程中输入指令是会打印数据的,并且使用热键【Ctrl+C】是无法结束进程的
这就是后台进程,这里的进程状态从S+变为S
我们结束后台进程需要使用

在这里插入图片描述

查看T状态–停止状态

使用指令kill -19 PID—>让进程处于暂停状态
在这里插入图片描述
也可以使用kill -18 PID—>让进程继续运行
在这里插入图片描述
这个时候使用【Ctrl+C】是结束不了进程的
需要使用kill -9 PID
在这里插入图片描述

查看Z状态–僵尸状态

myprocess.c

 1 #include<stdio.h>
    2 #include<unistd.h>
    3 int main()
    4 {
    5   pid_t id =fork();
    6   if(id == 0)
    7   {
    8     //child
    9     int cnt = 5;
   10     while(cnt)
   11     {
   12       printf("I am child, pid: %d,ppid: %d\n",getpid(),getppid());                    
   13       sleep(1);
   14       cnt--;
   15     }
   16     exit(0);  //让子进程直接退出
   17   }
   18   //father
   19   while(1)
   20   {
   21       printf("I am father, pid: %d,ppid: %d\n",getpid(),getppid());
   22       sleep(1);
   23   }
   24 }

Makefile

myprocess:myprocess.c
		gcc -o $@ $^ #-std=c99
.PHONY:clean
clean:
	rm -f myprocess

查看进程信息代码

运行结果:
在这里插入图片描述

刚开始两个进程都在跑,后来子进程挂掉了,父进程一个人在运行,右边的进程状态可以看到,我们子进程进程状态为z+,子进程成为了僵尸进程

僵尸进程的危害:

  • 进程的退出状态必须被维持下去,因为僵尸进程要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果⼀直不读取,那子进程就⼀直处于Z状态?是的!
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态⼀直不退出,PCB⼀直都要维护?是的!
  • 那⼀个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占⽤用内存,想想C中定义⼀个结构体变量(对象),是要在内存的某个位置进行开辟空间!
  • 内存泄漏?是的!

对于上面进程状态,需要说明的是:

在这里插入图片描述
既然说到了僵尸进程,就不得不提孤儿进程了。

孤儿进程:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
  pid_t id =fork();
  if(id == 0)
  {
    //child
    int cnt = 500;
    while(cnt)
    {
      printf("I am child, pid: %d,ppid: %d\n",getpid(),getppid());
      sleep(1);
      cnt--;
    }
    exit(0);  //让子进程直接退出
  }
  int cnt = 5;
  //father
  while(cnt)
  {
  	  cnt--;   //这里让父进程先行结束
      printf("I am father, pid: %d,ppid: %d\n",getpid(),getppid());
      sleep(1);
  }
}

在这里插入图片描述

在这里插入图片描述

4.查看进程状态相关的常用命令:

PS:显示的进程状态 STAT 列表(与上面的3种状态、5种状态不一样):

在这里插入图片描述

举报

相关推荐

0 条评论