Linux 0.11 源码阅读 1 -- syscall的调用实现

操作系统接口本质:从系统调用到用户/内核态隔离 操作系统接口是应用程序与硬件资源之间的抽象契约,其核心在于用户态与内核态的严格隔离——这一机制由CPU硬件保护环(Ring 0/Ring 3)强制实施,通过软中断(如int $0x80)和受控数据搬运(copy_from_user/copy_to_user)实现安全跨态交互。它屏蔽了底层硬件差异,赋予开发者专注业务逻辑的‘专注’能力与自由组合抽象的‘自由’能力。POSIX标准进一步将该模型泛化为跨平台通用范式,支撑从命令行工具到GUI应用的统一系统调用基础。理解这一接口原理,是掌握Linux系统编程、调试段 阅读详情

前言

        在main.c函数中,存在两个函数 fork.c pause.c,当我们尝试单步跟进去之后,却发现失败了,我们来分析其原因。

void main(void)		/* This really IS void, no error here. */
{			
    ....
	if (!fork()) {		/* we count on this going ok */
		init();
	}

	for(;;) pause();
}

    

_syscall0(type,name) 宏的实现

        我们在main函数中存在下面这些定义,我们现在尝试分析一下。

static inline _syscall0(int,fork)
static inline _syscall0(int,pause)
static inline _syscall1(int,setup,void *,BIOS)
static inline _syscall0(int,sync)

        其_syscall0(type,name)定义如下,我们尝试对此展开一下。

#define _syscall0(type,name) \
  type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
	: "=a" (__res) \
	: "0" (__NR_##name)); \
if (__res >= 0) \
	return (type) __res; \
errno = -__res; \
return -1; \
}

          我们现在对pause( )展开,内容如下,就是调用 int 0x80,然后eax来传递中断号,返回时将返回值存入变量__res中,判断是否成功,否则设置错误号。

#define __NR_pause	29
static inline _syscall0(int,pause)


int pause()
{
    long __res;
    __asm__ volatile(
    " int $0x80"
    : "=a" (__res)       // mov __res,eax
    : "0" (__NR_pause)); // mov eax, __NR_pause
    /* intel 
        mov eax, __NR_pause
        mov int 0x80
        mov __res,eax
    */
    if (__res >= 0)
        return int __res;
    error = -__res;
    return -1;

}

int 0x80后发生了什么呢

        我们尝试在vscode中全局搜索“0x80”,在sched.c中看到如下函数,因此我们知道是在void sched_init(void)中完成对int 0x80中断的初始化的。

void sched_init(void)
{
    ...
    ...
    ...
    set_system_gate(0x80,&system_call);
}

        system_call是一段汇编代码,在kernel\kernel_call.s中,核心代码如下,其通过sys_call_table这张表来查询到的,然后 call sys_call_table[eax*4] 来间接跳转到对应函数位置。

system_call:
    ....
    .... 
    mov %dx,%es
	movl $0x17,%edx		# fs points to local data space
	mov %dx,%fs
    call *sys_call_table(,%eax,4)
    pushl %eax
	movl current,%eax
    ...
    ...

        我们使用readelf工具查看syscall_call.o文件,看到sys_call_table还没有被定位。

readelf -s system_call.o


Symbol table '.symtab' contains 55 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
    ....
    ....
   39: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND sys_call_table
    ....
    ....

        全局搜索sys_call_table,在sys.h这个文件中找到该变量,内容如下。通过继续分析,我们可以发现其仅在sched.c中引用过这个头文件。


sys.h

....
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_iam, sys_whoami };

        但是我们通过对sched.c文件的分析,发现其没有直接使用sys_call_table[],因此我们可以推断出该步的目的是将syscall.h编译到sched.o的全局符号表中,等到链接的时候被syscall.o发现。

sched.o
 19: 00000000   296 OBJECT  GLOBAL DEFAULT    8 sys_call_table


system_call.o
  39: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND sys_call_table

后记

        我们这篇文字简单分析了下Linux0.11中的系统调用方式,Linux0.11是个比较简单的操作系统,分析起来应该很简单,但是刚开始被这小小的系统调用难住了半天,记录一下。

        

inline_syscall:内联syscall使得在clang上的Windows变得容易 立即下载

相关推荐

免费测试国外大模型Claude 3.7 Sonnet API:无需api key(秘钥)

