历史上的今天
返回首页

历史上的今天

今天是:2025年02月16日(星期日)

正在发生

2020年02月16日 | 浅析基于ARM的Linux下的系统调用的实现

2020-02-16 来源:eefocus

在Linux下系统调用是用软中断实现的,下面以一个简单的open例子简要分析一下应用层的open是如何调用到内核中的sys_open的。


t8.c


   1:  #include

   2:  #include

   3:  #include

   4:  #include

   5:   

   6:  int main(int argc, const char *argv[])

   7:  {

   8:      int fd;

   9:   

  10:      fd = open(".", O_RDWR);

  11:   

  12:      close(fd);

  13:      return 0;

  14:  }


这里需要注意的是:open是C库提供的库函数,并不是系统调用,系统调用时在内核空间的,应用空间无法直接调用。在《Linux内核设计与实现》中说:要访问系统调用(在Linux中常称作syscall),通常通过C库中定义的函数调用来进行。


将t8.c进行静态编译,然后反汇编,看一下是如何调用open的?


   1:  arm-linux-gcc t8.c --static

   2:  arm-linux-objdump -D a.out >a.dis


下面我们截取a.dis中的一部分进行说明:


   1:  ......

   2:  00008228

:

   3:      8228:   e92d4800    push    {fp, lr}

   4:      822c:   e28db004    add fp, sp, #4  ; 0x4

   5:      8230:   e24dd010    sub sp, sp, #16 ; 0x10

   6:      8234:   e50b0010    str r0, [fp, #-16]

   7:      8238:   e50b1014    str r1, [fp, #-20]

   8:      823c:   e59f0028    ldr r0, [pc, #40]   ; 826c

   9:      8240:   e3a01002    mov r1, #2  ; 0x2   ;  #define  O_RDWR  00000002 

  10:      8244:   eb002e7d    bl  13c40 <__libc_open>

  11:      8248:   e1a03000    mov r3, r0

  12:      824c:   e50b3008    str r3, [fp, #-8]

  13:      8250:   e51b0008    ldr r0, [fp, #-8]

  14:      8254:   eb002e9d    bl  13cd0 <__libc_close>

  15:      8258:   e3a03000    mov r3, #0  ; 0x0

  16:      825c:   e1a00003    mov r0, r3

  17:      8260:   e24bd004    sub sp, fp, #4  ; 0x4

  18:      8264:   e8bd4800    pop {fp, lr}

  19:      8268:   e12fff1e    bx  lr

  20:      826c:   00064b8c    .word   0x00064b8c

  21:  ......

  22:  00013c40 <__libc_open>:

  23:     13c40:   e51fc028    ldr ip, [pc, #-40]  ; 13c20 <___fxstat64+0x50>

  24:     13c44:   e79fc00c    ldr ip, [pc, ip]

  25:     13c48:   e33c0000    teq ip, #0  ; 0x0

  26:     13c4c:   1a000006    bne 13c6c <__libc_open+0x2c>

  27:     13c50:   e1a0c007    mov ip, r7

  28:     13c54:   e3a07005    mov r7, #5  ; 0x5   

  #在arch/arm/include/asm/unistd.h中:#define __NR_open  (__NR_SYSCALL_BASE+5)

                    其中,__NR_OABI_SYSCALL_BASE是0

  29:     

13c58: ef000000 svc 0x00000000 #产生软中断

  30:     13c5c:   e1a0700c    mov r7, ip

  31:     13c60:   e3700a01    cmn r0, #4096   ; 0x1000

  32:     13c64:   312fff1e    bxcc    lr

  33:     13c68:   ea0008d4    b   15fc0 <__syscall_error>

  34:  ......


通过上面的代码注释,可以看到,系统调用sys_open的系统调用号是5,将系统调用号存放到寄存器R7当中,然后应用程序通过svc 0x00000000产生软中断,陷入内核空间。


也许会好奇,ARM软中断不是用SWI吗,这里怎么变成了SVC了,请看下面一段话,是从ARM官网copy的:


SVC


超级用户调用。 

语法


SVC{cond} #immed


其中:


cond


    是一个可选的条件代码(请参阅条件执行)。 

immed


    是一个表达式,其取值为以下范围内的一个整数:


        在 ARM 指令中为 0 到 224–1(24 位值)


        在 16 位 Thumb 指令中为 0-255(8 位值)。


用法


SVC 指令会引发一个异常。 这意味着处理器模式会更改为超级用户模式,CPSR 会保存到超级用户模式 SPSR,并且执行会跳转到 SVC 向量(请参阅《开发指南》中的第 6 章 处理处理器异常)。


处理器会忽略 immed。 但异常处理程序会获取它,借以确定所请求的服务。 

Note


作为 ARM 汇编语言开发成果的一部分,SWI 指令已重命名为 SVC。 在此版本的 RVCT 中,SWI 指令反汇编为 SVC,并提供注释以指明这是以前的 SWI。 

条件标记


此指令不更改标记。 

体系结构


此 ARM 指令可用于所有版本的 ARM 体系结构。


在基于ARM的Linux中,异常向量表已经被放置在了0xFFFF0000这个位置。这个过程的完成:


start_kernel ---> setup_arch ---> early_trap_init


   1:  void __init early_trap_init(void)

   2:  {

   3:      unsigned long vectors = CONFIG_VECTORS_BASE;  // 就是0xFFFF0000

   4:      extern char __stubs_start[], __stubs_end[];

   5:      extern char __vectors_start[], __vectors_end[];

   6:      extern char __kuser_helper_start[], __kuser_helper_end[];

   7:      int kuser_sz = __kuser_helper_end - __kuser_helper_start;

   8:   

   9:      /*

  10:       * Copy the vectors, stubs and kuser helpers (in entry-armv.S)

  11:       * into the vector page, mapped at 0xffff0000, and ensure these

  12:       * are visible to the instruction stream.

  13:       */

  14:      memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);

  15:      memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);

  16:      memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);

  17:   

  18:      /*

  19:       * Copy signal return handlers into the vector page, and

  20:       * set sigreturn to be a pointer to these.

  21:       */

  22:      memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,

  23:             sizeof(sigreturn_codes));

  24:   

  25:      flush_icache_range(vectors, vectors + PAGE_SIZE);

  26:      modify_domain(DOMAIN_USER, DOMAIN_CLIENT);

  27:  }

关于上面这个函数的详细解释,参见:


http://www.cnblogs.com/pengdonglin137/p/3603549.html


把异常中断向量表的位置设置为0xffff0000的话,需要修改协处理器CP15的寄存器C1的第13位,将其设置为1。以Tq2440的提供的内核2.6.30.4为例看一下:


 arch/arm/kernel/head.S


   1:      adr    lr, __enable_mmu        @ return (PIC) address

   2:      add    pc, r10, #PROCINFO_INITFUNC

其中,PROCINFO_INITFUNC的值是16,r10的值是__arm920_proc_info的地址:


   1:  __arm920_proc_info:

   2:      .long    0x41009200

   3:      .long    0xff00fff0

   4:      .long   PMD_TYPE_SECT |

   5:          PMD_SECT_BUFFERABLE |

   6:          PMD_SECT_CACHEABLE |

   7:          PMD_BIT4 |

   8:          PMD_SECT_AP_WRITE |

   9:          PMD_SECT_AP_READ

  10:      .long   PMD_TYPE_SECT |

  11:          PMD_BIT4 |

  12:          PMD_SECT_AP_WRITE |

  13:          PMD_SECT_AP_READ

  14:      b    __arm920_setup

  15:      .long    cpu_arch_name

  16:      .long    cpu_elf_name

  17:       ......

  18:      .size    __arm920_proc_info, . - __arm920_proc_info

看一下__arm920_setup的实现(proc-arm920.S (archarmmm)):


   1:      .type    __arm920_setup, #function

   2:  __arm920_setup:

   3:      mov    r0, #0

   4:      mcr    p15, 0, r0, c7, c7        @ invalidate I,D caches on v4

   5:      mcr    p15, 0, r0, c7, c10, 4        @ drain write buffer on v4

   6:  #ifdef CONFIG_MMU

   7:      mcr    p15, 0, r0, c8, c7        @ invalidate I,D TLBs on v4

   8:  #endif

   9:      adr    r5, arm920_crval

  10:      ldmia    r5, {r5, r6}            @ 参看以下下面的arm920_crval的实现,本句话执行完后r5和r6分别为:0x3f3f和0x3135

  11:      mrc    p15, 0, r0, c1, c0        @ get control register v4   获取协处理器p15的寄存器才c1

  12:      

bic r0, r0, r5

  13:      

orr r0, r0, r6 @ 我们只关注第13位,这里将r0的第13位设置为了1

  14:      

mov pc, lr

  15:      .size    __arm920_setup, . - __arm920_setup

  16:   

  17:      /*

  18:       *  R

  19:       * .RVI ZFRS BLDP WCAM

  20:       * ..11 0001 ..11 0101

  21:       * 

  22:       */

  23:      .type    arm920_crval, #object

  24:  arm920_crval:

推荐阅读

史海拾趣

BESTECH公司的发展小趣事

由于“BESTECH”并非一个我所熟知的特定电子行业公司,因此我无法提供关于该公司具体发展故事的详细信息。此外,每个公司的发展都涉及到许多复杂的事件和因素,包括市场变化、技术革新、竞争态势、管理决策等,因此,撰写五个关于该公司发展的故事将需要详尽的研究和深入了解。

不过,我可以为您提供一个电子行业公司可能经历的一般性发展故事的框架,您可以根据这个框架来进一步了解或研究“BESTECH”或其他电子行业公司的发展历程。

电子行业公司一般性发展故事框架

  1. 创业初期与技术创新
    • 描述公司创始人的背景和对电子行业的热情。
    • 讲述公司如何从一个创业想法开始,通过技术创新解决某个行业痛点或满足市场需求。
    • 强调早期产品的独特性和市场接受度。
  2. 市场扩张与品牌建设
    • 描述公司如何逐渐扩大市场份额,可能包括进入新的地域市场或拓展产品线。
    • 讲述公司在品牌建设方面的努力和成果,如参加行业展会、获得奖项等。
    • 分析公司在市场竞争中的优势和策略。
  3. 技术升级与研发投入
    • 强调公司如何紧跟行业技术发展趋势,不断升级产品和技术。
    • 描述公司在研发方面的投入和取得的成果,如专利申请、新产品发布等。
    • 分析技术升级对公司市场竞争力的影响。
  4. 合作与战略联盟
    • 讲述公司如何与其他企业、研究机构或高校建立合作关系,共同推进技术创新和市场拓展。
    • 分析这些合作对公司发展的战略意义和价值。
    • 描述合作带来的具体成果和效益。
  5. 企业文化与社会责任
    • 强调公司在企业文化建设方面的努力和特色,如员工培训、激励机制等。
    • 讲述公司如何履行社会责任,如环保措施、公益活动等。
    • 分析企业文化和社会责任对公司长远发展的重要性。

请注意,这只是一个框架性的描述,具体的故事内容需要根据“BESTECH”或其他电子行业公司的实际情况来填充。如果您对“BESTECH”有特定的了解或需求,建议您查阅相关资料、公司年报或行业报告,以获取更准确和详细的信息。

Beck IPC GmbH公司的发展小趣事

Beck IPC深知人才是企业发展的根本。因此,公司高度重视人才培养和引进工作。通过提供良好的工作环境和福利待遇,吸引了一批批优秀的研发、销售和管理人才加入公司。同时,公司还注重企业文化建设,倡导创新、协作、务实、高效的企业精神。这种积极向上的企业文化为公司的持续发展提供了强大的精神动力。

以上五个故事虽然是虚构的,但它们基于Beck IPC在电子行业可能的发展路径和策略。实际的发展过程中,Beck IPC可能经历了更多的挑战和机遇,但无论如何,其始终坚持技术创新和市场导向的发展战略,为其在电子行业中的崛起奠定了坚实的基础。

DeLorme公司的发展小趣事

近年来,随着智能手机和移动互联网技术的快速发展,传统的GPS导航设备市场受到了巨大冲击。面对这一行业变革,DeLorme公司及时调整战略方向,将重心转向智能导航应用软件的开发和推广。他们通过与智能手机厂商的合作,将自己的导航软件集成到手机系统中,为用户提供更加便捷、高效的导航服务。同时,他们还积极探索新的商业模式和市场机会,为公司的未来发展奠定了坚实基础。

Frequency Sources公司的发展小趣事

面对日益严峻的环境问题和不断变化的市场需求,Frequency Sources公司积极响应国家环保政策和可持续发展战略,致力于研发绿色、环保、高效的频率源产品。同时,公司还继续加大在技术创新方面的投入力度,不断推出具有自主知识产权的新产品和新技术。这种可持续发展的理念和技术创新的精神使得公司在激烈的市场竞争中始终保持领先地位并实现了持续健康的发展。

需要注意的是,以上故事是基于电子行业的一般情况和频率源技术的特点来构建的虚构故事,并不直接对应任何具体公司的实际情况。在实际应用中,请根据具体公司的历史和发展情况进行调整和修改。

Global Power Technology Co., Ltd公司的发展小趣事
首先尝试断电重启冰箱看是否能解决问题;若问题依旧存在,需查阅冰箱说明书或联系售后服务了解错误代码的含义并采取相应的解决措施。
Hayashi Denko Co Ltd公司的发展小趣事
冰箱噪音大可能是由于压缩机运转声音、风扇转动声音或冰箱摆放不平稳等原因造成的。首先检查冰箱是否摆放平稳,如不平稳需调整冰箱底部螺丝使其平稳;若冰箱摆放平稳但噪音仍大,可能是压缩机或风扇故障,需联系专业维修人员检查并维修。

问答坊 | AI 解惑

D:\WINCE600\PUBLIC\DIRECTX\SDK\SAMPLES\DSHOW\FILTERS\BALL 范例如何编译,如何使用?

D:\\WINCE600\\PUBLIC\\DIRECTX\\SDK\\SAMPLES\\DSHOW\\FILTERS\\BALL目录下的范例如何编译,如何使用,编译出来的文件放在什么地方,什么形式(exe, lib) ?…

查看全部问答>

求sim300网络测试软件

跪求sim300服务器端的测试软件!!!!!! 可以接受sim300的连接请求,接收gprs发送过来的数据。。。…

查看全部问答>

wince 桌面字体修改

大家好! 请问: wince stand Shell桌面界面里中间较大的黑体字\" windows CE \"的字体大小该如何修改?? 我的是240*320TFT,现在只能显示windows,头和尾都没了,郁闷!! 谢谢!!…

查看全部问答>

求红外遥控资料

我的目的: 想知道常用红外遥控器(电视、空调、手机、特别是那种万能遥控器)的,原理(最好有所用芯片型号、电路图资料); 及编码方法(编码应该是通用的吧,我的遥控器控制另一台空调只要设置下型号码就行); 用单片机加红外接收器识别这些 ...…

查看全部问答>

关于IoCreateDevice的问题

我用IoCreateDevice来创建一个FILE_DEVICE_CD_ROM类型的设备,在2K下可以在我的电脑中 找到,但是当我在XP上的时候,却发现没有了反应.查看MSDN上面有这样一句话: Device objects for disks, tapes, CD-ROMs, and RAM disks are given a Volume Para ...…

查看全部问答>

移植uClibc库

现在2.4.27的内核和RAMDISK可以正常运行在AT91RM9200中,我交叉编译了一个简单测试程序 放到RAMDISK中,但是执行时却提示: Not Found ! eg: ash> ./bin/Test ash> ./bin/Test : Not Found 路径是没问题的,属性也具有可执行.原因可能是我动态 ...…

查看全部问答>

Bootloader 的结构

    在移植之前先了解Bootloader 的一些通用概念,对理解它的代码会有所帮助。    嵌入式Linux 系统从软件的角度通常可以分为以下4 个层次。   (1)引导加载程序,包括固化在固件(firmware)中的boot 代 ...…

查看全部问答>

【转】IE9未来如何?微软IE高管提前爆料

最近看到一篇科技网站采访到微软IE程序经理John Hrvatin的新闻。John是IE开发部门的高层人物,从他的口中得到了一些关于IE 9的最新消息:提问1:IE 9测试版的累积下载量已经超过1300万次,这是微软历史上最大的一次测试。从这次测试中,开发小组获 ...…

查看全部问答>

只想用定时计数PWM功能的时候,用汇编可行吗?

对它的高速度PWM感兴趣,如果不写复杂的算法和人机界面,单纯用汇编语言可行吗?哪些开发工具最简单易用?  我的意思是既然STM32那么便宜,功能强大速度快,干脆大大小小的项目都用这个,省得好多种单片机感觉很累。…

查看全部问答>

求:可以抑制汽车大灯强光的DSP视频处理的PCBA板

谁能提供可以抑制汽车大灯强光的DSP视频处理的PCBA板,联系人:邓先生,18820397668…

查看全部问答>