进程

我们平时写的 C 语言代码,通过编译器编译,最终它会成为一个可执行程序,当这个可执行程序运行起来后(没有结束之前),它就成为了一个进程。

程序是存放在存储介质上的一个可执行文件,而进程是程序执行的过程。进程的状态是变化的,其包括进程的创建、调度和消亡。程序是静态的,进程是动态的

在 Linux 系统中,操作系统是通过进程去完成一个一个的任务,进程是管理事务的基本单元。进程拥有自己独立的处理环境(如:当前需要用到哪些环境变量,程序运行的目录在哪,当前是哪个用户在运行此程序等)和系统资源(如:处理器 CPU 占用率、存储器、I/O设备、数据、程序)。我们可以这么理解,公司相当于操作系统,部门相当于进程,公司通过部门来管理(系统通过进程管理),对于各个部门,每个部门有各自的资源,如人员、电脑设备、打印机等。

进程状态

我们现在的电脑基本上都是多任务,我们聊着 QQ 的时候,同时可以看着视频,这里相当于 QQ 和视频两个程序同时运行着(两个进程)。早期的时候,电脑的 CPU 是单核的(单核理论上只运行操作一个任务),那它是如何做到多任务的呢?这就涉及到进程的调度策略。现在给大家举这么一个例子,有 A,B,C 三个进程,在我们单 CPU 的情况下,每一个时刻只有一个进程在运行,如果 A 运行完,B 运行,B 运行完,C 运行,C 运行完,A 运行,而 CPU 的运算速度足够快,A 两次运行时间间隔足够短,从宏观上就我们就看到 A,B,C 好像同时运行,这就是实现单 CPU 运行多个任务的核心原理,通过时间片轮询调度策略实现多任务(更多详情,请看《Linux 进程调度浅析》)

从上面的例子,我们可以得知,对于 A 进程而言,有时候在运行,有时候没有运行,两个状态不一样,所以,进程是有状态的,同时,状态是可以相互进行转换的,从执行的状态转换为不执行的状态,这里,我们可以把进程运行的整个生命周期简单划分为三种状态(实际上不指这三种状态):就绪态、执行态、等待态。

就绪态:

进程已经具备执行的一切条件,正在等待分配 CPU 的处理时间。

执行态:

该进程正在占用 CPU 运行。

等待态:

进程因不具备某些执行条件而暂时无法继续执行的状态。

这里需要注意,就绪态和等待态都是不执行,但它们是有区别的,就绪态是指满足条件,时间没到,等待态是不满足条件。

同样的,进程的这三种状态可以相互转换:

为了让大家更好地这三种状态的转换,给大家举一个买火车票的例子。

Mike 匆忙地赶去火车站买火车票,太着急了,到了售票厅才发现忘记带身份证,这时候,就算 Mike 排队也没用,因为 Mike 不具备买票的条件(没带身份证),这时候的 Mike 属于等待态。

Mike 给它对象打电话,让她把身份证带过来,等会,身份证送到了,这时候,Mike 可以去排队买票了,只是时间到,Mike 就可以买票了,这时,Mike 属于就绪态。而这过程是等待态转换到就绪态

等了 10 分钟,终于到 Mike 了,Mike 开始买票,这时候, Mike 属于执行态。而这过程是由就绪态转换为执行态

而在买票的过程中,Mike 的对象打电话给他,让 Mike 也帮她买一张火车票,但是, Mike 没有她对象的身份证,接着,Mike 继续等他对象送身份证,这时候,Mike由执行态转换为等待态

假如是这么一种情况,Mike 买火车票是给公司的同事买的(需要买 100 多张票),在买着票的过程中(执行态),后面还有很多人在排队,后面排队的人肯定不爽,这时售票员就说,20分钟后,如果你还没处理完,请你到后面排队。结果,Mike 花了 20 分钟还是没有处理完,于是,乖乖地到后面重新排队,这时候,Mike由执行态转换为就绪态

进程控制块

对于操作系统而言,它需要控制很多进程,同时,每个进程都有不同的状态,系统如何知道 A 执行完到 B 执行而不是 C?系统如何协调控制进程呢?

