Linux I/O操作基础知识(韦东山《嵌入式linux应用开发完全手册》学习笔记)

1.系统调用函数怎么进入内核?

app层的open函数调用glibc层的weak_alias (__libc_open, open)。

`weak_alias (__libc_open, open)` 是 GNU C Library (glibc) 中常用的宏,用来创建函数的弱符号别名。它的主要作用是将一个函数名(比如 `__libc_open`)定义为另一个函数名(比如 `open`)的别名,并且这个别名是“弱的”,意味着它可以被其他强符号所覆盖。

 weak_alias (__libc_open, open)具体作用与用途

1. 符号别名:
   - `weak_alias (__libc_open, open)` 这行代码会创建一个 `open` 函数的符号别名,指向 `__libc_open` 函数。这意味着,如果链接时没有其他 `open` 函数的定义,那么 `open` 就会解析为 `__libc_open`。
   
2. 弱符号:
   - "弱符号"(weak symbol)意味着它的定义优先级较低。如果程序中或链接时有其他地方定义了一个名为 `open` 的强符号(strong symbol),那个强符号会覆盖 `weak_alias` 创建的 `open`。因此,`__libc_open` 作为 `open` 的实现只在没有其他定义时才会被使用。
   
3. 灵活性与可扩展性:
   - 通过使用弱符号别名,glibc 提供了灵活性和可扩展性。例如,如果用户在程序中自己定义了一个 `open` 函数,系统会自动使用用户定义的版本,而不会冲突或重定义。这种机制可以在需要对库中的某些行为进行重写或自定义时,提供一个默认实现,并允许用户或其他库覆盖默认实现。

应用场景

- 内部实现和兼容性:
  - 在库内部,glibc 可能有一个低级实现函数(比如 `__libc_open`),并将它作为默认的 `open` 实现。当用户程序需要使用 `open` 函数时,默认会调用 `__libc_open`,但用户也可以提供自己的 `open` 实现。

- API 的平滑迁移:
  - 在某些情况下,库的 API 可能会更新或改变,但旧的符号仍然需要支持。通过使用弱别名,可以在不破坏旧有代码的情况下,提供新的实现并允许旧代码继续工作。

总结

`weak_alias (__libc_open, open)` 创建了一个 `open` 函数的弱符号,指向 `__libc_open` 函数。它的作用是为 `open` 提供一个默认的实现,除非在链接时有另一个强符号定义 `open`,否则会使用这个弱符号。这样做可以增加代码的灵活性,允许库或应用程序在需要时覆盖默认实现

之后根据不同平台对应不同的汇编指令,对于ARM64来说, 汇编语句就是:

move R8,#__NR_open SVC_0

这段代码是汇编语言中的指令,通常用于在 Linux 内核或嵌入式系统中进行系统调用(syscall)。让我们逐个拆解这些部分:

move R8, #__NR_open

  • move: 这是一条汇编指令,用于将一个值(通常是立即数、寄存器值或内存地址)存入一个寄存器中。

  • R8: 这是 ARM 处理器中的一个寄存器。R8 是通用寄存器之一,用于存储临时数据。

  • #__NR_open: 这是一个立即数,它代表系统调用号 open。系统调用号是一个唯一的数字,用于标识特定的系统调用(例如,文件打开、关闭、读写等)。在汇编代码中,这通常是由内核头文件定义的一个宏。

    move R8, #__NR_open 的含义是将 __NR_open 的值加载到寄存器 R8 中。这是为后续执行系统调用做准备。

SVC 0

  • SVC: 这是一条指令,用于触发超级用户调用(Supervisor Call),也称为系统调用。在 ARM 架构中,SVC 指令会触发一个异常,进入内核模式,从而执行指定的系统调用。
  • 0: SVC 指令可以带一个立即数参数,用来标识调用的类型或处理的方式。在许多情况下,0 只是一个占位符,因为调用的具体内容已经由之前的寄存器值指定。

SVC 0 的作用是告诉处理器执行系统调用,处理器会转入内核模式,内核根据寄存器中的系统调用号(如 R8 中的 __NR_open)来执行相应的系统调用。

总结

  • 这段代码的整体作用是:首先将系统调用号 open(用于打开文件的系统调用)存入寄存器 R8,然后通过 SVC 0 指令发起系统调用,执行文件打开操作。

这在嵌入式系统或直接与操作系统交互的低级代码中非常常见。

对于ARM64来说,在内核层,其会从R8中取出__NR_open,

得到参数值__NR_open或者__NR_read之后,通过sys_call_table[__NR_open]或者sys_call_table[__NR_read]调用对应的内核态函数接口。sys_call_table[]是一个有内核态函数指针组成的数组,通过下标可以直接找到对应的函数进行调用。

最后调用的 sys_call_table 的函数指针数组如下:

调用了sys_open后,sys_read/open 会首先根据参数判断文件的类型,然后根据不同的文件类型去找不同的设备驱动,继而进行读写或者输入输出控制。

2.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值