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