读Kernel感悟-伪装现场-fork()系统调用

A Mathematical Framework for Transformer Circuits—(二) transformer数学理论框架 阅读详情

文章来源:http://www.top-e.org/jiaoshi/class/

不仅进入系统调用时要伪装现场,fork系统调用时返回时也需要伪装现场。因为是“无中生有”。

例如在fork创建新进程时,系统要保证新进程与旧进程一样,从相同的代码开始执行。比如:

#include<stdio.h>

#include<unistd.h>

int main()

{

        pid_t pid;

        if((pid=fork())>0)

        {

                printf("parent/n");

        }

        else if(pid==0)

        {

                printf("child/n");

        }

        else

                printf("error/n");

        return 0;

}

在fork()处,也就是执行call指令的过程中,产生了一个新进程。

 80483f0:       e8 ef fe ff ff          call   80482e4 <fork@plt>

执行完fork()后,新旧两个进程都执行相同的指令:

 80483f5:       89 45 fc                mov    %eax,0xfffffffc(%ebp)

 80483f8:       83 7d fc 00             cmpl   $0x0,0xfffffffc(%ebp)

给人的感觉是新进程和旧进程一样,也是从main函数开始执行,只是执行到fork()处,返回值不一样而已。内核是如何做到的呢?当内核执行fork()系统调用时,内核堆栈里保存有很多寄存器的值。其中包括了eax等几个通用寄存器。通过SAVE_ALL和RESTORE_ALL这两个宏,pt_regs结构体里的变量与对应的寄存器建立了一一对应关系。只要修改pt_regs结构体里的变量,就可以达到修改系统调用结束后,进程执行那一刹那的寄存器值。

这样就简单了,因为fork()时首先把PCB复制了一份(sys_fork()->do_fork()->copy_process->dup_task_struct)。所以内核堆栈pt_regs结构体里的值也跟着复制了一份。之后,在copy_thread()中,把新进程的pt_regs的eax,也就是新进程的返回值设置为0,eip不变。这样当新进程返回到用户态时,就仿佛刚执行完fork()返回0。

这是伪装用户态的现场。还有内核态的现场呢?

copy_thread()中有以下代码:

468         childregs = (struct pt_regs *) ((unsigned long) childregs - 8);

469         *childregs = *regs;

470         childregs->eax = 0;

471         childregs->esp = esp;

472 

473         p->thread.esp = (unsigned long) childregs;

当子进程被调度到时,子进程处于内核态。经过switch_to()进程切换,eip设置为thread.eip,esp设置为thread.esp。 eip是ret_from_fork,esp是 childregs。伪装成刚执行完系统调用fork准备从内核态返回到用户态。

474         p->thread.esp0 = (unsigned long) (childregs+1);

 thread.esp0在switch_to()->__switch_to()中,会通过load_esp0设置为tss_struct中的esp0。这个字段是在CPU运行状态变化时(如系统调用从用户态进入内核态)保存0级也就是内核态的堆栈指针。这样的话不是有两个地方有内核态堆栈指针了么?不过他们不矛盾。thread.esp在进程切换时使用。thread.esp0在CPU运行状态变化时使用。当子进程返回到用户态后又发生中断或者系统调用。这时使用的是 esp0,内核堆栈是空的。正好指向(unsigned long) (childregs+1)。

如何同步,我也不清楚。

475 

476         p->thread.eip = (unsigned long) ret_from_fork;

 p->thread中保存了进程切换所需的很多信息。包括内核态的esp,eip

伪装的现场,给人的感觉是新进程在内核态正好快执行到 ret_from_fork时由于中断等原因被抢占,所以在fork()完毕后可能进行的进程调度中,新进程可能被调度到,在执行完ret_from_fork中的一些代码,返回到用户态后,开始执行fork()之后的代码。

文章来源:http://www.top-e.org/jiaoshi/class/

 

STM32H743 LAN8720网口配置避坑指南:用CubeMX v6.5.0快速搞定LWIP+FreeRTOS 本文详细介绍了使用CubeMX v6.5.0配置STM32H743与LAN8720网口的LWIP+FreeRTOS方案,涵盖硬件连接、时钟配置、ETH外设初始化及LWIP协议栈调优等关键步骤。特别针对常见陷阱提供解决方案,帮助开发者快速实现稳定网络通信,适用于嵌入式网络开发场景。 阅读详情

相关推荐

网络工程师软考通关指南:网络新技术与应用深度解析

网络安全与管理是网络工程师必须掌握的核心技能,华为设备在企业网络中广泛应用。建议考生在理解安全原理的基础上,重点掌握华为特有的命令体系和配置方法,通过模拟实验加深理解。下篇文章将深入讲解"网络优化与QoS"章节,涵盖流量调度、拥塞避免、服务质量等关键技术,敬请期待。

Programming Talk 227

【进程管理】认识系统调用函数fork

