【linux】进程状态

简介: 【linux】进程状态

1.创建子进程

由于fork()函数给子进程和父进程返回的pid不同,我们可以根据fork的返回值来对父进程和子进程区分开来

如果返回的id是<0,则创建子进程失败,如果id==0,则说明此进程是子进程,剩下的为父进程.可以写出代码加以验证.

#include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 int main()
  5 {
  6 pid_t id=fork();
  7 if(id<0)
  8 {
  9 perror("fork fail");
 10 
 11 
 12 
 13 }
 14 else if(id==0)
 15 {
 16 while(1)
 17 {  printf("我是子进程 ,pid= %d ppid= %d\n",getpid(),g    etppid());
 18 sleep(1);
 19 
 20                                                       
 21 }}
 22 else{
 23 while(1)
 24 {printf("我是父进程,pid=%d  ppid=%d\n",getpid(),getppid());
   sleep(1);
 26 
 27 
 28 
 29 
 30 
 31 }
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 }}

   
                       

创建makefile,用于代码的编译

 jingchengobj:jingcheng.c
   gcc -o jingchengobj jingcheng.c
 .PHONY:clean
 clean:
   rm -f jingchengobj  

为了方便观察,我们复制ssh渠道

一份代码中两个while(1)同时进行,fork之后有两个不同的执行流


问题1:为什么给子进程返回0,给父进程返回子进程的pid?

因为对应一个父进程可以有好多个子进程,为了区分不同的子进程,来返回给父进程状态,所以给父进程返回自己的pid,而好多子进程只有一个父进程,不用区分,所以给子进程返回0;

问题2:为什么有两个返回值?

问题3:父子进程创建出来,哪个进程会先进行呢??

cpu在执行父进程,可能跑几ms,就会将父进程放到运行队列的尾巴上,可能是父进程需要向磁盘写数据,但是磁盘的队列正在执行别的,只能将父进程链接到cpu的运行队列尾巴上,等待磁盘队列空闲.所以不确谁的运行先后这个是由操作系统调度器确定的.

2.进程状态

先认识几个状态

1.创建:进程刚创建出来

2.运行:task_struct在cpu的运行队列中排队,就叫做运行态

3.阻塞:等待非cpu资源就绪,就称为阻塞状态.

阻塞解释:系统中存在着各种资源,网卡,磁盘,显卡等其他设备,其他设备也会有各自对应的运行队列,当有一个好几个经常分别要向磁盘上写不同的数据,此时的磁盘队列被占用,因为要别的经常写数据,所以会将该进程链接到cpu运行队列尾等待磁盘队列不被占用时,在将进程从运行队列尾移动到头,这个进程状态叫阻塞.

比方说我写了一个c程序,需要printf到显示屏上,我们需要等待显示队列,如果c程序写了一个scanf,我们不给输入,卡住等待键盘就绪(非cpu资源就绪)

4.挂起:

5.挂起阻塞:和cpu没关系,此时在等待非cpu资源同时,且内存不足,需要将有些进程换到swap分区去,这种进程状态叫做挂起阻塞

当os频繁的将进程的数据和代码换入换出,会影响效率,进程太多,os压力大,宕机了.


看看Linux内核源代码怎么说

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在

Linux内核里,进程有时候也叫做任务)。

下面的状态在kernel源代码里定义

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

S睡眠状态: 等待某种资源(可中断睡眠),阻塞状态

代码演示S状态

while(1)
    {
    printf("进程正在执行,该进程的pid=%d\n",getpid());
    sleep(1);
                                                                                                                     
  }

利用命令行局部变量进行循环执行ps命令以便查看其进程状态:

while :; do ps axj | head -1 && ps axj | grep jingchengobj | grep -v grep;sleep 1 ; echo "-----------------------"; done    

此时进程在向显示屏上打印东西,等待非cpu资源就绪(显示屏)

此时可以发现S状态后面有个+号,有加号说明是在前台进程,会占用bash的命令行,当我们在命令行输入其他指令时会无效,当然我们可以将其能变成后台进程,就不会占用我们的命令行了。

前台进程改后台进程

./jingchengobj &

S状态可以通过kill指令来中断

R状态: 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里

代码演示R状态

while(1)
    {
   // printf("进程正在执行,该进程的pid=%d\n",getpid());
   // sleep(1);
                                                                                                                     
  }

当注释掉while循环里面的,就不会占用其他非cpu。

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

T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

kill -l //指令是展示kill指令所有的选项
• 1

停止状态和睡眠状态的区别是,停止状态没有等待其他非cpu资源。

当我们运行该程序时,给个kill 19号信号来暂停进程

此时kill给个18号命令继续进程

t进程状态还有一种就是在gdb调试中,在某一行打上断点,然后运行该程序,遇到断点,停止程序,也是t状态

-g生成debug模式


X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态

当一个进程结束之后,由于操作系统此时要处理好多个退出进程,还来不及来处理的这个退出的进程处于死亡状态(瞬时性特别强)不好演示

z状态:僵尸状态:进程已死,但是要将进程状态给父进程,还没给父进程,此时不允许被os释放,就叫做僵尸状态

举个例子,当使用fork创建子进程,设置子进程睡眠一会,然后退出,父进程必须等待子进程将自己的状态给父进程,此时子进程所处的状态叫做僵尸状态。

代码演示:

#include<stdio.h>
  #include<unistd.h>
   #include<sys/types.h>
   #include<stdlib.h>
int main()
     {
        pid_t id=fork();
      if(id<0)
       {
       perror("fork fail");
     
      
      
      }
      else if(id==0)
      {
     while(1)
      {  printf("我是子进程 ,pid= %d ppid= %d\n",getpid(),g          etppid());
      sleep(3);
      break;                                                    
      
                                                            
      }
      exit(0);}
        else{
     while(1)
      {printf("我是父进程,pid=%d  ppid=%d\n",getpid(),getppid()      );
      sleep(1);
     
     }
                                                               
     }}


目录
相关文章
|
26天前
|
资源调度 Linux 调度
Linux c/c++之进程基础
这篇文章主要介绍了Linux下C/C++进程的基本概念、组成、模式、运行和状态,以及如何使用系统调用创建和管理进程。
29 0
|
3月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
571 2
|
3月前
|
Linux Python
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
64 2
|
1天前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
19 4
linux进程管理万字详解!!!
|
2天前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####
|
3天前
|
消息中间件 存储 Linux
|
9天前
|
运维 Linux
Linux查找占用的端口,并杀死进程的简单方法
通过上述步骤和命令,您能够迅速识别并根据实际情况管理Linux系统中占用特定端口的进程。为了获得更全面的服务器管理技巧和解决方案,提供了丰富的资源和专业服务,是您提升运维技能的理想选择。
10 1
|
21天前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
【10月更文挑战第9天】本文将深入浅出地介绍Linux系统中的进程管理机制,包括进程的概念、状态、调度以及如何在Linux环境下进行进程控制。我们将通过直观的语言和生动的比喻,让读者轻松掌握这一核心概念。文章不仅适合初学者构建基础,也能帮助有经验的用户加深对进程管理的理解。
16 1
|
26天前
|
消息中间件 Linux API
Linux c/c++之IPC进程间通信
这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。
22 0
Linux c/c++之IPC进程间通信
|
26天前
|
Linux C++
Linux c/c++进程间通信(1)
这篇文章介绍了Linux下C/C++进程间通信的几种方式,包括普通文件、文件映射虚拟内存、管道通信(FIFO),并提供了示例代码和标准输入输出设备的应用。
17 0
Linux c/c++进程间通信(1)