当我们运行一个程序使它成为一个进程时,系统会开辟一段内存空间存放与此进程相关的数据信息,而这个数据信息是通过结构体( task_struct,打开 /usr/include/linux/sched.h 可以找到 task_struct 的定义 )来存放,我们把这个存放进程相关数据信息的结构体称为进程控制块。操作系统就是通过这个进程控制块来操作控制进程。更多详情,请看《 Linux 进程管理》。

进程控制块是操作系统中最重要的记录型数据结构。进程控制块记录了用于描述进程进展情况及控制进程运行所需的全部信息,它是进程存在的唯一标志。进程控制块里有很多信息,其中比较重要的是进程号,至于其他的一些信息我们不在这详细讨论。

进程号

每个进程都由一个进程号来标识,其类型为 pid_t(无符号整型),进程号的范围:0~32767。进程号总是唯一的,但进程号可以重用。当一个进程终止后,其进程号就可以再次使用。

系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型。整个 Linux 系统的所有进程也是一个树形结构。树根是系统自动构造的,即在内核态下执行的 0 号进程,它是所有进程的祖先。进程号为 0 的进程通常是调度进程,常被称为交换进程( swapper )。由 0 号进程创建 1 号进程(内核态),1 号负责执行内核的部分初始化工作及进行系统配置,并创建若干个用于高速缓存和虚拟主存管理的内核线程。随后,1 号进程调用 execve() 运行可执行程序 init,并演变成用户态 1 号进程,即 init 进程

所以,在 Linux 下面所有的进程都由 init 进程直接或者间接创建。

接下来,再给大家介绍三个不同的进程号。

进程号(PID):

标识进程的一个非负整型数。

父进程号(PPID):

任何进程( 除 init 进程)都是由另一个进程创建,该进程称为被创建进程的父进程,对应的进程号称为父进程号(PPID)。如,A 进程创建了 B 进程,A 的进程号就是 B 进程的父进程号。

进程组号(PGID):

进程组是一个或多个进程的集合。他们之间相互关联,进程组可以接收同一终端的各种信号,关联的进程有一个进程组号(PGID) 。这个过程有点类似于 QQ 群,组相当于 QQ 群,各个进程相当于各个好友,把各个好友都拉入这个 QQ 群里,主要是方便管理,特别是通知某些事时,只要在群里吼一声,所有人都收到,简单粗暴。但是,这个进程组号和 QQ 群号是有点区别的,默认的情况下,当前的进程号会当做当前的进程组号

Linux 操作系统提供了三个获得进程号的函数 getpid()、getppid()、getpgid()

所需头文件:

#include <sys/types.h>

#include <unistd.h>

pid_t getpid(void);

功能:

获取本进程号(PID)

参数:

返回值:

本进程号

pid_t getppid(void);

功能:

获取调用此函数的进程的父进程号(PPID)

参数:

返回值:

调用此函数的进程的父进程号(PPID)

pid_t getpgid(pid_t pid);

功能:

获取进程组号(PGID)

参数:

pid:进程号

返回值:

参数为 0 时返回当前进程组号,否则返回参数指定的进程的进程组号

示例代码如下:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char *argv[])
{pid_t pid, ppid, pgid;pid = getpid();printf("pid = %d\n", pid);ppid = getppid();printf("ppid = %d\n", ppid);pgid = getpgid(pid);printf("pgid = %d\n", pgid);return 0;
}

运行结果如下:

