Linux内核源代码中,进程的状态是用数字来表示的,为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在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 */
};
面这张图片展示了进程状态之间的关系,现在我们完全不知道这是什么东西!我们接下来逐一分析。
R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡(interruptible sleep))。
D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
1. 进程各状态的概念
1.1 R-运行态(running)
运行态是进程正在CPU上运行,还是进程只要在运行队列中就叫做运行态呢?
答:所谓的运行态,是只要在运行队列中就叫做运行态,代表我已经准备好了,随时可以被调度!
1.2 终止状态(stopped)
终止状态是这个进程已经被释放,就叫做终止态?还是该进程还在,只不过永远不运行了,随时等待被释放?
答:进程还在,只不过不运行。
此时,我们想问,进程都终止了,为什么不立马释放对应的资源吗,而要维护一个终止态??
答:我们要释放进程需要花费时间,有没有可能,当前操作系统很忙呢。
1.3 运行阻塞
一个进程使用资源的时候,可不仅仅是在申请CPU资源!‘
进程可能申请更多的其他资源:磁盘,网卡,显卡,显示器资源,声卡/音响
如果我们申请CPU资源,暂时无法得到满足,需要排队的–运行队列
那么如果我们申请其他慢设备的资源呢? — 也是需要排队的!(tast_struct在进程排队)
当进程访问某些资源(磁盘,网卡),该资源如果暂时没有准备好,或者正在给其他进程提供服务,此时:1.当前进程要从runqueue中移除;当前进程放入对应设备的描述结构体中的等待队列!(wait_queue)
当我们的进程此时在等待外部资源的时候,该进程的代码不会被执行,此时进程处于的状态叫做进程阻塞。
阻塞是一种临时状态。
1.4 运行挂起
之前我们提到过,代码是存放在磁盘中的,当运行程序时,先将程序加载到内存,那么当内存不足了怎么办?
当内存不足的时候,操作系统会将该进程的代码进行辗转腾挪,如何辗转腾挪–短期内不会被调度的进程,他的代码和数据依然在内存中!就是在白白浪费空间!操作系统就会把该进程的代码和数据置换到磁盘上!此时被暂时置换到磁盘上的进程就叫做进程挂起。
2.Linux 进程状态
2.1 R运行状态
R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
#include <stdio.h>
#include <unistd.h>
int main()
{
while(1)
{
printf("这是一个进程 %d\n",getpid());
sleep(1);
}
return 0;
(base) [jianming_ge@localhost ~]$ ps ajx | head -1 && ps ajx | grep "rrr" | grep -v grep
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
20470 29827 29827 20470 pts/7 29827 S+ 1002 0:21 ./rrr.o
发现运行的进程怎么是S呢? 这是因为printf函数太快了,而显示器显示速度太慢啦,因此这个进程看似实在死循环,其实大多数时间都在等待显示器。那么怎么才能进入运行态呢,我们屏蔽掉printf函数,只保留while循环再次进行查看发现已经处于运行态了。
2.2 S 睡眠状态
s对应的状态一般叫做阻塞状态!
如何把睡眠状态叫醒呢?只需要把进程状态从S睡眠态转换成R运行态即可。
我们常常把S状态叫做浅度睡眠(也叫做可中断睡眠),浅度睡眠可以被唤醒或者杀掉他。
3. 其它
cpulimit 就是不断地把它xx 在running 在两个状态切换。
- cpulimit
cpulimit是一个用于限制进程CPU使用率的工具。它使用cgroups进行管理。
main()
{
while(1);
}
常驻进程的死循环,一直占用100%的cpu。那么我们不像让他占用cpu这么多,所以需要cpulimit来限制它
要在CentOS 7上安装cpulimit,请遵循以下步骤:
-
打开终端并使用root用户登录系统。
-
运行以下命令以更新系统软件包:
yum update
-
安装EPEL存储库。运行以下命令:
yum install epel-release
-
安装cpulimit。运行以下命令:
yum install cpulimit
-
验证cpulimit是否已成功安装。运行以下命令:
cpulimit --version
此命令应该返回cpulimit的版本信息,表示已成功安装。
(base) [jianming_ge@localhost ~]$ climit 20509
-bash: climit: 未找到命令
(base) [jianming_ge@localhost ~]$ cpulimit 20509
Error: You must specify a cpu limit percentage
Usage: cpulimit [OPTIONS...] TARGET
OPTIONS
-l, --limit=N percentage of cpu allowed from 0 to 3200 (required)
-v, --verbose show control statistics
-z, --lazy exit if there is no target process, or if it dies
-i, --include-children limit also the children processes
-h, --help display this help and exit
TARGET must be exactly one of these:
-p, --pid=N pid of the process (implies -z)
-e, --exe=FILE name of the executable program file or path name
COMMAND [ARGS] run this command and limit it (implies -z)
Report bugs to <marlonx80@hotmail.com>.
(base) [jianming_ge@localhost ~]$ cpulimit -p 20509
Error: You must specify a cpu limit percentage
Usage: cpulimit [OPTIONS...] TARGET
OPTIONS
-l, --limit=N percentage of cpu allowed from 0 to 3200 (required)
-v, --verbose show control statistics
-z, --lazy exit if there is no target process, or if it dies
-i, --include-children limit also the children processes
-h, --help display this help and exit
TARGET must be exactly one of these:
-p, --pid=N pid of the process (implies -z)
-e, --exe=FILE name of the executable program file or path name
COMMAND [ARGS] run this command and limit it (implies -z)
Report bugs to <marlonx80@hotmail.com>.
(base) [jianming_ge@localhost ~]$ cpulimit -p 20509 -l 40
Process 20509 found
(base) [jianming_ge@localhost ~]$ cpulimit -p 15452 -l 40
通过这个命令,就把它限制到了40%,其实就是不断的ctrl+z, fg 实现的!!
2. 僵尸进程
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(void)
{
pid_t pid,wait_pid;
int status;
printf("hello world!!!!");
if (pid==-1){
perror("cannot create new process");
exit(1);
} else if(pid==0){
printf("a\n");
return 2;
} else {
printf("b\n");
}
printf("c\n");
while(1);
return 1;
}
这段代码中添加了进程的创建和等待,父进程创建了一个新进程并打印输出 ‘b’,子进程打印输出 ‘a’,然后父进程和子进程都打印输出 ‘c’,并进入了一个死循环,没有正常结束程序的方式。程序中中途没有调用 wait 等待子进程结束,因此子进程的结束状态无法得知,会变成一个僵尸进程。
pid==0 返回的是子进程 else 返回的是父进程
(base) [jianming_ge@localhost process-courses]$ ps aux | grep fork2
jianmin+ 28999 92.9 0.0 4216 356 pts/7 R+ 15:59 0:10 ./fork2.o
jianmin+ 29000 0.0 0.0 0 0 pts/7 Z+ 15:59 0:00 [fork2.o] <defunct>
jianmin+ 29088 0.0 0.0 112828 992 pts/2 S+ 15:59 0:00 grep --color=auto fork2
ref:https://blog.csdn.net/qq_58325487/article/details/126997978