- 博客(51)
- 资源 (12)
- 收藏
- 关注
原创 arm linux下的读写信号量rw_semphore的实现
是的话,则设置信号量count为RWSEM_WRITER_LOCKED (1<<0). 否则__down_write_trylock()就是获取信号量失败,down_write()则调用__down_write()去获取写信号量。所以,在armv7下,atomic_try_cmpxchg_relaxed没有#define.故,__down_read_trylock() -> atomic_long_try_cmpxchg_acquire() -> atomic_try_cmpxchg_acquire()
2025-03-19 16:02:39
816
原创 linux下块设备mmc代码流程
但这里3255行的file->f_mapping->a_ops不是ramfs_aops,因为在open’/dev/mmcblk0p0’的时候,file->f_mapping被替换为disk inode的bdev->bd_inode->i_mapping, 这个bdev->bd_inode->i_mapping就是bdev->bd_inode->i_data.a_ops, 即def_blk_aops。定义中emmc是emmc_controller的child,一个emmc连接一个emmc flash芯片。
2025-03-13 16:12:37
537
原创 linux ACPI PCIe扫描
acpi_pci_root_create()在调用acpi_pci_probe_root_resources()处理完IO资源后,调用pci_scan_child_bus()开始取扫描root bus下的devices了(1066行),我们接着看这个扫描函数pci_scan_child_bus().1404行:acpi_bus_init()->acpi_load_tables()->acpi_tb_load_namespace()->acpi_ns_load_table()->
2025-03-05 14:24:19
683
原创 arm linux下的中断处理过程。
irq_handler这个宏就是调用handle_arch_irq, 这个处理函数就是前面初始化介绍过在start_kernel() -> init_IRQ() -> irqchip_init() -> of_irq_init() -> gic_of_init() ->__gic_init_bases() -> set_handle_irq()的注册的函数gic_handle_irq().gic_of_init()调用__gic_init_bases()去设置各种处理函数。
2025-02-11 18:19:30
982
原创 linux kenel的三大内存管理
文章是基于openbmc ast2600的配置来写的。本文主要简单介绍三种内存管理: memblock、buddy、slub。原文写在自己的ppt中,不想重新排版了,直接截图过来了,见谅!
2025-01-22 15:01:33
215
原创 openbmc ast2600 jffs2挂载mtd5(rwfs)失败
然后再fs/jffs2/scan.c jffs2_scan_eraseblock()跟踪打印,最后发现是aspeed spi驱动读数据操作有问题,一直都是读master mtd base offset为0处的数据(spi flash为xip flash,前256M可直接寻址访问)。查看image文件,发现这些数据是image开头的数据,也就是u-boot分区中的数据,而不是rwfs分区的数据。这个问题可能有很多原因,有flash配置问题,有image打包问题。这些都不是我的板子上的问题。
2024-12-13 09:26:53
842
原创 ast2600 i2c framework
然后 device_add() ---> bus_probe_device(&i2c_bus_type)i2cdev_write() ---> i2c_master_send() ---> i2c_master_send() ---> i2c_transfer_buffer_flags() ---> i2c_transfer() ---> __i2c_transfer() ---> adap->algo->master_xfer().create_files()将group中的所有attrs创建文件。
2024-10-17 16:43:26
957
原创 BMC panic 之cpu stuck问题分析
当watchdog定时器超时时(这个必然发生,也就是每4s会调用一次超时处理函数watchdog_timer_fn),watchdog_timer_fn()得到调用,它会启动当前cpu的stopper task,这个stopper task通过函数softlockup_fn()来复位当前cpu的soft lockup时间为当前时间。每个cpu(准确的说是core)上电上线后,都会启动一个watchdog定时器,用来监测soft lockup是否超时,以实现监测当前cpu是否一直超长时间被某个task占用。
2024-10-17 14:23:35
556
原创 flex/bison结合使用解析配置文件
当data_parser.tab.c中的yyparser()被调用时,它会循环调用flex的yylex(), yylex()则从yyin指定的配置文件中读取内容,去匹配flex的lex.yy.c定义的规则表达式。yyparser()拿到%token后,会执行bison语法文件定义的rule的action, 从而完成整个配置文件的解析(我们的示例程序只打印解析出来的数据,实际应用时,可以将数据写到我们自己定义的结构体变量中去)。匹配到后,执行对应的action,return相应的%token.
2024-07-30 15:25:10
820
原创 flex/lex使用和学习
definitions就是定义一些变量,或者一些C代码段,用%{<c code>%}包含的c code会被原封不动的拷贝到lex.yy.c中。flex/lex用于生成解析配置文件的C代码,我们可以不用自己手动去做解析的工作,交由他们生成的代码去做。要生成lex.yy.c,我们需要编译个*.l文件,flex工具根据这个*.l来生成lex.yy.c。user code就是一些用户自己定义的函数,这些函数会原封不动的拷贝到yy.tex.c中。好了,*.l写好了,我们使用flex命令来生成yy.lex.c.
2024-07-26 17:07:01
487
原创 I2C framework
驱动drivers/i2c/i2c-core-base.c注册了i2c总线类i2c_bus_type,我们说的i2c0等具体的i2c总线需要注册到这个i2c_bus_type./dev/i2cX是i2c总线设备驱动文件。I2C总线是一种字符设备。先来看驱动drivers/i2c/i2c-core-base.c。
2024-07-26 08:44:46
195
原创 使用wireshark解密ipsec ISAKMP包
Ipsec首先要通过ikev2协议来协商自己后续协商所用的加解密key以及用户数据的esp包用的加解密包。ISAKMP就是加密过的ike-v2的加密包,有时候我们需要解密这个包来查看协商数据。如何来解密这样的包?点击apply后,对应的包就被解密了。
2023-10-09 17:28:05
2140
1
原创 使用wireshark解析ipsec esp包
Ipsec esp包就是ipsec通过ike协议协商好后建立的通信隧道使用的加密包,该加密包里面就是用户的数据,比如通过的语音等。那么如何将抓出来的esp包解析出来看呢?获取相关的esp的key信息.打开wireshark -> edit->preferences找到protocol->esp右边依次填入相关的信息:SA#1的格式为: protocol|source address| destination address|SPIProtocol为网络层协议
2023-10-09 17:02:09
3311
原创 linux usb gadget driver代码
中断发生时,通过ast_vhub_irq() -> ast_vhub_epn_ack_irq() -> ast_vhub_epn_handle_ack() -> ast_vhub_done() -> usb_gadget_giveback_request(),将数据放到req->buf中,收完后,调用req->complete()来结束,这个req->complete()就是bulk_out_complete和bulk_in_complete.但它提供了mkdir的操作function_make()。
2023-05-06 09:11:51
2909
3
原创 linux下动态库so的debug方式
然后‘cat /proc/1/maps_file | grep xxx.so’得到映射的虚地址空间,最后,gdb attach 该进程,使用dump memory将so对应的地址dump出来。使用lsof找到一个使用该so的进程,比如Pid为1.3. 将动态库so加载到的内存中的内容dump出来。2. 查看elf文件link了哪些动态库so。1. 查看哪些进程使用了特定的动态库so。使用gdb, attach 某个进程。4. dump 内存。
2023-04-14 14:57:49
1420
原创 bash: ./<one_executable_file>: no such file or directory
关于这个问题,原因很多。但大部分的资料都是说PATH环境变量坏掉了,或者/etc/profile坏掉了。但其实,还有一种原因,就是你的可执行程序<one_executable_file>是elf32,而当前的linux环境却是64位的。如果系统中没有安装32bit的包,那么,所有elf32的可执行程序,都会被bash报告这个错误:no such file or directory。64位系统上安装32位的包,举例如下:$ sudo dpkg --add-architecture
2021-12-09 14:35:41
427
原创 linuxn内存管理之buddy
本文基于linux-3.11.1代码, arm cpu, flat memory model(平坦连续的内存,用于嵌入式)为背景来说明。start_kernel() -> setup_arch()arch/arm/kernel/setup.c883行,调用setup_machine_fdt() -> early_init_dt_scan() -> early_init_dt_scan_memory() -> early_init_dt_add_memory
2021-07-26 10:07:38
464
原创 linux MMU以及初始化过程内存布局
本文以linux-3.14.17(arm)版本的代码来讲述linux从第一行代码运行至start_kernel()的过程。arch/arm/kernel/vm-linux.lds链接脚本定义了kernel image各段的分布,以及定义了一些全局符号,如下图:这个链接脚本同时定义了入口符号stext.stext定义在arch/arm/kernel/head.S92行safe_svcmode_maskall做了些什么?arch/arm/include/asm/assembl
2021-06-16 17:57:09
2405
3
原创 linux kernel同步之mutex
互斥锁,顾名思义,就是互斥的,独占的,只能有一个进程占有锁,其他进程都得等待锁占有者释放互斥锁,才有可能占有锁。以下的内容是基于linux-3.11.1(arm)内核代码来讲解内核中mutex的实现。mutex的定义:linux-3.11.1/include/linux/mutex.h其中, count表示空闲资源的数目,初始值为1,表示只有一个资源可用,即只能一个进程可以用。count: 1 表示可以lockcount: 0 表示锁被某个进程lock了,且没有其他进程来lock
2021-06-01 14:19:28
803
原创 linux的用户态堆栈(sp_usr)和内核态堆栈(sp_svc)
在arm linux中,进程的运行处于两种模式之一,要么在用户空间运行(用户模式USR_MODE),要么在内核空间运行(SVC_MODE)。在内核空间时,处于特权模式,在用户空间时,处于普通模式。用户空间运行时和内核空间运行时,所用的堆栈是不同的。本文基于linux-3.11.1代码来学习这两种运行空间下,堆栈是如何运作的(切换)。linux-3.11.1/kernel/fork.cSYSCALL_DEFINE0(fork) -> do_fork() -> copy_proces
2021-05-28 18:12:27
2134
1
原创 linux kernel中的DTS解析到platform_device的注册
在linux内核早期的时候,每个嵌入式系统的板载信息(总线,设备的寄存器地址等)都是hardcode在arch/<cpu>/match-xxx/board-xxx.c之类的文件中,即必须存在这样的c文件,里面定义了板子上的硬件的地址等信息。这样做会造成很多很多的大量相似的没多少用的重复代码。为了解决这个问题,而引入了DTS(device tree source)。每个嵌入式系统的描述硬件信息的DTS文件存放在arch/<cpu>/boot/dts/目录下,比如ast250
2021-04-27 16:39:16
2567
原创 Ethernet下字节序和bit序的总结
Ethernet下字节序和bit序的总结本文讲述的是在ethernet中多字节数据发送时涉及到字节序和bit序的剖析。关于字节序(大小端)和bit序,以及MSB和LSB的叙述,请另行学习,本篇不涉及。正文开始:对于多字节数据的发送(ethernet上是一个字节一个字节的传送数据的,故,对于多字节的数据,必然存在要先发送哪个字节,后发送哪个字节的顺序问题),这个很多文章都讲清楚了,这里快速过一下:比如要发送4字节的int型数据0x12345678, 由于网络上要求的是大端字节序,那么要求发
2021-04-16 16:37:21
4414
6
原创 linux下non-preempt的RCU实现分析(基于rcu-tree)
本文讲述的是linux 4.7.1下的RCU实现(tree-RCU)。在kernel中,rcu有tiny rcu和tree rcu两种实现,tiny rcu更加简洁,通常用在小型嵌入式系统中,tree rcu则被广泛使用在了server, desktop以及android系统中.RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构,读者不需要获得任何锁就可以访问它,但写者在访问它时首先拷贝一个副本,然后对副本进行修改,最后使用一个
2021-03-24 15:39:53
1561
转载 BPF filter
原文:https://www.gsp.com/cgi-bin/man.cgi?section=4&topic=bpf#1FILTER MACHINEA filter program is an array of instructions, with all branches forwardly directed, terminated by areturninstruction. Each instruction performs some action on the pseud...
2021-03-18 10:32:43
641
原创 ARM下的读写锁rwlock实现
内核同步之读写锁rwlock_t本文讲述的是基于linux 4.7.1版本的。我们先来看读写锁的结构体定义:include/linux/rwlock_types.h这里只考虑raw_lock一个成员。arch/arm/include/asm/spinlock_types.harch_rwlock_t只有一个成员lock.下面,我们来介绍相关的API。1. rwlock_init()这个用来初始化rwlock.include/linux/rwlock.h
2021-03-09 16:32:36
813
原创 ARM下的自旋锁spinlock
本文讲述的是linux 4.7.1下ARM architecture的自旋锁spinlock的实现。先来看定义:include/linux/spinlock_types.h我们不考虑CONFIG_DEBUG_LOCK_ALLOC, spinlock_t结构体中只有一个成员struct raw_spinlock rlock. struct raw_spinlock也只有一个成员arch_spinlock_t raw_lock.arch/arm/include/asm/spinlock_ty
2021-03-08 17:15:17
1334
原创 k8s下POD之间的通信过程
本文主要描述同一个node之内的pod之间的通信,以及不同node之间的pod之间的通信。同一个node上的不同pod之间的通信:假设上图的POD A要和POD B 通信: POD A 发送一个包,目的ip为POD B,当包路由后,按路由从POD A的veth0接口出去。这是查找veth0接口下的arp table,如果arp table中没有POD B的record,则进行arp地址解析,即发送arp request,请求reserve 10.1.20.3的mac地址,这个arp reques
2021-03-03 15:40:55
6630
4
原创 linux下strongswan workflow
Strongswan starter is the excutable program, located at /usr/libexec/ipsec/starter.(strongswan/src/starter/starter.c)Usage: starter [--nofork] [--auto-update <sec>][--debug|--debug-more|--debug-all|--nolog][--attach-gdb] [--daemon <name>]
2021-03-03 15:24:29
1993
2
原创 linux下的ip tunnel workflow
预置条件: PC1发送包到PC2,PC1和PC2在不同的局域网中,要使得PC1的包能够到达PC2,有两种途径:使用NAT 使用ip tunnel这里,我们只介绍ip tunnel这种方式。PC1发往PC2的包的src为192.168.1.10,dst为192.168.2.10,PC1首先将包发往网关GW1。在网关GW1和GW2之间建立ip tunnel,使得PC1的包能到达GW2。先介绍网关GW1和GW2的ip tunnel的配置。GW1:#iptunneladdtun...
2021-03-03 15:17:13
1085
1
原创 oprofile的使用
本文介绍的是>=1.0.0版本的,以前的opcontrol是之前的版本,现在不推荐使用。1.0.0版本之后使用的是operf, opreport, opannotate.文档官方地址: https://oprofile.sourceforge.io/doc/index.htmloprofile是一系列性能监视工具集,包含operf, opreport, opannotate等工具。它依赖于硬件的”performance counter”。oprofile需要你的linux版本不低于2.6.
2021-03-01 16:07:03
2211
原创 linux CFS调度和load balance
内容有点多,文章篇幅长!!!本文讲述的是基于sched entity的cfs调度和load balance,不涉及group的cfs调度和load balance. 代码是基于linux-4.7.1.首先,我们来看一下两个初始化sched_init()和sched_init_smp()。start_kernel() -> sched_init()kernel/sched/core.csched_init()为每个cpu的rq(running queue)初始
2021-02-20 09:53:04
928
原创 linux ARM多处理器的启动过程
本文的假设前提: 单CPU(同一个package/socket), 多核multi-core, smp。在smp系统中,primary cpu进入start_kernel()执行。init/main.cboot_cpu_init()将primary cpu设置为active, present, possible, online。setup_arch()将构建machine_desc(单板硬件描述),设置secondary cpu引导方式psci。arch/arm/kernel/s
2020-12-04 18:18:51
2888
原创 linux X86下的段地址_段内偏移_虚拟地址_线性地址_物理地址
本文描述的是基于Linux下的x86的段地址、段内偏移、虚拟地址、线性地址、物理地址的转换与关系。我们先来看一个二进制可执行程序test:段基地址:当test加载运行时,linux使用预先设置好的GDTR和LDTR寄存器,找到对应的段描述符表,已经表项。然后,从断描述符表项(entry)中拿到段基地址。在linux实现中,所有段的基地址都是0,最大偏移为4GB(32bits机器)。段内偏移地址:在上面test汇编代码截图中,黄色的框表示偏移地址,当test被加载运行时..
2020-11-13 13:14:48
1044
原创 hamming weight algorithm(汉明算法)以及kernel的实现
hamming weight(汉明权重)算法是一种用于计算字节串中1bit的数目。比如,0b1001 0000,ob0000 0011, 0b1000 0001的汉明权重均为2,ob 1110 0001, 0b1100 1100, 0b1001 1001的汉明权重均为4.汉明权重的算法(32位):int Hamming_weight(uint32_t n ) { n = (n&0x55555555) + ((n>>1)&0x55555555); ...
2020-11-11 18:06:08
1527
原创 内存barrier
指令乱序和内存障碍(barrier)什么是指令乱序?指令乱序分为执行指令乱序(cpu)和编译器指令乱序。执行指令乱序(cpu)要了解cpu执行指令乱序,我们要先了解cpu的流水线pipeline.cpu处理指令时,将指令的处理过程分为取指、译码、[访存]、执行、[回写]等几个阶段。取指:顾名思义,就是到内存中(I-cache)取要执行的指令译码:cpu识别这个指令是做什么的,比如识别出操作码[op]、操作数等访存:cpu锁定内存的地址执行:执行指令操作,比如A..
2020-11-03 14:13:18
513
原创 linux kernel同步之原子操作
内核同步之原子操作在多线程编程中(无论多核还是单核),对同一内存访问时,如果没有同步机制,那么程序的执行结果和预期结果可能就不一致。比如: 线程1 线程2 read read modify modify write write 线程1和线...
2020-10-29 17:04:55
541
原创 x86下usb驱动framework
本文讲述的USB驱动,是基于X86架构下的PCI-USB总线下的USB设备驱动,侧重函数调用。架构如下:涉及的几个modules:arch/x86/pci/legacy.cdrivers/usb/host/uhci-hcd.cdrivers/usb/core/usb.c其中arch/x86/pci/legacy.c和drivers/usb/core/usb.c使用了subsys_initcall()来申明初始化的函数存放在initcall4这个段,结合makefile可知,drive
2020-09-28 09:28:47
671
1
原创 pci总线扫描及pci网卡驱动
本文讲述的基于intel 总线架构的硬件架构为例来说明linux是如何扫描总线上的PCI设备。CPU通过前端总线FS连接到北桥芯片North Bridge Chip(又称host Bridge), 北桥芯片本身也是PCI总线0上的PCI设备。北桥芯片通过DMI总线连接南桥芯片Sourth Bridge Chip。北桥芯片内置内存控制器,访问内存需要通过北桥芯片; 南桥芯片负责IO操作,以及下挂子pci总线,usb总线等。Linux kernel扫描pci总线从pci总线0开始,即pci0。
2020-09-14 14:59:35
3162
原创 linux kernel编译makefile简要介绍(arm)
本文以ast2500evb板子的linux kernel编译来进行。该板子使用的是arm cpu(1176)编译内核的命令参数为make ARCH=arm CROSS_COMPILE=arm-linux-首先来看顶层目录的Makefile.Linux/Makefile588行定义了make的target为vmlinux,但是,要注意了,我们需要明白make是怎么工作的:make程序首先读取-f参数指定的makefile文件或当前目录下的Makefile或makefile文件,并且递归
2020-09-07 18:04:52
1221
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人