跟踪系统调用之旅

简介: 想学linux  c开发的博友或者正在学的博友,当你们的代码里出现系统调用,比如read、write、open等。你怎么看、怎么想?有没有想一探究竟,深究一下系统调用的始终。准备好纸和笔,让我们开始系统调用跟踪之旅: 开始之前呢,先花费2分钟概览一下图(1),在你的头脑中做个快照,便于后面分析的理解,以read调用为例,展开分析。

想学linux  c开发的博友或者正在学的博友,当你们的代码里出现系统调用,比如readwriteopen等。你怎么看、怎么想?有没有想一探究竟,深究一下系统调用的始终。准备好纸和笔,让我们开始系统调用跟踪之旅:

开始之前呢,先花费2分钟概览一下图(1),在你的头脑中做个快照,便于后面分析的理解,以read调用为例,展开分析。
           
                 

read函数的声明位于头文件#include

原型为:ssize_t read(int fd, void *buf, size_t count)

read函数在用户空间的伪代码:
                       

说明:

4行,寄存器eax保存了read函数的系统调用号,在 文件include/asm-i386/unistd.h里有定义(#define __NR_read  3);第57行,将三个参数分别放入三个寄存器(通过寄存器来传递参数)

8行,执行系统调用,进入内核;

9行,获取eax寄存器所保存的函数返 回值。

8行是一个中断,执行完第8行后,已经进入了系统内核,中断向量表中记录0x80号的中断处理程序开始执行,中断向量表的初始化在arch/x86_64/kernel/traps.c中定义:
                   

如红框标注所示。IA32_SYSCALL_VECTOR是系统调用的中断号,在include/asm-x86_64/hw_irq.h中定义:
                   

正好是0x80。而system_call是系统调用的中断处理函数指针,用户执行int $0x80后会执行到这个函数,它在arch/x86_64/kernel/entry.S中定义:
                  
                  
                  

SAVE_ALL是一个宏,在这include/asm-x86_64/calling.h文件里定义:


                  

主要作用就是将各个寄存器压入栈中。

cmpl $(nr_syscalls), %eax比较eax的值是否大于等于nr_syscallsnr_syscalls是比最大有效系统调用号大1的值,在arch/i386/kernel/entry.S中定义:

                 

syscall_table_size就是系统调用表的大小(单位:字节),syscall_table_size其实是一个数组,数组里存放的是各个系统调用函数的地址,元素类型是long型,除以4刚好是系统调用函数的个数。

如果从eax寄存器传进来的系统调用号有效,那么就执行第12行,在系统调用表里找到相应的系统调用服务程序,sys_call_tablearch/i386/kernel/entry.S中定义:

                 





*sys_call_table(,%eax,4)指的是sys_call_table里偏移量为%eax*4上的那个值指向的函数,这里%eax=3,那么第5行的sys_read()函数就会被调用。sys_read()/fs/read_write.c中定义:

                   

asmlingage是一个宏,定义为:__attribute__((regparm(0))),作用是让这个函数只从栈上获取参数(因为之前的SAVE_ALL将参数压到了栈里面)。

 Fget_light:根据fd指定的索引,从当前进程描述符中取出相应的file对象,如果没有找到指定的file对象,则返回错误,如果找到了指定的file对象,则调用file_pos_read函数取出此次读写文件的当前位置。

   然后调用vfs_read执行文件读取操作,而这个函数最终调用file->f_op_read指向的函数[fs/read_write.c文件中],代码如下:

                   

接下来调用file_pos_write()更新文件的当前读写位置,调用fput_light更新文件的引用计数。最后返回读取数据的字节数。

思考:file->f_op_read指向的函数是哪个?鉴于篇幅,我们准备在下一篇博文详解,继而开始真正数据读取之旅。

   

当数据读取完毕,需要返回用户态。以下即为推出内核,恢复各个寄存器的值,然后返回用户态的过程。
                 
                 
                 
                 
当执行完中断处理程序后,后面会调用RESTORE_REGS来恢复各个寄存器:

RESTORE_REGS的定义:


                 
                 
                 

                RESTORE_INT_REGS的定义:


                 

       当你耐着性子看到这里,真诚的说一声谢谢。我的劳作是有意义的。我写这篇博文的本意就是让自己在头脑形成一条清晰的脉络,read系统调用的清晰脉络。在平时分析问题的时候,沿着这条清晰的脉络,将疑难一一排除。对了,写这篇博文时,我参照的系统内核源码版本是:
linux-2.6.0



      Good luck for you!

目录
相关文章
|
存储 算法 NoSQL
接口限流
防止用户恶意刷新接口, 防止对接口的恶意请求,减少不必要的资源浪费,从而保证服务可用。如果不做限流,任由某个用户以非正常方式高频率访问的话,会直接将网络流量、服务器资源挤占完,从而影响正常对外提供服务,造成服务不可用。
345 1
|
1月前
|
关系型数据库 MySQL Unix
MySQL中日期和时间函数的使用指南
使用这些函数可以有效地处理和分析日期和时间数据,对于数据库管理、报表生成和数据分析非常关键。在实际应用中,根据具体需求选择适当的函数进行数据处理,可以极大地提高数据处理的效率和准确性。
175 17
|
9月前
|
分布式计算 大数据 数据处理
从Excel到大数据:别让工具限制你的思维!
从Excel到大数据:别让工具限制你的思维!
370 85
|
C# 开发者 Windows
WPF 应用程序开发:一分钟入门
本文介绍 Windows Presentation Foundation (WPF),这是一种用于构建高质量、可缩放的 Windows 桌面应用程序的框架,支持 XAML 语言,方便 UI 设计与逻辑分离。文章涵盖 WPF 基础概念、代码示例,并深入探讨常见问题及解决方案,包括数据绑定、控件样式与模板、布局管理等方面,帮助开发者高效掌握 WPF 开发技巧。
383 65
|
数据处理 Python
Python 高级技巧:深入解析读取 Excel 文件的多种方法
在数据分析中,从 Excel 文件读取数据是常见需求。本文介绍了使用 Python 的三个库:`pandas`、`openpyxl` 和 `xlrd` 来高效处理 Excel 文件的方法。`pandas` 提供了简洁的接口,而 `openpyxl` 和 `xlrd` 则针对不同版本的 Excel 文件格式提供了详细的数据读取和处理功能。此外,还介绍了如何处理复杂格式(如合并单元格)和进行性能优化(如分块读取)。通过这些技巧,可以轻松应对各种 Excel 数据处理任务。
711 16
|
数据采集 存储 监控
CDGA|做好数据治理的几个策略,不看后悔
做好数据治理是企业实现数字化转型和智能化升级的关键。通过明确目标、建立组织、制定标准、实施质量管理、促进共享与协作以及持续优化与迭代等策略,企业可以构建完善的数据治理体系,提升数据价值,为业务决策提供有力支持。在未来的发展中,数据治理将成为企业核心竞争力的重要组成部分。
|
关系型数据库 Java Linux
在Linux中,有哪些基本组件?
在Linux中,有哪些基本组件?
|
机器学习/深度学习 存储 算法
【2022天府杯数学建模】A题 仪器故障智能诊断技术 一等奖总结及Python实现代码
关于2022天府杯数学建模A题“仪器故障智能诊断技术”的一等奖总结,包括问题解析、Python实现代码,涵盖了信号去噪、特征提取、无监督和有监督学习方法在故障诊断中的应用,以及聚类和分类算法的性能评估。
267 1
十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!(三)
十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!