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

《深入Linux内核架构》第2章 进程管理和调度 (2)

目录

2.4 进程管理相关的系统调用

2.4.1 进程复制

2.4.2 内核线程

2.4.3 启动新程序

2.4.4 退出进程


本专栏文章将有70篇左右,欢迎+关注,订阅后续文章。

2.4 进程管理相关的系统调用

2.4.1 进程复制

1. _do_fork函数

        fork vfork clone都最终调用_do_fork

                clone:通过CLONE_XX标志精确控制父子进程共享哪些资源。

                vfork:由于fork使用了COW技术,vfork优势不再,使用少。

COW:copy-on-write,写时复制。

        

fork子进程时,使用COW机制,原理:

        1. 不复制父进程的地址空间。而是将父进程的地址空间标记为只读,并与子进程共享相同的物理内存页。

        2. 当父进程或子进程有写内存时,发生缺页异常。

       3. 缺页异常处理中检查该页是否可以写。

                若可以,写数据到内存页,再修改子进程页表项。

                若不可以,段错误。

COW页:减少不必要的拷贝,提高性能。

2. 执行系统调用

long do_fork(unsigned long clone_flags,unsigned long stack_start,unsigned long stack_size,int __user *parent_tidptr,int __user *child_tidptr)stack_start:用户栈parent_tidptr,child_tidptr:用于返回线程ID给用户空间,因为pthread_create函数需要tid值

系统调用在用户空间和内核空间传递参数的方法因体系结构而异。

方法有:

        寄存器传递:速度快,但寄存器数量有限。

        栈传递:可传递内容多。

3. do_fork的实现

copy_process:见下节

wake_up_new_task:将该新进程加入调度器队列。

4. copy_process 复制进程

dup_task_struct函数:

        复制父进程的task_struct和thread_info结构体。

task_struct:存储体系架构无关的通用信息。

thread_info:存储线程的重要信息,不同体系架构定义不一样。从task_struct中独立出来。

        通常包含:内核栈栈顶,指向当前线程的task_struct等。

        task_struct:存储体系架构无关的通用信息。

创建新进程时分配了新的内核栈,即task_struct->stack

复制后,父子进程两个的task_struct结构体只有一个成员不同:

        新进程分配了一个自己的内核栈,即task_struct->stack

union thread_union {struct thread_info thread_info; 定义在不同体系中unsigned long stack[THREAD_SIZE/sizeof(long)];
};

每个进程有一个内核栈,大小为8K。如下:

THREAD_SIZE=8K,即上图内核栈最大为8K,恶意操作内核栈可能覆盖thread_info

struct thread_info {            //以arch/arm为例unsigned long            flags;            int                      preempt_count;    抢占计数,表示当前线程是否可被抢占。struct task_struct        *task;            代表当前线程__u32                     cpu;                当前线程所在CPU    struct cpu_context_save   cpu_context;    保存着CPU寄存器(如PC,SP等)
};其中thread_info中flag有:TIF_SIGPENDING 当前进程是否有待决信号TIF_NEED_RESCHED 当前进程想让出CPU,调度器选择其他进程执行。TIF = Thread Info Flag

如何访问指定线程的thread_info?

        (struct thread_info *) (task)->stack

如何根据当前线程thread_info找到当前线程的task_struct?

        task_struct *current = current_thread_info()->task

如何访问当前线程的thread_info?

struct thread_info *current_thread_info(void)        ARM为例
{register unsigned long sp asm ("sp");        //sp寄存器:保存了当前线程的内核栈顶部return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}

  

如何根据thread_info找到对应task_struct?

        task_struct *current = current_thread_info()->task

task_struct->stack和CPU sp寄存器,如上图,两者不指向同一地址:

        task_struct->stack:

                指向创建该线程时分配8K内核栈的起始地址。也就是thread_info处

        CPU sp寄存器:

                当前CPU运行线程的内核栈栈顶。

当前进程正在运行时:

        通过ARM sp寄存器值,得到当前线程的thread_info,再得到current的task_struct。

进程切换到一个新进程时:

        通过task_strcut -> stack,得到该线程的thread_info,再通过thread_info得到cpu_context,即可得到该进程上次执行时的寄存器信息,如pc,sp,r0-r12等。

进程切换时,关于进程的task_struct的stack成员,sp寄存器,变化过程?

1. 保存当前进程的上下文:

        保存当前进程上下文到内核栈中:包括CPU的通用寄存器、程序计数器PC、栈指SP等。

2. 切换新进程的:

     切换到新进程的task_struct结构体,再通过task_struct->stack得到thread_info。

3. 恢复新进程上下文

        从thread_info中cpu_context得到该进程上次执行时的上下文信息。如pc,sp,r0-r12等。从而恢复新进程上下文值。此时可正确得到新进程的内核栈栈顶sp。

struct pt_regs 和 thread_info中struct cpu_context_save 是用于保存 CPU 寄存器状态

区别:

        struct pt_regs:用于处理异常或系统调用返回时将其恢复到原始状态,还可传参。

        struct cpu_context_save:用于进程切换时主动保存CPU上下文。

kstack_end(void *addr)函数:

        返回当前线程的内核栈的结束地址。

                这样就可判断某个地址是否在内核栈区间。

继续回到copy_process

sched_fork函数:

        1. 初始化子进程调度参数:优先级和调度策略等。

        2. 复制父进程的调度器相关数据(调度器类别,时间片)。

        3. 将子进程加入调度队列。

copy_process会检测如下标志:

        CLONE_FS 共享父进程的文件系统

        CLONE_NEWXX 不共享的资源

        CLONE_FILES 共享父进程的文件描述符

        CLONE_SIGHAND 共享父进程的信号处理函数

        CLONE_MM COW,只复制页表

struct pt_regs { 如上图,存储在当前线程的内核栈最底部中。

        long uregs[18];

};

struct pt_regs作用:

        从用户态陷入内核态时候,用户态的上下文信息保存在pt_regs数据结构中。还可传递系统调用参数和返回值。

存储的寄存器信息有:

        #define ARM_cpsr uregs[16] 程序状态寄存器

        #define ARM_pc uregs[15]

        #define ARM_lr uregs[14]

        #define ARM_sp uregs[13] 当前线程内核栈的栈顶

        #define ARM_ip uregs[12]

        #define ARM_fp uregs[11]

        #define ARM_r10 uregs[10] //通用寄存器 r0-r10

struct pt_regs这18个寄存器,保存在当前线程的内核栈的底部,如上图。

        即 :struct pt_regs *regs = task_struct->stack + THREAD_START_SP - 1

copy_process还调用copy_thread。

        copy_thread重要内容:

                填充thread_info和pt_regs。

父子进程可共享信号处理函数,但不共享挂起待处理信号。

unsigned long put_user(void __user *dst, const void *src, unsigned long size);

        向用户空间传递单个数据。如char,short,int大小的数据,比copy_to_user快。

copy_to_user优点:可复制任意类型和长度数据。

每个体系的虚拟地址0到4KB的区域,没有任何意义。可重用该地址范围来编码错误码。

如果返回值指向0-4KB地址范围内部,表示该调用失败,其原因由指针值判断。

宏ERR_PTR:将数值常数编码为指针。

使用方法:return ERR_PTR(-EINVAL);

2.4.2 内核线程

内核线程父进程是:init进程

内核线程的任务通常是周期任务,如:

        pdflush:刷新脏页到磁盘。

        kswapd:回写内存页到交换区。

        ksoftirqd:处理软中断。

创建内核线程:

        pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)

        最终也调用_do_fork(CLONE_VM)

创建的内核线程在指定CPU上运行:

        kthread_create_on_cpu()

                -> p->sched_class->set_cpus_allowed(p, new_mask);

kthread_run() = kthread_create() + wake_up_process()

