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

2.【Linux】(进程的状态||深入理解fork||底层剖析||task_struct||进程优先级||并行和并发||详解环境变量)

一.进程

1.进程调度

Linux把所有进程通过双向链表的方式连接起来组成任务队列,操作系统和cpu通过选择一个task_struct执行其代码来调度进程。

2.进程的状态

1.运行态:pcb结构体在运行或在运行队列中排队。
2.阻塞态:等待非cpu资源就绪(硬盘,网卡等资源)
3.挂起态:一个进程对应的代码和数据被操作系统因为资源不足而导致操作系统将该进程的代码和数据临时地置换到磁盘当中,进程的pcb还在内存中。

3.linux下进程的状态

在这里插入图片描述

R:对应上面的运行态
S:(可中断睡眠),对应上面的阻塞状态
D:深度睡眠,不可被中断。深度睡眠的状态进程,只能通过 “一觉睡到自然醒” 自己醒来,OS 无权唤醒或杀死之。
T:暂停状态(调试)
X:dead终止,瞬时性非常强
Z:僵尸状态

二.深入理解fork

1.介绍fork

fork通过复制一份当前进程(父进程)来创建一份全新的进程(子进程),父进程创建成功返回子进程的pid,失败返回-1,子进程创建成功返回0,失败返回-1。

2.为何会有两个返回值?

在这里插入图片描述
fork可以分为以上三步:1.操作系统先将用户态转为内核态通过系统调用create创建一个空进程。2.调用clone将父进程的代码和数据(数据段,堆栈等)完全拷贝给子进程。3.return 返回。
当父进程通过前两步创建出子进程并把代码数据复制完成后,父进程便return返回子进程的pid。子进程有了父进程的所有数据(堆栈信息,pcb),由于pcb中记录了父进程代码执行到的位置,因此子进程会接着执行后续return语句,失败返回-1,成功返回0.

3.fork底层剖析

摘自博客园
三个调用的区别在于传入的参数不同
在这里插入图片描述
具体细节参考
资料1
资料2
资料3

1.fork() 和 vfork() 参数是写死的,而 clone() 是可选的,它可以选择当前创建的进程哪些部分是共享的,哪些部分是独立的;
2. vfork() 是历史的产物,当调用 fork() 的时候,需要将父进程的线性区和页表都拷贝一份,而调用 exec()执行新程序后,又要把所有页表删除重置新的页表,建立映射关系,效率很低;
3.所以要有 vfork(),vfork() 的 clone_flags 位置了 CLONE_VM ,表示共享父进程的地址空间,vfork()中创建的进程没有分配自己的地址空间,而是通过一个 mm_struct 指针指向父进程的地址空间,这个进程是为了在之后调用 exec() 执行新的程序; 而在有了 Copy-on-write 技术后,fork()出的子进程只创建了自己的地址空间,然后用父进程的地址空间初始化,每个页表的项置为父进程的页表项,共享父进程的物理页面,并将所有 私有/可写页面改为只读;
4.当我们改变父子进程的数据后,cpu 在运行过程中会发生一个缺页错误,cpu 转交控制权给操作系统,操作系统查找 VMA。发现该页权限为只读,但所在段又是可写的,产生一个矛盾,这就是识别 Copy-on-write 的方法,接着 OS给子进程分配一个新的物理页,并将页表该页的地址修改成新的物理页地址;这样 fork() 后再调用 exec() 就不用那么麻烦了,可以直接将新的物理页与子进程的虚拟空间建立映射。

三.linux中的pcb实体task_struct

参考资料4
在这里插入图片描述
转载

四.进程优先级

1.优先级

优先级PRI=nice+old(pri),PRI越小,优先级越高。
linux下调整优先级就是调整nice值,nice值从-20到19。

2.并发和并行

并行:多个进程多个cpu下分别同时运行。
并发:多个进程采用进程切换通过一个cpu在一段时间下(时间片)让多个进程推进
上下文:cpu内存在寄存器,当一个进程a在运行时,cpu内的寄存器里面一定保存的是进程a的临时数据,这些数据就叫该进程的上下文。为了实现并发,当进程a暂时被切换的时候,进程a会带走自己的上下文数据(保存在pcb中),目的是为了下次切换回来时能快速恢复。

五.环境变量

1.概念

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。

2.常见环境变量

PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash

3.操作

1.查看环境变量:echo $ PATH
2.显示所有环境变量:env
3.清除环境变量unset
4.设置一个新的环境变量:export

4.获取环境变量

#include <stdio.h>
int main(int argc, char *argv[], char *env[])
{
int i = 0;
for(; env[i]; i++){
printf("%s\n", env[i]);
}
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[])
{
extern char **environ;
int i = 0;
for(; environ[i]; i++){
printf("%s\n", environ[i]);
}
return 0;
}

libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%s\n", getenv("PATH"));
return 0;
}

常用getenv和putenv函数来访问特定的环境变量

相关文章:

  • k8s学习-Deployment
  • javaweb学习day01(HTML)
  • 前端关于学习方式,解决问题的面试题(本人真实面试题)
  • Windows系统还原打印机系统教程
  • kafka简单介绍和代码示例
  • 【深度学习入门】深度学习基础概念与原理
  • 一款优秀的双链笔记Blossom 安装教程 私有部署的云端双链笔记软件Blossom
  • UI设计中插画赏析和产品色彩分析
  • 昇思MindSpore技术公开课——第三课:GPT
  • GO基础进阶篇 (十四)、Http编程
  • 现阶段Python和Java哪个更吃香?
  • 代码随想录算法训练营第二十三天| 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树
  • 网络安全(黑客)—2024秩序
  • 实验二 体系结构
  • 红队打靶练习:HOLYNIX: V1
  • 【Linux系统编程】快速查找errno错误码信息
  • 【node学习】协程
  • create-react-app项目添加less配置
  • CSS3 变换
  •  D - 粉碎叛乱F - 其他起义
  • in typeof instanceof ===这些运算符有什么作用
  • JavaScript 基础知识 - 入门篇(一)
  • JavaScript的使用你知道几种?(上)
  • maven工程打包jar以及java jar命令的classpath使用
  • ReactNativeweexDeviceOne对比
  • Spring Boot MyBatis配置多种数据库
  • springMvc学习笔记(2)
  • underscore源码剖析之整体架构
  • 反思总结然后整装待发
  • 高度不固定时垂直居中
  • 后端_ThinkPHP5
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 聊聊hikari连接池的leakDetectionThreshold
  • 深入浅出webpack学习(1)--核心概念
  • 手机端车牌号码键盘的vue组件
  • 应用生命周期终极 DevOps 工具包
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • (4)STL算法之比较
  • (Python) SOAP Web Service (HTTP POST)
  • (ros//EnvironmentVariables)ros环境变量
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)ssm高校实验室 毕业设计 800008
  • (四) 虚拟摄像头vivi体验
  • (转)EOS中账户、钱包和密钥的关系
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET NPOI导出Excel详解
  • .NET 服务 ServiceController
  • .NET和.COM和.CN域名区别
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • [.net]官方水晶报表的使用以演示下载
  • [1127]图形打印 sdutOJ
  • [2]十道算法题【Java实现】
  • [ACTF2020 新生赛]Upload 1