fork函数牵扯的操作系统进程方面知识,全文干货,建议收藏

weixin_74113106的博客 586

10天冲刺国自然基金!用这套实战AI提示词指令教程,助你中标率翻倍!亲测DeepSeek和ChatGPT不好用

虽然以上国自然提示词指令经过反复实测,但并不是万能无脑帮你搞定所有,大模型AI的特性是你专业领域能力越强,它的智商表现就会更加强大,通过以上提示词教程的使用,大大提升中标概率是肯定的。还有就是大模型的使用上,不是市面上大家都说好的就一定适用,目前来看,Gemini和Claude的两个模型是非常适合国自然本子的修改的。在使用大模型进行国自然本子撰写修改时,首先是角色的设定,然后是目标和背景的描述,好用的提示词指令都是要经过无数次的实测,比对输出结果后又反复调整,达到最佳的效果状态的提示词指令。

智能AI让学术科研更容易 1187

fork()系统调用

在Linux系统内,创建子进程的方法是使用系统调用fork()函数。fork()函数是Linux系统内一个非常重要的函数,它与我们之前学过的函数有一个显著的区别:fork()函数调用一次却会得到两个返回值。

薛铁钢的博客 1913

【Linux进程】三、进程控制——fork()系统调用深度刨析

本文介绍了进程控制相关的命令与函数,并深入讨论了fork函数的实现机制以及fork函数的一次调用两次返回,最后通过实例演示了如何使用fork函数控制进程的创建。

仅以此博客记录日常学习工作中所思所得,水平有限,难登大雅,万望海涵。 2743

Linux 学习笔记(五):fork() 系统调用

Linux 学习笔记(五):fork() 系统调用

Amentos的博客 1498

Linux多进程/线程编程之【fork()和exec()

在多进程中fork()和exec()通常是结合起来一起使用,在多线程中,通常不建议使用fork()和exec()

weixin_53351963的博客 3477

Kernel感悟-伪装现场-系统调用参数

文章来源:http://www.top-e.org/jiaoshi/class/内核支配了整个计算机的硬件资源,好像一位独裁者,高高在上。他有时候必须像法官一样公正,有时候则必须像狐狸一样狡猾。伪装现场就是他的拿手好戏。系统调用是很特别的函数,因为它里面实现了用户态到内核态的转换。应用程序要创建新进程,不可能在用户态直接调用sys_fork()。这就需要内核为sys_fork()伪装

李亚锋老师 1596

Kernel感悟-伪装现场-内核线程

文章来源:http://www.top-e.org/jiaoshi/class/众所周知,内核中创建一个内核线程是通过kernel_thread实现的。声明如下:int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);我们知道,用户态创建线程调用clone(),如果要在内核态创建线程,首先想到的是在内核

李亚锋老师 1744

Linux内核编程 fork( )系统调用

Linux内核编程 fork( )系统调用

m0_56051805的博客 1519

fork系统调用

在操作系统里,进程是正在运行的程序的实例。fork()函数的作用是复制当前进程,生成一个新的进程,这个新进程被称作子进程,而原本的进程则是父进程。这两个进程(父进程和子进程)会从fork()调用处开始,并发执行后续代码。

2301_80657297的博客 295

Linux fork()系统调用流程解析

fork系统调用用于创建一个新进程,称为子进程,它与进程(称为系统调用fork的进程)同时运行,此进程称为父进程。创建新的子进程后,两个进程将执行fork()系统调用之后的下一条指令。子进程使用相同的pc(程序计数器),相同的CPU寄存器,在父进程中使用的相同打开文件。它不需要参数并返回一个整数值。下面是fork()返回的不同值。负值:创建子进程失败。零:返回到新创建的子进程。正值:返回父进程或调用者。该值包含新创建的子进程的进程ID 。

assiduous_me的博客 2160

Kernel源码笔记之调度:4.Fork系统调用