内核线程不需要用户空间,所以内核线程task_struct的mm_struct=NULL。

当内核线程运行,可不置换掉之前进程的用户空间地址,因为内核线程不使用用户空间。所以用active_mm保存用户空间mm_struct,因为内核线程运行后调度的进程通常还是之前那个用户进程,通过active_mm直接恢复,不用修改映射表,TLB中缓存的映射表仍然有效。这叫惰性TLB。

惰性TLB:一种优化策略,延迟或避免不必要TLB的更新,提高性能。

TASK_SIZE:即用户态虚拟地址大小(32位,0-3G)。

        内核线程地址空间大于TASK_SIZE。

2.4.3 启动新程序

execve系统调用

int do_execve(struct filename *filename, const char __user *const __user *__argv, const char __user *const __user *__envp)

会__user定义的指针进行参数检查。

linux_binfmt存储了所有注册的可执行程序的加载函数和执行函数。

struct linux_binprm:保存可执行文件的信息,包括可执行程序的路径,参数和环境变量的信息,vma

struct linux_binfmt {struct list_head lh;         连接所有二进制的执行函数int (*load_binary)(struct linux_binprm *); 加载二进制文件int (*load_shlib)(struct file *); 加载动态库int (*core_dump)(struct coredump_params *cprm); 用于crash时核心转储文件}

Linux文件特殊权限SUID、SGID、Sticky总结:

SUID文件所属主:Set User ID

        当一个可执行文件具有SUID权限时,它执行时临时具有文件所有者的权限,而不是执行者的权限。

        作用:暂时提升用户权限。允许普通用户执行root用户的程序。

        缺点:潜在安全性威胁。谨慎使用。

        使用举例:

                /usr/bin/passwd:允许用户更改自己的密码而无需root权限。

        设置方法:

                增加suid权限:chmod u+s ,或chmod 4755

                移除suid权限:chmod u-s ,或chmod 0755。

SGID文件属组: Set Group ID

        当一个文件或目录设置SGID权限后,任何用户执行该文件或访问该目录时,都以该文件或目录所属的组身份执行,而不是该用户的组权限。

        使用场景:当不同组的用户在一个共享目录下创建新文件,新文件是该目录所属组的权限,而不是创建文件的用户的组权限。可确保所有用户以相同的组权限执行该目录下新文件。

        设置方法:

                增加suid权限:chmod g+s ,或chmod 2755。

                移除sgid权限:chmod g-s ,或chmod 0755。

Sticky权限:

        作用:一般用于目录,只允该目录下的文件的创建者删除自己的创建的文件,不允许其他人删除文件。

二进制文件起始处的magic值可标识该文件类型。

        如:ELF可执行文件:Magic number: 0x7F ELF

                JPEG图像文件:Magic number:0xFFD8FF

search_binary_hander:

        根据文件起始处的magic值来查找对应二进制文件的加载,执行函数。

二进制加载函数: 将文件段映射到虚拟地址空间。

        最终给变量start_code,end_code,start_data,end_data,start_brk brk,start_stack,arg_start,arg_end赋值。

每种二进制格式通过register_binfmt注册:

        如script_format,elf_format,aout_format等

2.4.4 退出进程

exit

各种引用计数减1。减1后若等于0,释放资源。

相关文章:

《深入Linux内核架构》第2章 进程管理和调度 (2)

目录 2.4 进程管理相关的系统调用 2.4.1 进程复制 2.4.2 内核线程 2.4.3 启动新程序 2.4.4 退出进程 本专栏文章将有70篇左右,欢迎关注,订阅后续文章。 2.4 进程管理相关的系统调用 2.4.1 进程复制 1. _do_fork函数 fork vfork clone都最终调用_…...

(四)PostgreSQL的psql命令

PostgreSQL的psql命令 基础信息 OS版本:Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本:16.2 pg软件目录:/home/pg16/soft pg数据目录:/home/pg16/data 端口:5777psql 是 PostgreSQL 数据库的命令行界面…...