Claude 3.7 Sonnet是Anthropic公司推出的第三代Claude系列AI模型中的中规模版本(2024年发布),在性能与效率间实现平衡。该模型基于改进的Transformer架构,支持128K上下文窗口,擅长复杂推理、数学计算和创意写作,在GSM8K数学基准测试中准确率达92%。其采用"宪法AI"伦理框架,通过多轮对抗训练减少有害输出,同时新增多模态理解能力(可解析图片/图表内容)。Claude 3.7 Sonnet是Anthropic推出的高效轻量级大模型,主打快速响应与成本优化。

Explinks的博客 1497

【Linux】syscall系统调用原理及实现

linux syscall系统调用

种一棵树最好的时间是十年前,其次是现在 1万+

别再被网站风控了!手把手教你修改Chromium源码,实现TLS指纹随机化

本文详细介绍了如何通过修改Chromium源码实现TLS指纹随机化,有效规避网站风控。文章深入解析了TLS指纹(如JA3指纹)的工作原理,并提供了具体的源码修改步骤和编译方法,帮助开发者突破高级反爬技术。通过动态打乱加密套件顺序,实现每次请求生成不同的指纹,显著提升自动化工具的隐蔽性。

weixin_28712661的博客 426

为Linux0.11添加系统调用

为Linux0.11添加系统调用一,在 include/unistd.h 中为iam和whoami增加系统调用号:二,修改 kernel/system_call.s 中的系统调用总数:三,在include/linux/sys.h中sys_call_table函数表中增加两个函数引用==将include/linux/sys.h,include/unistd.h复制到hdc/usr/include对应目录下,否则编译不通过==四:在 kernal/ 中新增who.c实现sys_iam与sys_whoami:五,

qq_37447786的博客 2481

ARC学习(6)arc 编译器overlap 地址重叠方式使用

摘要:本文介绍了ARC编译器中使用overlap地址重叠的方法。

张一西的博客 717

Multisim 14.0元件库下载完整指南:从安装到配置

详细介绍Multisim 14.0版本的元件库下载方法,涵盖安装步骤与后续配置流程,帮助用户快速搭建仿真环境。内容覆盖常见问题及解决方案,让multisim元件库下载更高效、稳定。

weixin_34511754的博客 1931

操作系统之——为Linux0.11添加系统调用

1.目标 为Linux0.11添加两个系统调用, 分别为: int iam(const char* name); 功能为:将字符串name拷贝到内核并保存,要求 name 的长度不能超过 23 个字符。返回值是拷贝的字符数。如果 name 的字符个数超过了 23,则返回 “-1”,并置 errno 为 EINVAL。 在 kernal/who.c 中实现此系统调用。 int whoami(cha...

princeteng's blogs 2374

青龙面板实战:用快手极速版脚本日赚XX元的核心参数解析

本文深入解析了青龙面板运行快手极速版脚本的核心参数配置,旨在帮助进阶用户提升收益稳定性。重点剖析了设备标识符(did)的获取原理、多账号Cookie的精准拼接规则,以及如何通过科学设置定时任务频率来量化并优化收益,实现细水长流的稳定收益。

weixin_29310605的博客 1073

实验2:系统调用

本章为哈工大操作系统实验——系统调用的实验过程记录。

weixin_40909092的博客 654

笔试题-2023-星宸-数字IC设计【纯净题目版】

4 笔试题-2023-星宸-数字IC设计【纯净题目版】

w0shishabi的博客 1171

基于Qt C++开发一套大疆农业无人机的AI飞控系统

如果需要补充**多机协同作业代码**、**农田测绘数据导出**、**作业数据统计大屏**或**移动端地面站适配**功能,可以告知具体需求,我会针对性完善。"开启" : "关闭") << "喷洒,流量:" << flowRate << "L/min";emit errorOccurred(QString("SDK初始化失败,错误码:%1").arg((int)ret));report += QString("问题区域数量:%1\n").arg(info.problemAreas.size());

寒寒豆豆软件公司的博客 380

main函数解析(一)——Linux-0.11 学习笔记(五)

main()函数解析(一)——Linux-0.11 学习笔记(五) 经过了前面的各种铺垫,终于来到了main函数。这篇博客的任务是把init/main.c讲清楚。由于牵扯到很多的函数调用,要想一次就说明白是很难的,所以我们把目标定得低一点,把脉络理清楚就行。 1. 宏定义_syscall0 文件开头的头文件包含等就不多说了。对于C语言比较熟悉的朋友,我想第一个拦路虎就是“GCC内嵌汇编”...