【Linux系统编程】进程介绍相关推荐

  1. Linux 系统编程 -进程概念篇

    Linux系统编程-进程篇 冯诺依曼体系结构 冯诺依曼的两个重要思想 当代计算机的三级缓存 操作系统 操作系统的概念 操作系统的组成 操作系统作用 Linux下的操作系统体系 进程 进程概念 进程特性 ...

  2. Linux系统编程——进程基础知识

    Linux系统编程--进程基础知识 1.程序和进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu.内存.打开的文件.设备.锁-) 进程,是一个抽象的概念,与操作系统原理联系紧密.进程 ...

  3. Linux系统编程——进程

    一.进程概念 基础 程序:死的.只占用磁盘空间. --剧本 进程:活的.运行起来的程序.占用内存,cpu等系统资源. --戏 并发 并发的出现基于CPU的发展.然后有了多道程序设计(多进程并发执行). ...

  4. Linux系统编程 进程控制

    文章目录 01. 学习目标 02. 进程和程序 (理解) 03. 单道.多道程序设计(了解) 3.1 单道程序设计 3.2 多道程序设计 04. 并行和并发(理解) 05. MMU(了解) 06. 进 ...

  5. Linux C编程--进程介绍1--进程的创建

    这篇文章介绍的内容包括 1.Linux进程--进程标识号 2.进程控制--进程创建 1.Linux进程--进程标识号 进程(Process)是一个程序在其自身的虚拟地址空间中的一次执行活动.多个程序并 ...

  6. Linux C编程--进程介绍7--综合应用实例

    第一个实例重点说明fork和exec系统函数 该实例是一个交互式命令处理程序,它能完成Linux系统标准Shell的小部分功能,具体功能如下所述: 1.提交命令的参数最多为8个 2.可前,后台执行 3 ...

  7. Linux C编程--进程介绍6--进程的各种标识

    本文将介绍进程的: 1.进程的用户标识号 2.进程标识号 进程的用户ID     Linux/Unix进程涉及到三类用户ID:       1.实际用户ID(real user id,RUID):为该 ...

  8. Linux C编程--进程介绍3--进程终止和等待

    进程结束 1.在Linux中任何让一个进程结束 进程退出表示进程即将结束.在Linux中进程退出分为了正常退出和异常退出两种. 1>正常退出 a. 在main()函数中执行return . b. ...

  9. Linux系统编程——进程替换:exec 函数族

    在 Windows 平台下.我们能够通过双击运行可运行程序.让这个可运行程序成为一个进程:而在 Linux 平台.我们能够通过 ./ 运行,让一个可运行程序成为一个进程. 可是,假设我们本来就执行着一 ...

  10. Linux C编程--进程介绍5--system函数

    表头文件 #i nclude<stdlib.h> 定义函数 int system(const char * string); 这个函数是用fork,exec,waitpid这三个系统函数实 ...

最新文章

  1. 新的一年你该如何起飞
  2. BZOJ 2957: 楼房重建
  3. VC窗口形状的绘制---SetWindowRgn
  4. 使用VS2019创建项目,添加文件和库地址
  5. 英语口语 Week14 Monday
  6. Spring中事务的使用、抽象机制及模拟Spring事务实现
  7. 解决Error: Protected multilib versions:
  8. python ctypes 回调函数_如何用Python中的ctypes创建回调函数?
  9. 实惠星扫地机器人不能开机_扫地机器人不能承受的重量,14kg法斗坐在上面,它旋转后死机...
  10. VmWare工作笔记001---弹出错误提示无法连接mks:套接字连接尝试次数太多
  11. Layui表单账号注册校验密码是否一致
  12. 蓝桥杯 ADV-90 算法提高 输出日历
  13. Python UnicodeEncodeError: ‘gbk‘ codec can‘t encode character 解决方法
  14. 【小教程】完全卸载Adobe Creative Cloud以及删除资源管理器左侧Creative Cloud Files导航栏的最快方法
  15. QT 如何在其他类中修改UI控件的属性?
  16. ce游戏逆向修改之植物大战僵尸
  17. 我的电脑数据执行保护设置不了须是计算机管理员,比使用boot.ini文件。我该怎么办?
  18. 静态库与共享库制作,及区别
  19. CSDN文章转PDF
  20. php 完全前后端分离使用jwt,前后端分离,在 angular 8 中利用 JWT 进行身份认证

热门文章

  1. COM本质论学习笔记(一)IDL
  2. html中的标签在xml中被识别为什么,在strings.xml中定义html标签
  3. phpquery类php,一个基于phpQuery的php通用采集类分享
  4. C语言学习之求1-1/2+1/3-1/4+···+1/99-1/100
  5. 河南城建学院linux期末试题,河南城建学院Linux期末考试复习题
  6. UML大战需求分析阅读笔记——02
  7. Newlife.Net QA
  8. Django(补充CBV,FBV)
  9. Jsoup(二)-- Jsoup查找DOM元素
  10. var和dynamic的区别及如何正确使用dynamic ?