前端使用minio传输文件

minio官方文档 minio-js可以支持ts。 安装完可能会出现 Can‘t import the named export ‘xxx‘ from non EcmaScript module (only default export is available)可以尝试降低minio的版本 npm install minio7.0.18 --save代码: 初始化 const Minio require(…...

[大模型] BlueLM-7B-Chat WebDemo 部署

BlueLM-7B-Chat WebDemo 部署 模型介绍 BlueLM-7B 是由 vivo AI 全球研究院自主研发的大规模预训练语言模型,参数规模为 70 亿。BlueLM-7B 在 C-Eval 和 CMMLU 上均取得领先结果,对比同尺寸开源模型中具有较强的竞争力(截止11月1号)。本次发布共包含 7…...

一文了解ERC404协议

一、ERC404基础讲解 1、什么是ERC404协议 ERC404协议是一种实验性的、混合的ERC20/ERC721实现的,具有原生流动性和碎片化的协议。即该协议可让NFT像代币一样进行拆分交易。是一个图币的互换协议。具有原生流动性和碎片化的协议。 这意味着通过 ERC404 协议&#xf…...

iOS cocoapods pod FrozenError and RuntimeError

0x00 报错日志 /Library/Ruby/Gems/2.6.0/gems/cocoapods-1.12.0/lib/cocoapods/user_interface/error_report.rb:34:in force_encoding: cant modify frozen String (FrozenError)from /Library/Ruby/Gems/2.6.0/gems/cocoapods-1.12.0/lib/cocoapods/user_interface/error_r…...

【鸿蒙开发】第二十章 Camera相机服务

1 简介 开发者通过调用Camera Kit(相机服务)提供的接口可以开发相机应用,应用通过访问和操作相机硬件,实现基础操作,如预览、拍照和录像;还可以通过接口组合完成更多操作,如控制闪光灯和曝光时间、对焦或调焦等。 2 …...

JS阅读笔记

myweb3.html <video id"video" width"400" height"300" autoplay></video> <button id"capture-btn">拍摄图片</button> <canvas id"canvas" width"400" height"300">&…...

基于spring boot的留守儿童爱心管理系统

基于spring boot的留守儿童爱心管理系统设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开…...

python输入某年某月某日判断这一天是这一年的第几天

如何使用python实现输入某年某月某日判断这一天是这一年的第几天 from datetime import datetime #引入日期类 def is_leap_year(year):"""判断是否为闰年"""return (year % 4 0 and year % 100 ! 0) or (year % 400 0)# 根据年份和月份返回当…...

docker 上达梦导入dump文件报错:本地编码:PG GBK,导入女件编码:PGGB18030

解决方案&#xff1a; 第一步进入达梦数据容器内部 docker exec -it fc316f88caff /bin/bash 第二步&#xff1a;在容器中 /opt/dmdbms/bin目录下 执行命令 cd /opt/dmdbms/bin./dimp USERIDSYSDBA/SYSDBA001 FILE/opt/dmdbms/ZFJG_LJ20240407.dmp SCHEMASZFJG_LJUSERIDSYSD…...

一起学习python——基础篇(19)

今天来说一下python的如何修改文件名称、获取文件大小、读取文中指定的某一行内容。 1、修改文件名称&#xff1a; import os testPath"D:/pythonFile/test.txt" testPath2"D:/pythonFile/test2.txt" #修改文件名称使用rename方法&#xff0c; #第一个参…...

数模 初见数建

文章目录 初见数学建模1.1 数学建模是什么1.2 数学建模的概述1.3 如何学习数学建模---分模块化1.4 数学建模前提了解1.5 数学建模的六个步骤1.6 如何备战建模比赛1.7 数学建模赛题类型1.8 数学建模算法体系概述 初见数学建模 1.1 数学建模是什么 1.原型与模型 原型&#xff…...

windows系统搭建OCR半自动标注工具PaddleOCR

深度学习 文章目录 深度学习前言一、环境搭建准备方式1&#xff1a;安装Anaconda搭建1. Anaconda下载地址: [点击](https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?CM&OD)2. 创建新的conda环境 方式2. 直接安装python 二、安装CPU版本1. 安装PaddlePaddle2、安装…...

01、ArcGIS For JavaScript 4.29对3DTiles数据的支持

综述 Cesium从1.99版本开始支持I3S服务的加载&#xff0c;到目前位置&#xff0c;已经支持I3S的倾斜模型、3D Object模型以及属性查询的支持。Cesium1.115又对I3S标准的Building数据实现了加载支持。而ArcGIS之前一直没有跨越对3DTiles数据的支持&#xff0c;所以在一些开发过…...

Spark_SparkSql写入Oracle_Undefined function.....将长字符串写入Oracle中方法..

在使用Spark编写代码将读库处理然后写入Oracle中遇到了诸多小bug,很磨人&#xff0c;好在解决了。shit!! 实测1&#xff1a;TO_CLOB(a3) 代码样例 --这是一个sparksql写入hive的一个小逻辑&#xff0c;我脱敏了噻 SELECT a1, a2, TO_CLOB(a3) AS clob_data, TO_DATE(a4) AS …...

2023数据要素白皮书(免费下载)

【1】关注本公众号&#xff0c;转发当前文章到微信朋友圈 【2】私信发送 【2023年数据资源入表白皮书】 【3】获取本方案PDF下载链接&#xff0c;直接下载即可。 如需下载本方案PPT原格式&#xff0c;请加入微信扫描以下方案驿站知识星球&#xff0c;获取上万份PPT解决方案&a…...

kafka学习记录

文章目录 windows单机版kafka搭建步骤主题的增删改查操作消息的生产与消费 Windows集群版kafka搭建步骤 prettyZoo 尚硅谷Kafka教程&#xff0c;2024新版kafka视频&#xff0c;零基础入门到实战 【尚硅谷】Kafka3.x教程&#xff08;从入门到调优&#xff0c;深入全面&#xff0…...

无线网络2.4和5G的区别

无线网络2.4和5的区别 无线网络2.4GHz和5GHz的主要区别在于频率、覆盖范围、传输速度、干扰能力和穿透性。以下是详细介绍&#xff1a;12 频率不同。2.4GHz的频率较低&#xff0c;而5GHz的频率较高。频率越低&#xff0c;信号在传播过程中的损失越小&#xff0c;因此覆盖范围…...

大模型笔记:Prompt tuning

1 NLP模型的几个阶段 1.1 第一阶段&#xff08;在深度学习出现之前&#xff09; 通常聚焦于特征工程&#xff08;feature engineering&#xff09;利用领域知识从数据中提取好的特征 1.2 第二阶段&#xff08;在深度学习出现之后&#xff09; 特征可以从数据中习得——>…...

【Ambari】Ansible自动化部署大数据集群

目录 一&#xff0e;版本说明和介绍信息 1.1 大数据组件版本 1.2 Apache Components 1.3 Databases支持版本 二&#xff0e;安装包上传和说明 三&#xff0e;服务器基础环境配置 3.1global配置修改 3.2主机名映射配置 3.3免密用户名密码配置 3.4 ansible安装 四. 安…...

RTSP/Onvif视频安防监控平台EasyNVR调用接口返回匿名用户名和密码的原因排查

视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入&#xff0c;并能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。平台拓展性强、支持二次开发与集成&#xff0c;可应用在景区、校园、水利、社区、工地等场…...

opencv基础图行展示

"""试用opencv创建画布并显示矩形框&#xff08;适用于目标检测图像可视化&#xff09; """ # 创建一个黑色的画布&#xff0c;图像格式(BGR) img np.zeros((512, 512, 3), np.uint8)# 画一个矩形&#xff1a;给定左上角和右下角坐标&#xff0…...

GIF在线生成器

上传图片就能生成GIF的前端WEB工具 源码也非常简单 <!DOCTYPE html> <html lang"zh" class"dark"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1, m…...

使用JavaScript制作一个简单的天气应用

随着Web开发技术的不断发展&#xff0c;JavaScript已经成为前端开发中不可或缺的一部分。它不仅可以用于创建动态和交互式的用户界面&#xff0c;还可以用于处理各种复杂的任务&#xff0c;如数据验证、动态内容更新、实时通信等。以下是一个使用JavaScript来创建一个简单天气应…...

说说对WebSocket的理解?应用场景?

文章目录 一、是什么二、特点全双工二进制帧协议名握手优点 三、应用场景参考文献 一、是什么 WebSocket&#xff0c;是一种网络传输协议&#xff0c;位于OSI模型的应用层。可在单个TCP连接上进行全双工通信&#xff0c;能更好的节省服务器资源和带宽并达到实时通迅 客户端和…...

网路维护基础知识

1、路由器 路由器&#xff1a;路由器就是将一个可以接入互联网的网路地址分成若干个网路地址可供终端设备连接的网路设备&#xff0c;设备既可以通过有线连接也可以通过无线连接进入互联网 2、交换机 交换机&#xff1a;个人感觉交换机只是为那些有线网路设计的&#xff0c;…...

【GD32】MQ-3酒精检测传感器

2.31 MQ-3酒精检测传感器 MQ-3气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(Sn0)。当传感器所处环境中存在酒精蒸气时&#xff0c;传感器的电导率随空气中酒精蒸气浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。…...

如何在极狐GitLab 启用依赖代理功能

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何在[极狐GitLab…...

ES6中 Promise的详细讲解

文章目录 一、介绍状态特点流程 二、用法实例方法then()catchfinally() 构造函数方法all()race()allSettled()resolve()reject() 三、使用场景# 参考文献 一、介绍 Promise&#xff0c;译为承诺&#xff0c;是异步编程的一种解决方案&#xff0c;比传统的解决方案&#xff08;…...

阿里百秀wordpress/港港网app下载最新版

转载于:https://www.cnblogs.com/supper-Ho/p/6264023.html...

做网站须知/百度文库官网首页

源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明&#xff1a; 有些类在功能设计上要求&#xff0c;自身包含两个或两个以上变化的因素&#xff0c;即该类在二维或者多维上变化。现有一杯咖啡&#xff0c;咖啡杯的大小和是否加奶为两个变化因素&#xff0c;使…...

贵阳市 网站建设/网络营销师证书怎么考

配置执行 选择测试用例 机器人框架提供了几个选择的命令行选项 执行测试用例。 也工作在相同的选项 后处理输出与 Rebot 。 通过测试套件和测试用例的名称 测试套件和测试用例可以选择通过他们的名字的命令 行选项 ——套件(- s) 和 ——测试(- t) , 分别。 这两个选项可以多次…...

聊城定制化网站建设/怎么创建网站链接

文章目录动态规划的三大步骤实例例1&#xff1a;简单的一维DP例2&#xff1a;不同路径例3&#xff1a;最小路径和例4&#xff1a;编辑距离优化例2不同路径数的优化例4编辑距离优化文章出处&#xff1a;告别动态规划&#xff0c;连刷 40 道题&#xff0c;我总结了这些套路&#…...

哪个地方旅游网站做的比较好/上海优化公司

ssh-keygen.exe cat ~/.ssh/id_rsa.pub 转载于:https://www.cnblogs.com/chentailin/p/11136191.html...

成品网站安装/最近新闻大事

SPI是一种总线协议。 总线&#xff0c;一个主设配&#xff08;FPGA&#xff09;只用三四个引脚和n个从设备进行通信。 例如FPGA通过SPI配置SI4133频综模块。 spi是一种通信协议。但是有时候我们看到对spi进行配置&#xff0c;配置什么时钟极性&#xff08;cpol&#xff09;时钟…...