车子(chezi) 4064

基于Python的股票K线图爬取与形态识别系统

本文详细介绍了一个基于Python的股票K线图爬取与形态识别系统。该系统通过网络爬虫技术获取股票历史数据,使用Matplotlib生成K线图,并应用卷积神经网络(CNN)对经典K线形态进行识别。文章详细阐述了数据采集、K线图生成、CNN模型构建与训练的完整流程,并提供了完整的代码实现。本研究为金融科技领域的毕业设计提供了有价值的参考方案。关键词:Python爬虫、K线图、卷积神经网络、形态识别、股票交易。

2201_76125261的博客 1033

Linux_0.11源码学习阅读(壹)

本来想阅读当前我正在使用的Linux系统源码,但代码实在过于繁杂,查找很不方便,所以就分析linux0.11的源码,查找确实方便了,但很多新策略没有,之前学习的内核双链表就没有查找出来,有能力大家可以阅读较新的源码,后续还未完成,待更新。

weixin_45672701的博客 245

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

深入 syscall_intercept 汇编实现:寄存器保存与调用约定转换的完整图解

系统调用拦截是 Linux 底层开发的硬核话题,而 **syscall_intercept** 正是这样一款用热补丁方式在用户态拦截系统调用的开源库。它的核心难点在于:被补丁的 `syscall` 指令周围是普通机器码,无法直接跳进 C 函数,必须靠**手写汇编**完成寄存器保存与调用约定转换。本文不堆砌代码,而是用图解方式带你拆解这条汇编链路:从栈对齐、红区避让,到 GPR/SIMD 寄存器保存

gitblog_00103的博客 641

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

ChatLab 使用 AI Agent 转换聊天记录:chatlab-convert Skill 全流程实战指南

