当前位置: 首页 > news >正文

Linux编程1:进程和线程

进程和线程


1.进程
1.进程基本概念

  • 进程:是程序动态执行的过程,包括创建、调度、消亡。
  • 程序:存放在外存中的一段数据的集合

2.进程创建

1进程空间分布

  • 每个进程运行起来后,操作系统开辟0-4G虚拟内存空间
  • 空间:用户空间+内核空间(无法访问)
  • 进程用户空间:文本段(文本区)+数据段(数据区)+系统数据段(堆区、栈区)
    • 文本段:存放代码和指令
    • 数据段:字符串常量、已初始化全局变量/静态变量,未初始化全局变量/静态变量
    • 系统数据段:堆区(malloc空间)、栈区(局部变量、函数运行)

  • 数据区存放数据特点:
  • 未经初始化为0值
  • 编译时开辟空间
  • 程序结束时回收空间
  • 堆区存放数据特点:
    • malloc申请堆区空间
    • free释放堆区空间
    • 注意:避免未释放空间导致内存泄漏
  • 栈区空间存放数据特点:
    • 未经初始化为随机值
    • 执行到变量定义开辟内存空间
    • 超过变量作用域回收变量空间

2虚拟地址和物理地址

1.虚拟地址:
所有能够被用户看到的地址均为虚拟地址,表示用户可以寻址的范围

2.物理地址:
内存存放数据对应的实际硬件物理地址

3. MMU
实际地址和物理地址之间的映射由内存映射单元(MMU)完成

3多进程存储:

    1存储方式:

  •  多个进程空间在操作系统中存储时,空间(物理地址是独立的)
  • 多个进程在操作系统中共用一个虚拟内存空间(虚拟地址是共享的)

4多进程的调度:

   1常见的进程调度算法:

  • 1先来先执行,后来后执行
  • 2高优先级调度算法
  • 3时间片轮转调度算法(时间片:在某一段进程中运行的一段时间)
    • 进程1中时间片运行到达了,进程1就向CPU发送中断信号,CPU进行在虚拟地址空间进行保存现场操作,进程1进入内核中的一个进程管理块区域,通过MMU内存映射单元把进程1的数据存入进程1的物理地址空间,CPU执行进程2...再次执行进程1时,从进程1的物理地址进行拿到进程1 的相关数据,在虚拟地址空间进行恢复现场操作。

2多进程调度本质:

  • 宏观并行、微观串行
  • 宏观分析:一个CPU同时执行多个进程任务
  • 微观分析:一个CPU在多个任务中高速切换保障多任务执行

5进程相关的命令

1. top

示例:top
功能:根据CPU占用率和内存占用率查看当前所有进程的信息
PID:唯一区分进程的ID号
USER:创建者
PR  NI:优先级
VIRT    
RES   
SHR:资源占用
S:状态
%CPU:CPU占用率
%MEM:内存占用率
TIME+:运行的时长
COMMAND:进程命令q退出

2. ps -ef

示例:ps -ef
功能:查看该时刻的所有进程信息
UID:创建进程的用户         
PID:进程的ID号   
PPID:父进程的ID号  
C 
STIME 
TTY:进程依赖的终端        
TIME 
CMDps -ef | grep 进程名
查找与进程名对应的进程信息

3. ps -aux

示例:ps -aux
功能:查看该时刻的所有进程信息
USERPID 
%CPU 
%MEM    
VSZ   
RSS 
TTY      
STAT:进程的状态
START   TIME 
COMMAND

4. 后台执行进程任务

示例:./a.out &
功能:后台执行a.out进程

5. jobs

示例:jobs
功能:查看终端下所有的后台进程任务

6.fg

示例:fg 编号(通过jobs查看)
功能:后台执行的任务放到前台执行

7. nice/renice

示例:nice -n 优先级编号 进程名renice -n 优先级编号 进程PID
功能:改变进程的优先级
优先级范围:-20 - 20
数字越小优先级越高

8kill/killall

示例:kill -编号 进程PIDkillall -编号 进程名
功能:杀死进程任务
kill -9 PID

6进程的状态

进程状态标识含义
就绪态/运行态R进程位于CPU任务调度的队列中
可唤醒等待态S等待某个资源的到来,资源到来后被唤醒加入调度队列br等待过程中可以被打断
不可唤醒等待态D等待某个资源的到来,资源到来后被唤醒加入调度队列br/>等待过程中不可以被打断
停止态T用户人为让进程任务暂停等待
僵尸态Z进程代码运行结束,空间尚未回收
结束态X进程代码运行结束,空间被回收

3.进程相关函数接口

1. fork

原型:pid_t fork(void);
功能:创建一个新的进程,新的进程称为子进程,调用fork的进程称为父进程
参数:缺省
返回值:父进程中返回子进程的PID子进程中返回0 出错返回-1 

注意:

  • 子进程拷贝父进程文本段、数据段、系统数据段
  • 父进程与子进程空间独立,同一份代码中的变量和数据都会在父子进程中各有一份,父子进程 修改自己空间的数据不会影响对方的空间
  • 进程的PID不一样
  • fork的返回值不一样,父进程中返回子进程的PID,子进程中返回0
  • PID:一定是 > 0

