Linux进程初识2

进程状态
为了弄明白正在运行的进程是什么样的,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)

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

这些状态是在kernel源代码中的定义

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

进程状态查看:ps aux
示例:
运行一个上篇博客所写的test代码,博客链接https://editor.csdn.net/md/?articleId=117648040
在这里插入图片描述
复制会话后ps aux | grep test查看这个进程的状态
Linux进程初识2_第1张图片
会列出一些信息,其中S+、R+就是进程所处的状态了,S就代表这这是一个可以中断的睡眠状态了,所以这里直接Ctrl+C(前台应用)就直接可以终止进程了,也可以kill -9 加pid(后台应用)杀掉这个进程。如果是kill -9 也杀不掉,那么这个进程就处于D状态了不可中断睡眠状态。
Z状态(zombie)-僵尸进程

僵死状态(Zombies)是一个比较特殊的状态。当子进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵尸进程,僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

原理:子进程先于父进程退出,父进程来不及回收子进程的资源,导致子进程变成僵尸进程,而子进程对应的task_struct(pcb)还在内核当中,双向链表管理着,对于子进程而言,程序员已经退出了,并不能任何执行任何用户写的代码了;子进程的状态会变成Z状态:刀枪不入!!!

用代码演示下
Linux进程初识2_第2张图片
用给父进程套死循环保证父进程在运行,子进程提前退出的感觉。
Linux进程初识2_第3张图片
再打开另一层会话查看testz的进程状态
在这里插入图片描述
可以看到子进程处于Z(僵尸状态)了
那为什么要有僵尸状态呢?

一个父进程派生了一个子进程, 那么这个父进程有可能想知道,子进程的终止状态。如果父进程没有获取这个状态,那么子进程就变为zombie,直到父进程用wait来获取。如果没有这个状态,子进程直接结束。那么父进程就不会知道子进程的终止状态了。这个终止状态以用来判断子进程终止的原因,有些时候还是挺重要的。比如 ,是不是正常终止,是由什么信号终止的…
僵尸状态的时候,他的task_struct是会被保留的,进程的退出信息是放在进程控制块中的所以能够保存进程基本退出信息,方便进程读取获得退出原因。

产生僵尸进程之后,僵尸进程对应的状态是Z,并且使用kill命令或者强杀命令kill -9,都结束不了僵尸进程。

僵尸进程的危害

产生僵尸进程之后,僵尸进程是不能被强杀杀死的,原因是僵尸进程已经死了,但是操作系统内核双向链表还维护着僵尸进程的task_struct。内核维护这样的结构体,是需要消耗内存的;程序员还结束不了僵尸进程,操作系统就会产生内存泄漏。
那如何如何预防僵尸进程的产生呢?后面再谈。
下面我们来认识另一种进程

孤儿进程
孤儿进程顾名思义那应该是父进程先挂掉吧,与僵尸进程相反,孤儿进程是父进程挂了而子进程还在。
想想父进程先结束了,那么子进程要怎么办,他肯定要被领养的,被谁?
1号进程,在Linux中所有进程都有爹,除了1号进程。1号进程是Linux操作系统当中启动的第一个进程,该进程会启动若干个独立的子进程。所以孤儿进程会被1号init进程领养,由init进程回收。
ps aux | grep 1 查看1号进程
Linux进程初识2_第4张图片

运行
Linux进程初识2_第5张图片
前面子进程的ppid还是他的父进程,但是父进程结束后,他的父进程就变成了1号进程。
Linux进程初识2_第6张图片
Ctrl C杀不掉这个孤儿进程
在这里插入图片描述
kill -9可以杀掉

  • 由于父进程提前退出,所以子进程会被1号进程领养。因此当前进程的父进程变成了1号进程,我们称这样的进程为“孤儿进程”。
  • 需要注意的是孤儿进程不是状态是一种进程。
  • 数据任然是各自私有,代码共享。

进程优先级
基本概念

  • cpu资源分配的先后顺序,就是指进程的优先权(priority)。
  • 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

在linux或者unix系统中,用ps –l命令则会类似输出以下几个内容:
Linux进程初识2_第7张图片

PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高(默认情况下优先级pri=80)
那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为PRI(new)=PRI(old)+nice
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
所以,调整进程优先级,在Linux下,就是调整进程nice值
nice其取值范围是-20至19,一共40个级别
所以pri结合ni后的优先级范围就是[60,99]

所以可以通过修改nice值从而修改进程的优先级。
除非特殊情况,否者不要修改优先级,专业人做专业事,所以这些会有调度器去管理,除非一些必要的操作。

进程具有独立性,比如运行了多个程序,某个进程挂了是不会影响到其他进程的,进程执行时是独占资源的。
Linux进程初识2_第8张图片

进程具有并行性,多个程序运行时,会有进程一直占用CPU到进程结束吗?不会,它是会根据时间片来分配的,但是时间片很短,调度器会根据进程优先级来让进程轮流占用CPU,这样就感觉许多程序就同时跑了起来,这种基于时间片的进程同时推进叫并发。调度器对所有进程都是公平的会让进程对CPU都雨露均沾。

你可能感兴趣的:(Linux操作系统,linux)