ChatLab 是一款本地优先(Local-first)的 AI 聊天记录分析工具,能够将多平台聊天导出统一转换为标准格式后进行分析。当某个聊天平台的导出格式尚未被 ChatLab 原生识别时,你可以借助官方的 `chatlab-convert` 技能(Skill),让本机 Agent 自动分析文件结构、编写可复用的转换脚本,并将记录转换为 [ChatLab 标准格式](https://link.

gitblog_01150的博客 349

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Linux Kernel源码阅读: x86-64 系统调用实现细节(超详细)

本文采用Linux 内核 v3.10 版本本文不涉及调试、跟踪及异常处理的细节系统调用是用户空间程序与内核交互的主要机制。系统调用与普通函数调用不同,因为它调用的是内核里的代码。使用系统调用时,需要特殊指令以使处理器权限转换到内核态。另外,被调用的内核代码由系统调用号来标识,而不是函数地址。下面我们以示例程序中使用的write系统调用为例,来看看系统调用是如何定义的。write系统调用函数原型如下,可以通过命令查看。在linux内核中,write系统调用定义在文件中。由于write。

嵌入式Linux内核的博客 3426

深入理解Linux系统调用与API(0.9)

内核为了向用户空间提供服务,设计出了系统调用机制,系统调用机制可以让用户空间调用内核里的某些特定的函数。要实现系统调用机制需要有CPU提供的特殊指令才行。由于历史原因,系统调用指令在x86平台上不止有一个。系统调用指令的作用是把CPU模式切换到特权模式、让CPU跳到指定的入口函数来执行,并把用户空间提供的系统调用编号和参数传递进内核。入口函数根据系统调用编号调用相应的函数并传递参数,执行完毕后再返回用户空间。我们一般情况下并不会直接使用系统调用,操作系统为我们提供了非常丰富的API,用起来更方便。.....

Linux内核爱好者 1585

Linux函数调用和寄存器笔记

CS, DS, SS, ES, FS, GS:16位 最多可以有2**13个段,因为32位系统下每个段描述符占8字节,所以段选择子的最低3位应该是0,但是为了合理利用,实际中选择子的最低3位用来表示权限RPL,具体作用是LDTR或者GDTR中的32位基地址+段选择子。CR0, CR2, CR3, CR4:32位, CR0可以控制分段和分页机制,CR1暂时保留不用,CR2用以保存导致页错误的线性地址,CR3用以分页机制,保存了页目录地址。64位架构的引入主要是为了支持更大的内存空间和更复杂的计算任务。

无香花自开 729

深度拆解:Linux read() 系统调用的真正实现

本文通过分析musl libc中5行代码的read()实现,揭示了系统调用的本质。文章指出read()并非直接调用操作系统,而是通过libc封装层syscall_cp进入内核,其中_cp表示支持线程取消点。对比了musl(精简设计)和glibc(多层封装)的不同实现风格,解释了系统调用号、用户态/内核态切换过程,并列举了read()常见的三大使用误区(未读满缓冲区、EOF判断、EINTR处理)。最后强调read()本质是libc提供的"内核门票",而syscall_cp确保线程在阻塞期间

2302_80441878的博客 40

在Visual C++中调试Linux 0.11内核:搭建混合开发环境与实战指南

操作系统内核是计算机系统的核心,负责管理硬件资源和提供基础服务。理解其工作原理对于深入计算机体系结构至关重要,而调试是学习内核不可或缺的环节。传统上,内核调试依赖于命令行工具和模拟器,流程割裂,体验不佳。现代集成开发环境(IDE)通过远程调试技术,能够将源码管理、智能导航和图形化调试界面整合,极大提升学习与开发效率。Visual Studio凭借其强大的C++开发与跨平台调试能力,结合GDB远程调试协议,可以构建一个高效的混合开发环境。这使得开发者能够在熟悉的Windows IDE界面下,对运行在Linux

weixin_34214500的博客 311

Linux内核深入理解系统调用(3):open 系统调用实现以及资源限制(setrlimit/getrlimit/prlimit)

Linux内核深入理解系统调用(3) open 系统调用实现以及资源限制(setrlimit/getrlimit/prlimit) rtoax 2021年3月 对原文进行了5.10.13的代码分析。 1. open 系统调用实现 1.1. 简介 本节是详述 Linux 内核中的 系统调用 机制章节的第五部分。之前的内容部分概述了这个机制,现在我将试着详细讲解 Linux 内核中不同系统调用的实现。本章之前的部分和本书其他章节描述的 Linux 内核机制大部分对用户空间是隐约可见或完全不可见。但是 Li

RToax 1843

深入了解Linux内核-系统调用如何实现?

函数名就相当于一个地址,name: 后面的代码就是这个函数具体要做的事,就像 c 语言编写函数时的函数体,只不过这里是用汇编写的而已。这是以 write 系统调用为例的系统调用过程图,图是丑了点,不过这条线应该捋得还是挺清晰的,好啦,本文就到这里,有什么错误还请批评指正,也欢迎大家来同我讨论交流学习进步。系统调用是给用户态下的程序使用的,但是用户程序并不直接使用系统调用,而是系统调用在用户态下的接口。可以看到,如果中断栈帧中的向量号表示的是系统调用号的话,就会去执行系统调用入口程序。

m0_74282605的博客 523

万字深入分析Linux系统调用与API

内核为了向用户空间提供服务,设计出了系统调用机制,系统调用机制可以让用户空间调用内核里的某些特定的函数。要实现系统调用机制需要有CPU提供的特殊指令才行。由于历史原因,系统调用指令在x86平台上不止有一个。系统调用指令的作用是把CPU模式切换到特权模式、让CPU跳到指定的入口函数来执行,并把用户空间提供的系统调用编号和参数传递进内核。入口函数根据系统调用编号调用相应的函数并传递参数,执行完毕后再返回用户空间。我们一般情况下并不会直接使用系统调用,操作系统为我们提供了非常丰富的API,用起来更方便。

youzhangjing_的博客 1122

Go源码阅读2

golang源码阅读学习

追求幸福,探索未知的博客 327

深入C语言标准库源码:从原理到实践的学习指南

C语言标准库是系统编程的核心基础,它封装了底层操作系统调用,为开发者提供了文件操作、内存管理、字符串处理等通用接口。理解其实现原理,不仅能掌握抽象背后的具体机制,还能学习到防御性编程、错误处理和性能优化的工程实践。通过阅读glibc、musl等开源实现,可以深入分析malloc/free的内存管理策略、printf的格式化解析流程等关键模块。这种源码级探究,尤其适合希望突破平台期、从语言使用者成长为驾驭者的开发者,能显著提升编写健壮、高效、可移植代码的能力。

迷彩风情 1026
上一篇: ELF编译链接过程中有关信息(暂时整理笔记,日后详细补充)
下一篇: 00-boot.asm的代码解读
WriteAnything_
博客等级 码龄5年 66粉丝 39原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值