2. getpid和getppid

原型:pid_t getpid(void);
功能:获得调用函数进程的PID号
原型:pid_t getppid(void);
功能:获得调用函数进程的父进程的PID号
tip::子进程不影响父进程且子进程会copy父进程的缓存区
int main(void)
{pid_t PID1 = 0;printf("Hello World\n");PID1 = fork();if (-1 == PID1){perror("fail to fork");return 01;}if (0 == PID1){printf("hello\n");}else if (PID1 > 0){printf("world\n");}while (1){}return 0;
}
// 注意:若第6行打印Hello World没有\n --------输出结果为:
// Hello Worldworld
// Hello Worldhello// 若第6行打印Hello World有\n --------输出结果为:
// Hello World
// word
// hello// 为什么呢 因为正常情况是执行过fork之后 父子进程才会分别执行(前面的不会重复执行);
// 但是由于printf是库函数,标准IO具有缓存区(遇到\n刷新),
// 当没有\n时刻,没有刷新缓存 fork复制父进程的数据时 缓存区一起复制到子进程了,因此会一起打印// 对于一个变量 子进程对它改变了值 不会影响父进程里这个值 
// (子进程是父进程copy去的)他们存储在不同的数据空间 后续子进程的变换和父进程无关

3. exit与_exit

原型:void exit(int status);
功能:结束进程任务并返回进程结束状态
参数:status:进程结束状态的值原型:void _exit(int status);
功能:结束进程任务并返回进程结束状态
参数:
返回值:

注意:

  • 在主函数中调用exit和return功能保持一致
  •  return在函数内部将结束该函数
  • exit在函数内部会将进程结束
  • exit会在结束前刷新缓存区
  • _exit不会刷新缓存区

4进程回收

  • wait
原型:pid_t wait(int *wstatus);功能:回收子进程空间
参数:wstatus:存放子进程结束状态空间的首地址返回值:成功返回回收到的子进程的PID失败返回-1

注意:

wait具有阻塞等待功能,等到有子进程结束才会回收子进程继续向下执行

  • waitpid

4进程消亡

1孤儿进程:

        父进程先结束,子进程会成为孤儿进程,被int进程收养

2僵尸进程:

  • 是每个进程结束必然会经历的阶段
  • 产生原因:子进程结束之后,父进程没有回收子进程空间,导致进程执行结束,空间依然被占用的状态,称为僵尸进程
  • 如何避免产生僵尸进程?
    • 让父进程先结束,子进程会成为孤儿进程,孤儿进程被init进程收养,子进程再结束,init进程回收进程空间
    • 子进程结束,父进程回收子进程,避免产生僵尸进程

ex:编写一个程序,将当前系统中所有进程的PID、PPID、Name信息记录到record.txt文件中
(/proc目录下,每个纯数字组成的文件夹就是一个进程,也是该进程的PID号)

http://www.dtcms.com/a/330887.html

相关文章:

  • DTW算法判断两条曲线的相似度,Python代码
  • [激光原理与应用-272]:理论 - 波动光学 - 单纯的白色其实并不单纯
  • 迅为RK3562开发板获取Android13源码
  • 3D商品展示:技术狂欢下的普及困局
  • 【新启航】起落架大型结构件深孔检测探究 - 激光频率梳 3D 轮廓检测
  • Uniapp 自定义头部导航栏
  • 表达式树实战:Unity动态逻辑编程
  • 考研408《计算机组成原理》复习笔记,第三章(6)——Cache(超级重点!!!)
  • 【科研绘图系列】R语言绘制蝶形条形图蝶形柱状堆积图
  • 考研408《计算机组成原理》复习笔记,第四章(3)——指令集、汇编语言
  • 一致性哈希Consistent Hashing
  • Rust Web框架Axum学习指南之入门初体验
  • Java面试宝典:JVM性能优化
  • 【代码随想录day 20】 力扣 669. 修剪二叉搜索树
  • MySQL 性能优化实战指南:释放数据库潜能的艺术
  • 【visual studio】visual studio配置环境opencv和onnxruntime
  • 零知开源——基于STM32F4的HC-12无线通信系统及ST7789显示应用
  • 【Linux】库制作与原理
  • mysql卸载了 服务内还显示如何解决
  • CVPR 2025丨时间序列:动态多尺度机制登场,即插即用,预测稳准狠刷新SOTA
  • Vivado GPIO详解
  • 量化因子RSI
  • 中小型泵站物联网智能控制系统解决方案:构建无人值守的自动化泵站体系
  • 基于STM32单片机智能手表GSM短信上报GPS定位温湿度检测记步设计
  • OS设备UDID查看方法
  • Mybatis学习笔记(一)
  • 「iOS」————设计架构
  • 在语音通信业务量下降时候该怎么做
  • PHP现代化全栈开发:微服务架构与云原生实践
  • 基于FPGA的8PSK+卷积编码Viterbi译码通信系统,包含帧同步,信道,误码统计,可设置SNR