简介 fork系统调用是用户空间进程的起点,fork的流程中涉及了内核中大多数核心的基础组件,比如:文件系统,内存管理,namespace等等,execve用来执行一个程序,调度是驱动系统运行的核心,所以了解这三个流程,对学习内核是一个很好的引导。 本文基于4.19.190版本的内核。 文中可能有些地方描述不准确,如有请指出,感谢。 陷入系统调用 系统调用通过0x80号中断来陷入内核。 在内核启动的主函数start_kernel(init/main.c)中会调用trap_init(arch/x86/kern

苟浩的博客 996

系统调用 fork()

用户态:| 用户程序调用 fork() || ↓ || 封装后执行 int 0x80 触发中断 |内核态:| 中断处理器进入 sys_call || ↓ || 找到 syscall table 中 fork 对应函数 sys_fork() || ↓ || 执行:复制PCB、内存、文件、寄存器等 || ↓ || 设置返回值 eax=0 / eax=child_pid || ↓ || 用 iret 恢复到用户态 |用户态:| 两个进程继续执行,父子分流 |

zjkyeah的博客 453

Linux/Unix系统调用fork()学习

(1)当fork()出来的父子进程,均为执行写操作时,此时父子进程内存空间大致如下:(2)当fork()出来的父子进程,任意一个执行执行写操作时,此时父子进程内存空间大致如下:子进程是父进程的副本,拥有相同的代码段、数据段和堆栈段,但它们有各自的进程ID和内存空间。进程控制块(Process Control Block, PCB) 是操作系统中用于管理进程的重要数据结构。它包含了与进程相关的所有信息,操作系统通过 PCB 来跟踪和控制进程的状态。

zhanghui962623727的博客 1699

详解Linux的系统调用fork()函数

fork()函数的本质是在内核中创建一个新的进程控制块(PCB),然后将原来进程的PCB中的大部分内容都复制到新的PCB中去,然后让两个进程同时运行。由于只有在父进程中fork的返回值才会是进程ID,而子进程中fork的返回值永远是0,所以只有父进程会打印除L0、L1和L2并创建三个子进程,四个进程再打印出四个Bye。父进程输出一个L0、一个L1和一个Bye,一个子进程输出一个L1和一个Bye,一个子进程输出一个Bye,两个孙子进程输出两个Bye,一共一个L0、两个L1和四个Bye。

笔记 1853

【Linux进程】三、进程控制——fork()系统调用深度刨析_fork系统调用

包含头文件函数原型函数功能getpid() returns the process ID of the calling process. 获得当前进程的ID。getppid() returns the process ID of the parent of the calling process. 获得当前进程的父进程的ID。函数参数void函数返回值getpid()返回当前进程IDgetppid()返回当前进程的父进程ID。

2401_89210283的博客 780

fork系统调用及示例

fork是Unix/Linux系统中最基本的进程创建系统调用,用于创建一个调用进程(父进程)的副本(子进程)。其特点是"一次调用,两次返回":父进程中返回子进程PID,子进程中返回0。子进程继承父进程的代码段、数据段、堆栈、文件描述符等状态,之后两者独立执行。典型应用场景包括多进程编程,常与wait、exec等函数配合使用。示例代码展示了如何创建单个子进程和多个子进程,并通过返回值区分父子进程的执行路径。fork是实现Unix多任务的基础,广泛用于服务器、shell等程序。

悟空看八戒烤熟了没的专栏c)4Upqt4SeVk 1236

【Linux Kernel 进程管理】深入分析fork

fork,vfork,clone三个系统调用入手,深入分析其过程,最后是总结和对比。

918

fork 系统调用解析

fork:一次调用,两个返回值 fork 函数用于在Linux中创建新进程,英文本意是叉子,fork系统调用就像是叉子一样,寓意一分为二,一次调用,两个返回值 fork执行后发生了什么? fork函数执行后,后将存在两个进程,且每个进程都会从 fork() 的返回处继续执行 新的子进程几近于对父进程的翻版:子进程获得父进程的栈、数据段、堆和执行文本段的拷贝 执行 fork()之后,每个进程均可修改各自的栈数据、以及堆段中的变量,而并不影响另一进程 父进程的fork返回值为子进程的pid,子进程的fork

郭同学如是说 1895

最新鸽哒IM即时通讯系统源码 带安卓、苹果、PC端(全开源)

鸽哒是一款类似于微信的即时通讯软件。 独立部署!加密通道!牢牢掌握通讯信息! 1.产品为独立开发,非网上下载不能用的产品! 2.即时聊天软件技术难度大,请不要拿网络其他聊天软件来对比! 3.网络上大部分聊天类APP是调用第三方平台插件, 没有独立数据库及后台,数据量大需要收费,且安全性得不到保障! 即时通讯,纯原生开发,各种功能应有尽有 支持加好友、消息私聊、消息群聊、朋友圈、红包、语音、视频、表情包,定位等。 当前市面上大部分即时通信源码都是较老的版本,不仅界面老旧还不支持最新的安卓版本, 三端是java,oc,c#,全是纯原生,全开源的,市面上很多都是用h5封装, 加载慢不说,还有很多bug,体验根本不能与原生想比。 后台是酷信的,包括linux、Windows、docker三种部署方式,后台开发语言主要是java, 部署较麻烦,但整体架构满足高并发场景,支持集群,有完整的部署教程。 后台推送包含市面上主流的推送方式,并且有独立的公告推送,保证大部分用户都可以收到消息。 支持阅后即焚、消息过期自动销毁、支持3DES加密传输、支持端到端传输,保护消息隐私。 朋友圈支持发送语音、视频、

ProfileMaker 5.0.10.rar

ProfileMaker 5.0.10.rar破解

上一篇: 读Kernel感悟-伪装现场-内核线程
下一篇: 读Kernel感悟-kbuild系统-内核模块的编译
TopEmbedded
博客等级 码龄18年 58粉丝 61原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值