博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Linux】进程控制(一):进程概念和进程创建 fork 和 vfork
阅读量:4156 次
发布时间:2019-05-25

本文共 2787 字,大约阅读时间需要 9 分钟。

【Linux】进程概念和进程创建 fork 和 vfork

文章目录


一、进程

1.1 进程概念

  程序: 程序是一个文本文件,是静态的

  进程: 进程是程序运行起来的一个表现形式,是操作系统分配资源的最小单位,在操作系统内核中,为进程创建一个 task_struct 的结构体,称之为 PCB (Process Control Block, 进程控制块),它是进程属性的集合。

   进程是程序运行起来的一种表现形式,是操作系统分配资源的最小单位。

   进程资源管理的最小单位,线程程序执行的最小单位。Linux 下的线程本质是用进程实现操作系统通过 PCB 实现对程序运行调度的控制。


1.2 进程控制块 (PCB)

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

  task_struct中包含的进程信息有:进程标识符 (PID)、状态、优先级、程序计数器、上下文数据、内存指针、I/O 状态信息、记账信息以及其它信息。

(1) 进程标识符PID

  描述本进程的位图标识符,在当前操作系统中不会重复

(2) 进程状态

  运行状态: 正在CPU上面进行运算

  就绪状态: 程序已经准备好了,在就绪队列中等待获取CPU资源

  阻塞状态: 等待 I/O 就绪

并发执行: 多个进程使用同一 CPU,每个进程都独占 CPU 一小会儿,操作系统进行进程切换,让每一个进程都可以使用 CPU

并行执行: 多个进程,在同一时刻,每一个进程都独占一个 CPU 进行运算

image-20210622103159375

  在操作系统内核中,具体的进程状态有:

  R:运行状态

  S:可中断睡眠状态
  D:磁盘睡眠状态,不可被打断
  T:暂停状态
  t:跟踪状态,gdb调试程序时进程就处于 t 状态
  X:死亡状态
  Z:僵尸状态

补充:

  “+”: 代表前台进程

   没有 “+”: 代表后台进程

   fg : 将最后一次放在后台的进程放入前台来运行

(3) 程序计数器

  保存进程即将要执行的下一条指令 ,为下一次恢复现场使用

(4) 上下文数据

  保存上一次执行时寄存器当中的值

补充:

  • 进程在执行的时候,进程会进行切换,切换是操作系统调度的。
  • 在被切换出去的时候,该进程当中的程序计数器会保存程序要执行的下一条指令上下文信息会保存寄存器当中的值
  • 再次切换回来的时候,通过程序计数器和上下文信息来恢复之前的场景,继续进行。

(5) 进程优先级PR

  PR(new) = PR(old) + NICE ,其中 NICE 的范围在 [-20,19],一共40个级别。PR 值越大,优先级越低,反之则优先级就越高。top 可以查看系统资源消耗情况。

补充:

  top 命令更改已存在进程的 NICE

  ① top; ② 进入 top 后输入 “r”; ③ 输入进程PID; ④ 输入 NICE 值

(6) 内存指针

  内存指针指向了程序地址空间

(7) I/O信息和记账信息

  记录当前进程启动时间,记录当前进程占用 CPU 的时间。ll /proc/[PID]/fd 打开文件信息


   总结:

  操作系统内核是用 task_struct 结构体来描述进程,用双向链表来组织进程的

在这里插入图片描述

image-20210621171727950


二、进程创建

2.1 fork函数

#include 
pid_t fork(void);

  让已经启动的程序(父进程)调用 fork 函数,来创建子进程,子进程的 PCB (task_struct) 是拷贝父进程的。下面例子可以理解子进程是拷贝父进程的PCB。

#include
#include
int main(){
printf("---begin---"); fork(); printf("fork 函数创建子进程"); return 0;}

在这里插入图片描述


2.2 fork函数的返回值

#include 
pid_t fork(void);

  fork函数有返回值:

  • 子进程创建失败,返回小于0的值

  • 子进程创建成功,返回两次。父进程中返回大于0的值(子进程的PID),子进程中返回值等于0

    #include 
    int main(){
    pid_t ret = fork(); if(ret < 0) {
    //创建子进程失败 } else if(ret > 0) {
    //父进程 } else {
    //子进程 } return 0;}

  通过返回值的不同,可以让父进程执行不同的代码


2.3 PID 和 PPID

  • 通过 ps -ef | grep [程序名称] 或者 ps aux | grep [程序名称] 查看父/子进程的PID,从而确定哪个是子进程,哪个是父进程。

  • 一旦子进程创建成功,父/子进程是抢占式执行

  • 通过终端启动的前台进程的父进程是 bash(命令行解释器)。

   还可以通过函数获取进程的PID和PPID

#include 
#include
pid_t getpid(void); //谁调用获取谁的进程PID pid_t getppid(void); //谁调用获取谁的父进程PID

2.4 vfork

#include 
#include
pid_t vfork(void)

  vfork 函数也是用来创建子进程的函数,vfork 函数创建出来的子进程拷贝父进程的 PCB,并且子进程 PCB 当中的内存指针指向了父进程的进程虚拟地址空间,也就是说父子进程共用同一块进程虚拟地址空间。从下面这幅图也可以看出它们之间的区别。

在这里插入图片描述
  但是,vfork 存在一个问题在于,父子进程指向同一块进程虚拟地址空间,如果父子进程同时并行运行,有可能导致函数调用栈混乱的问题,vfork 的解决方法是让子进程先运行,等子进程结束后,再让父进程运行。

  相关推荐文章:

  

  


  总结:

  1. 调用 fork 函数,fork 函数是一个系统调用

  2. 父进程调用 fork 函数创建子进程,子进程拷贝父进程的 PCB (task_struct),父进程和子进程是独立的两个进程

  3. 子进程从 fork 函数之后的代码开始运行,程序计数器(保存了程序即将要执行的下一条指令)+ 上下文信息(保存了寄存器当中的值)

  4.子进程和父进程是代码共享,数据独有

转载地址:http://lnwxi.baihongyu.com/

你可能感兴趣的文章
关于多目标跟踪的一点理解
查看>>
Learning by tracking:Siamese CNN for robust target association
查看>>
MUSTer:Multi-Store Tracker:A Cognitive Psychology Inspired Approach to Object Tracking
查看>>
Understanding and Diagnosing Visual Tracking Systems
查看>>
Multiple People Tracking by Lifted Multicut and Person Re-identification
查看>>
Visual Tracking Using Attention-Modulated Disintegration and Integration
查看>>
Action-Decision Networks for Visual Tracking with Deep Reinforcement Learning
查看>>
Multiple Object Tracking with High Performance Detection and Appearance Feature
查看>>
深度学习入门(上)-第一章 必备基础知识点
查看>>
Python中使用中文
查看>>
Python绘图详解
查看>>
Python 各种IDE比较
查看>>
ImportError: No module named cv2 解决方法
查看>>
python中if __name__ == '__main__': 的解析
查看>>
ubuntu unzip解压时提示错误 解决方法
查看>>
sprintf函数的说明
查看>>
BOOST_TYPEOF和BOOST_AUTO 作用
查看>>
白化原理及Matlab实现
查看>>
随机森林概述
查看>>
applet部署,无需修改客户端设置。
查看>>