Linux入门——进程状态

Posted 银背欧尼酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux入门——进程状态相关的知识,希望对你有一定的参考价值。

一,操作系统(Operator System,即OS)

1.操作系统的概念

任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:

  • 内核(进程管理,内存管理,文件管理,驱动管理)
  • 其他程序(例如函数库,shell程序等)

2.设计OS的目的

  • 与硬件交互,管理所有软硬件资源
  • 为用户程序(应用程序)提供一个良好的执行环境

3. 定位

  • 在计算机体系中,操作系统的定位是:一款只负责 “管理” 的软件

4. 如何理解计算机中的管理

  • 描述被管理的对象
  • 组织被管理的对象

计算机管理硬件:

  • 描述:用struct结构体
  • 组织:用链表或其他数据结构

5. 系统调用和库函数

  • 在开发时,操作系统对外会表现为一个整体,但是会暴漏自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
  • 对部分系统调用形成封装,从而形成库,库更有利于开发者进行二次开发。

二,进程

1.概念

一个正在执行的程序。即一个担当分配系统资源(CPU,内存)的实体

2. 描述进程-PCB

储存所有进程属性的集合。PCB即process control block。linux操作系统下的PCB是:task_struct

3. task_struct

linux操作系统下的PCB是:task_struct。task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

4.task_struct内容分类

  • 1.标示符: 描述本进程的唯一标示符,用来区别其他进程

  • 2.状态: 任务状态,退出代码,退出信号等

  • 3.优先级: 相对于其他进程的优先级

  • 4.程序计数器: 程序中即将被执行的下一条指令的地址

  • 5.内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针

  • 6.上下文数据: 进程执行时处理器的寄存器中的数据

  • 7.I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表

  • 8.记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等

    5.组织进程

    可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里

6. PID

进程ID:PID

父进程ID:PPID

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
 printf("pid: %d\\n", getpid());
 printf("ppid: %d\\n", getppid());
 return 0;
}

7.查看进程

进程的信息可以通过/proc系统文件夹查看。如果要获取PID为1的进程,需要查看/proc/1这个文件夹

在这里插入图片描述

8.进程和程序的区别

程序:程序本身是一个文件,是静态的,存储在磁盘中。

进程:程序运行起来之后,就称之为进程,是动态的,是由操作系统来管理的

9.通过系统调用创建进程-fork初识

  • fork有两个返回值
  • 父子进程代码共享,数据各自开辟空间,采用写时拷贝
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
 int ret = fork();
 printf("hello proc : %d!, ret: %d\\n", getpid(), ret);
 sleep(1);
 return 0;
}

fork()返回值小于零说明程序错误,等于0为子进程,大于0为父进程。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;
}

三,进程状态

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

3.1 僵尸进程

子进程退出了,但是父进程没有用wait或waitpid去获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称为僵尸进程。

在这里插入图片描述
在这里插入图片描述

3.1.1 僵尸进程的危害

  • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态。

  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护

  • 那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间

  • 内存泄漏

3.2 孤儿进程

孤儿进程:父进程结束了,而它的一个或多个子进程还在运行,那么这些子进程就成为孤儿进程(father died)。子进程的资源由init进程(进程号PID = 1)回收。

在这里插入图片描述
在这里插入图片描述

四,Linux编译器-gcc/g++的使用

4.1背景知识

代码执行的四个步骤:

  • 1.预处理(进行宏替换)
  • 2.编译(生成汇编)
  • 3.汇编(生成机器可识别代码)
  • 4.连接(生成可执行文件或库文件)

4.2 gcc如何完成

预处理(进行宏替换)

  • 预处理的功能主要包括宏定义,文件包含,条件编译,去注释等。
  • 预处理指令是以#号开头的代码行。
  • 实例:
gcc –E hello.c –o hello.i
  • 选项“-E”,该选项的作用是让gcc在预处理过程结束后停止编译过程。
  • 选项“-o”是指目标文件,“i”文件为已经过预处理的C原始程序。

编译(生成汇编)

  • 在这个阶段中,gcc首先要检查代码的规范性
  • 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
gcc –S hello.i –o hello.s

汇编(生成机器可识别代码)

  • 汇编阶段是把编译阶段生成的“.S”文件转化成目标文件。
  • 读者在此可使用选项"-c"就可看到汇编代码已转化为“.o”的二进制目标代码了
gcc –c hello.s –o hello.o

连接(生成可执行文件或库文件)

  • 在成功编译之后,就进入了链接阶段
gcc hello.o –o hello

以上是关于Linux入门——进程状态的主要内容,如果未能解决你的问题,请参考以下文章

Linux入门——进程状态

Linux入门——进程状态

Linux快速入门教程-进程管理ipcs命令学习

LINUX PID 1和SYSTEMD PID 0 是内核的一部分,主要用于内进换页,内核初始化的最后一步就是启动 init 进程。这个进程是系统的第一个进程,PID 为 1,又叫超级进程(代码片段

嵌入式Linux从入门到精通之第十一节:进程间通信

嵌入式Linux从入门到精通之第十节:系统编程之进程