- 博客(40)
- 资源 (3)
- 收藏
- 关注
原创 linux面试题:操作系统是怎么知道 IO 就绪的
这篇文章探讨了Linux系统中IO就绪后唤醒进程的机制。作者通过分析V站帖子中提到的面试问题,重点研究了ttwu(try to wake up)唤醒进程的过程。通过使用bpftrace工具追踪sched_wakeup事件,作者捕获到一个内核态调用栈,展示了从TTY终端写入到唤醒对端进程的完整路径。进一步通过gdb调试内核,作者详细分析了ttwu_do_activate函数调用栈,揭示了IO就绪后通过工作队列(worker_pool)唤醒阻塞进程的具体实现机制。文章最后指出,唤醒操作会从worker_pool
2025-08-15 10:15:18
660
原创 从内核源码角度理解cgroup cpu中的cfs_period_us、cfs_quota_us配置
摘要:Linux内核5.10.202版本中,CFS调度器通过定时器机制实现带宽控制。当定时器周期到期时,会调用sched_cfs_period_timer回调函数,将任务的剩余可用时间(runtime)重置为预设的配额值(quota)。该机制通过__refill_cfs_bandwidth_runtime函数实现,确保任务在每个周期内获得固定的CPU时间配额。定时器初始化时配置了回调函数,并在到期时触发时间补充,从而维持公平调度。
2025-08-07 09:07:53
396
原创 抓虫:xfce桌面丢失权能
摘要:系统发现secadm用户登录后权能丢失问题。经排查,发现lightdm启动的xfce4-session进程未通过pam_cap.so模块继承权能。在/etc/pam.d/lightdm中添加auth required pam_cap.so keepcaps后,终端bash权能恢复。该问题一小时定位,但最终修复方案需仓库管理员根据lightdm三个PAM文件的具体作用进一步确认。
2025-08-06 10:18:02
170
原创 linux面试题:Ctrl+Alt+Fx 切换 tty 这个功能是在哪里实现的?
Linux终端切换功能实现分析 文章探讨了Linux系统中Ctrl+Alt+Fx切换tty功能的实现机制。通过分析发现: 终端切换功能主要由systemd-logind服务实现,通过ioctl(fd, VT_ACTIVATE)系统调用来完成 使用chvt命令可以直接切换终端,其核心逻辑是调用VT_ACTIVATE和VT_WAITACTIVE的ioctl操作 在SSH的pts终端中执行chvt可能无效,需要在真实tty终端中操作 通过strace跟踪发现,按键切换时会触发systemd-logind服务读取/
2025-07-31 15:13:52
850
原创 c++,lambda是匿名函数也可能不是函数,从汇编底层角度深入理解带捕获的lambda如何转化为std::function
摘要:本文通过分析C++中std::function的汇编实现,揭示了其内部工作机制。std::function是一个类而非单纯别名,其构造函数接收lambda捕获变量的地址而非函数指针。关键实现细节包括通过_Base_manager初始化函数对象,存储_M_invoker调用地址,以及利用完美转发传递参数。汇编代码显示function对象保存了lambda的调用器地址和管理器指针,验证了其作为通用函数包装器的类实现本质。(149字)
2025-07-22 16:07:34
732
原创 c++,从汇编角度看lambda
本文通过汇编分析揭示了C++ lambda表达式的工作机制。实验通过4个不同lambda示例,发现每个lambda都会生成对应的函数符号。不带捕获的lambda调用时传入无意义地址参数(类似this指针但大小为1);带捕获的lambda会将捕获变量按顺序排列形成内存块,调用时传入该内存块地址(类似结构体指针传参)。参数传递方式与常规函数一致,其中带默认参数的lambda会直接传入默认值。这些发现为后续研究lambda如何转换为std::function奠定了基础,展示了编译器对lambda的底层实现方式。
2025-07-22 14:39:09
276
原创 c++,stl库阅读之std::forword完美转发
摘要:完美转发通过std::forward解决模板函数中的引用丢失问题。它利用模板类型推导和引用折叠规则:当参数为通用引用(T&&)时,左值推导为T&,右值推导为T&&;通过remove_reference获取原始类型,再配合static_cast<_Tp&&>实现引用类型的完美转发。关键点包括:1)必须在模板函数中使用以自动推导类型;2)引用折叠规则确保引用类型正确传递;3)避免手动指定类型以保持自动化特性。示例代码演示了左值/右值的转发
2025-07-21 17:47:24
159
原创 c++,邪恶的花括号!列表初始化构造实现方式
文章摘要:讨论了C++中花括号初始化{}的使用场景,重点分析了std::vector的初始化列表构造实现。通过汇编代码解析,展示了initializer_list的内部工作机制:编译器会将{64,64}转换为数组指针和大小参数,并调用vector的初始化列表构造函数。文中还对比了四种初始化方式的适用场景,强调应根据代码意图选择最清晰可读的初始化方式,而非强制使用单一语法。最后指出initializer_list通过私有构造函数实现,编译器可直接调用。
2025-07-18 11:19:47
139
原创 C++无用的知识,inline不是宏,没有魔法!
摘要:《More Effective C++》指出,静态成员函数使用inline不会导致静态变量被复制,这与宏不同。示例代码显示,内联后的static_member()函数中静态变量i仍保持单一实例,输出结果为1和2,符合预期。相比之下,宏替换可能导致变量多次自增,产生意外结果(如4)。说明内联函数不会改变代码语义,而宏可能带来副作用。关键区别在于内联保持程序逻辑,而宏可能破坏设计意图。
2025-07-12 12:22:08
399
原创 c++,用 delete [] 释放 new 对象,会发生什么???
摘要:文章通过分析C++汇编代码,揭示了delete和delete[]的内存管理机制差异。delete[]通过访问数组对象前8字节获取元素个数(如new string[2]会在内存-8处存储2),而普通delete仅处理单个对象。在示例中:1) delete_normal(s)正确,2) delete_array(s)会越界访问;3) delete_normal(s2)会内存泄漏,4) delete_array(s2)正确。关键发现:new[]返回地址实际是"数组头-8",delete[
2025-07-11 14:21:48
289
原创 C++,从汇编角度看《虚拟继承的邪恶》
摘要:文章通过分析一个C++虚继承案例揭示了反直觉的输出结果(123和0)。代码中D(456)输出0的原因是虚继承初始化规则:1)虚基类A由最底层派生类D初始化;2)在D构造过程中,中间类C的构造函数未实际调用A(a),导致A被默认初始化为0。通过反汇编验证发现,编译器会生成两个版本的C构造函数,分别处理直接实例化和作为中间类的情况,解释了虚继承的底层实现机制。
2025-07-11 13:21:55
426
原创 c++的拷贝省略,返回局部类,如何实现?
本文探讨了C++中的拷贝省略(copy elision)优化机制。通过分析函数返回局部对象时的汇编代码,展示了编译器如何优化掉不必要的拷贝构造。在默认情况下,编译器会将返回对象的地址直接传递给调用方,避免临时对象的构造和拷贝。当使用-fno-elide-constructors选项时,编译器会生成完整的拷贝构造流程。文章通过对比两种编译方式的汇编代码,揭示了拷贝省略优化的实现机制,说明编译器如何通过参数传递优化来避免对象拷贝的开销。
2025-07-09 14:33:37
423
原创 c++的默认参数怎么回事?
摘要:通过分析C++程序的反汇编代码发现,带默认参数的函数(func_arg_with_default_val)和不带默认参数的函数(func_arg_without_default_val)在函数体部分完全相同。关键区别在于调用处:当调用带默认参数的函数时,若未显式传参,编译器会在调用时自动填充默认值(如main函数中默认传0)。这说明默认参数的处理是在调用阶段而非函数体内部实现的,与函数声明时的参数设置密切相关。该机制与C++的函数声明特性一致,验证了默认参数是在编译时根据函数声明信息处理的。
2025-07-02 11:30:52
139
原创 sysak中的iosdiag latency分析
总延迟 =block_getrq (类似于部分bcc工具中使用的blk_account_io_start hock位置)其余延迟为:block_getrq -> rq issue, rq issue -> rq done, rq done ->IO_ISSUE_DEVICE_POINT, // virtblk/scsi rq issue 驱动层这里 驱动代码位于 tracepoint/rq_issue 前后都有可能,位置随意。
2025-06-26 17:15:09
693
原创 iostat中的util原理
带上-x选项,最后一列是一个util列,这个值很重要,体现这个设备忙不忙。就像windows中的任务管理器看磁盘一样,如果磁盘导致性能非常卡,磁盘会使用率100%,延迟也很高。
2025-06-24 16:48:34
364
原创 摆脱跳板,使用bpftrace任意时刻暂停程序等待gdb附加
以前调试的时候,经常会用到一系列进程启动,需要附加到某一个进程,这个进程可能被其他程序唤起的,又很快就结束了,也不能直接执行这个程序复现情况,必须要在当时的现场中运行。上面的步骤中,/dev/pts/13是另一个终端,要把gdb的pid发送到另一个终端中,方便另一个终端中使用gdb附加到这个出错的gdb中。然后sleep(10)为了留出时间附加,在接下来execve将会将这个跳板替换为真正的gdb程序。
2025-04-03 10:23:23
314
原创 抓虫:捡个漏,loongarch架构gdb dump Assertion `supply_size == collect_size‘ failed.
loongarch架构的系统中,gcore命令用于转储进程,此时gcore会挂掉报错,一个断言错误。
2025-03-27 13:17:55
1076
原创 BCC-应用程序组件分析
追踪glibc中的函数用时以为例,域名的访问需要先解析域名为ip,再对ip进行访问。解析域名大多数应用层程序会通过调用glibc的相关函数解析。
2025-03-26 14:49:41
749
原创 BCC-CPU模块梳理
统计各类型硬中断消耗时间部分类型的中断处理分上半部和下半部,如网络,网络硬中断只负责唤醒软中断,硬中断只会耗时非常短。部分类型的中断处理和cpu数量成倍关系。
2025-03-25 15:37:09
647
原创 BCC-调度组件分析
第一个百分比 running/总,代表cpu的负载,类似于top命令看到的负载/cpu个数或windows任务管理器显示的cpu负载百分比。上面的示例就是8核cpu上8开启了8个任务但8个任务都设置了绑定到一个cpu上。用以计算cpu无人认领的几率,代表有任务都被挤在个别cpu了有的核心空闲,有的核心任务太多。统计任务加入调度队列或失去CPU时到获取CPU任务上线的时间间隔,以直方图呈现。统计任务加入调度队列或失去CPU时到获取CPU任务上线的时间间隔。统计进程从失去到重新获得CPU的次数,按栈计数。
2025-03-25 15:35:39
1100
原创 BCC-BIO组件分析
对于不同的硬盘物理形态该值的重要性可能不同,对于机械硬盘连续的IO请求对于磁头寻道可能更加友好,但对于SSD,IO是否连续影响可能较小。上方输出表示在一段间隔(默认3s)时,最长的(100%列)写耗时255us完成(on-device开始至结束),大部分写IO可在5us内完成。一次提交IO的长度对于硬盘的物理形态、总线协议也可能有不同的重要性,有些总线一次通信报文长度有限。该位置通常位于块设备驱动层,准备将队列中的扇区对设备操作,此。该位置通常位于块设备驱动层,准备将队列中的扇区对设备操作。
2025-03-25 15:34:13
835
原创 BCC-文件系统组件分析
对于和中的接口并不是会被vfs层直接调用,如果内核处理文件时已经获取到inode或其他表示文件的结构体信息可以直接调用文件系统层的接口操作文件。系统调用open时如果需要创建文件并不通过vfs_createvfs_create用于创建其他特殊类型文件,创建普通文件会在namei层直接调用文件系统的create接口。
2025-03-25 10:21:29
941
原创 tracepoint真的比kprobe开销更小吗???
本文通过实践分析了eBPF程序在追踪点(tracepoint)和kprobe两种场景下的性能开销。作者选取了Linux内核中两个简单的函数blk_mq_sched_request_inserted和nonseekable_open作为测试对象,使用gdb调试内核,观察了eBPF附加前后指令的变化。研究发现,tracepoint会创建一份函数体副本,并修改跳转指令;当eBPF程序附加时,原有的调用路径会被替换为perf_trace调用。通过调试bpf_printk的执行路径,揭示了从tracepoint到eB
2025-03-13 12:29:11
826
原创 从操作系统新的视角看hello world
本篇紧跟上篇《栈-函数调用轨迹图》根据上一篇,知道栈的两个寄存器位置rbprsprip,在内存中便可以获取进程当前执行到了哪个位置,被哪个函数调用到的。虚拟内存:能运行主线linux的芯片都带有专门的设计支持虚拟内存。虚拟内存可以由内核分配给各个进程内存空间,这些分配的空间的内存地址对于各个进程而言不再是物理地址,而是虚拟的地址,每个进程的内存地址各自独立互不影响。每个进程申请到的内存就像是这个进程私有的内存一样使用,互相不影响。虚拟内存概念先了解即可,后面会用到。
2025-03-10 18:12:59
488
原创 栈-函数调用轨迹图
是一个和现在讲的栈有关的选项,以前的一些操作系统为了性能优化和常规程序栈的方式不太一样,以前的已经淘汰不再详述,现在较新的操作系统如。至于这两个寄存器函数跳转如何变化的,,每个函数的开头都是这样的两行,上一个函数的。指令的下一个指令位置(即跳转函数的返回位置)入栈,函数执行结束返回时就会跳转到到。代表新的栈的开始位置,由于栈是自顶向下的所以。区域就是函数内的一个栈帧,函数不发生跳转。函数的位置,这样就完成了一次栈的查找,在。的位置应该就是上一个函数的位置,也就是,指令的下一条位置,符合刚才提到的。
2025-03-09 22:01:53
348
原创 linux网络数据从网卡到应用层需要几次内存拷贝?
环境不考虑报文特殊处理,需要两次数据拷贝。一次发生在网卡收包,网卡的环形队列固定大小,网卡驱动将包放在环形队列,内核需要及时将这些包取走否则队列满网卡将丢弃接下来的包。内核从网卡环形队列中取走放到结构中,在内核的接下来协议栈、socket处理中,始终使用这个结构不需要内存拷贝。第二次内存拷贝发生在内核态到用户态中,用户态进程取回报文中的内容。
2025-02-25 10:58:55
451
原创 eBPF调度器追踪部分项目源码分析
本文分析了几个主流调度器延迟检测工具的实现方式,主要包括bcc的runqlat和runqslower,以及字节跳动的trace-runqlat项目。 这些工具都基于Linux内核的调度器跟踪点(sched_wakeup、sched_wakeup_new、sched_switch等)来测量进程从就绪到实际运行的时间延迟。核心原理是: 在进程唤醒时(sched_wakeup)记录时间戳 在进程实际运行时(sched_switch)计算时间差 runqlat输出延迟分布直方图,runqslower仅显示超过阈值的
2025-01-03 18:03:07
752
原创 抓虫:申威编译gcc过程中f951程序dump
摘要:在构建GCC 8.5.0时出现Fortran编译器错误,配置阶段检测到GNU Fortran无法正常工作。错误日志显示编译器在尝试编译简单测试程序时发生段错误,导致构建失败。建议将错误报告提交至GCC官方bugzilla,并附上config.log文件以便进一步分析问题原因。
2024-12-19 10:48:29
800
原创 抓虫:lorax在mips64el中dump,未能使用指定的配置文件
文件,对内核文件在这个文件中有特殊处理,期望lorax会使用这个文件。在mips64平台中,内核中的文件不一样,版本组新增了这样一个。首先,观察lorax的输出日志,发现这里有一行是使用到了一个。命令追踪制作镜像的过程中使用了哪些脚本,并没有使用到新建的。修改lorax脚本,使用pdb看一下哪里执行到的这。的369行已经报错了。mips中的kernel相关问题,在。这里是lorax脚本里添了一行。的371行,此刻还没有走到这里。而继续运行报错的时候,,找到是在这里输出的。,找到这个地方赋值的。
2024-12-06 13:31:58
357
原创 linux内核从源码详解ext4文件系统
rec_len属性标记一个条目的长度,这个长度可能超过结构体+name实际长度,甚至是远超,可能是文件夹内删除条目时调整,也可能是占位,因为文件夹类型的文件总是和文件系统的块大小整数倍的,如果文件夹内只有一个条目(即使不包含。都是硬盘中实际存储的内容,并不方便在内存中直接使用,有的要做大小端转化,有的要高位地位合并,所以下面的信息就是把常用的信息处理好,方便直接使用。获取设备的逻辑块大小,ext4的最小块大小为1024B,如果设备的块小于ext4的最小块则默认为ext4的最块。
2024-12-05 14:46:38
1228
原创 抓虫:mips架构systemd部分命令移除rpath会dump
systemd的较多命令原先使用rpath控制systemd相关动态库的搜索路径,在后续某次版本中,移除了rpath的方式,改为通过ld.so.conf.d中添加配置文件从上面的程序执行上看,命令必然是执行了的,输出了消息,意味着动态库必然是找到并加载成功了的。通过查看也能看到动态库和原先使用rpath时使用的动态库也是一致的。。。
2024-11-14 10:44:26
637
原创 那么,古尔丹,读写锁的代价是什么呢
在有临界区的情况下,读写锁是有作用的但是,有临界区不属于优秀的程序设计,程序设计应该减少资源互斥,尽可能临界区足够可能是临界区的存在,读锁多线程同时访问起到了作用,读锁的开销≈(互斥锁开销+互斥锁导致的调度开销)在优秀的多线程设计中,临界区足够小的时候,读写锁确实没有优势,不如互斥锁那么简洁不易产生问题。有些锁的封装库或是新的语言有互斥锁,但没有提供读写锁,也行也是这个问题例如下面的伪代码,使用非常小的临界区对共享资源读写,优秀设计read() {{ # 临界区write() {
2024-07-23 11:04:19
417
原创 抓虫:chown失败 Couldn‘t change ownership of savefile
chown报错 Couldn't change ownership of savefile使用ftrace/bpftrace 内核跟踪
2024-06-05 16:41:29
763
原创 centos断开网线,桌面不提示依然显示链接,ip也接着显示,问题排查
属性不正常,正常时此属性为false,不正常时为true,定位到/usr/lib64/libnm.so中。通过和正常的centos情况比对,包后会默认配置忽略carrier。属性标识是否链接,此属性正常。
2024-01-11 15:23:46
590
原创 龙蜥anolis系统迁移组件ance逆向分析、追踪venv,cython生成的so库python执行
摘要:本文介绍了如何跟踪和分析 sysom 组件中的 ance(系统状态检测工具)的运行情况。ance 采用 Python 编写但不开源,通过解包其虚拟环境并修改解释器路径,可以替换为外部 Python 解释器进行调试。文中详细展示了如何通过 strace/ltrace 跟踪文件读取和命令执行,以及使用 GDB 调试 CPython 解释器来查看 Python 类型值和函数调用堆栈。这些方法可用于定位 ance 崩溃时的具体问题,特别是针对其内核扫描和收集功能的分析。
2024-01-08 09:28:14
870
原创 cPython中的Type、Object结构体定义、内存布局
cPython中,一个package、一个module,甚至一个function,都是一个类,每个类都有自己的Type类表示自己的class类型内存布局PyObject 类指针(类的size存储在这里,私有成员影响size)、引用计数私有成员类.ob_base.ob_size = sizoef(类)
2024-01-08 09:25:53
1278
原创 execve 继承了什么?映射、信号、文件描述符、优先级、ptrace
execve syscall 做了什么重要参考Linux 进程启动 execve 系统调用内核源码解析sp 就绪 执行环境okmaps 映射父进程的所有maps都会消失里被替换为新的进程的mmfiles 文件描述符不变 对除了复制下来外没有额外处理(除了open时候标记为O_CLOEXEC的会被关闭)stdin stdout stderr 和其他 都不会有变化 继承父进程,bash中的管道得以实现信号除了忽略的,其他都被重置为默认信号处理。
2024-01-08 09:13:37
1173
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人