Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1597123
  • 博文数量: 92
  • 博客积分: 2002
  • 博客等级: 大尉
  • 技术积分: 4717
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-01 17:09
文章分类

全部博文(92)

文章存档

2013年(1)

2012年(6)

2011年(85)

分类: LINUX

2011-05-30 23:35:04

一、汇编语句sc

不同平台的系统调用汇编不一样,powerpc平台通过汇编语句sc来执行系统调用

helloworld的例子(powerpc平台)
  1. /*
  2. /opt/montavista41/montavista/cge/devkit/ppc/85xx/bin/ppc_85xx-as -gstabs hello.s -o hello.o
  3. /opt/montavista41/montavista/cge/devkit/ppc/85xx/bin/ppc_85xx-ld hello.o -o hello
  4. */
  5. .data # section declaration - variables only

  6. msg:
  7. .string "Hello, world!\n"
  8. len = . - msg                 # length of our dear string

  9. .text # section declaration - begin code

  10. .global _start
  11. _start:

  12. # write our string to stdout

  13. li 0,4           # syscall number (sys_write)
  14. li 3,1           # first argument: file descriptor (stdout)
  15. # second argument: pointer to message to write
  16. lis 4,msg@ha     # load top 16 bits of &msg
  17. addi 4,4,msg@l   # load bottom 16 bits
  18. li 5,len         # third argument: message length
  19. sc               # call kernel

  20. # and exit

  21. li 0,1 # syscall number (sys_exit)
  22. li 3,1 # first argument: exit code
  23. sc     # call kernel

helloworld的例子(ia32平台)
  1. .data # section declaration

  2. msg:
  3. .string "Hello, world!\n"
  4. len = . - msg # length of our dear string

  5. .text # section declaration

  6. # we must export the entry point to the ELF linker or
  7. .global _start # loader. They conventionally recognize _start as their
  8. # entry point. Use ld -e foo to override the default.

  9. _start:

  10. # write our string to stdout

  11. movl $len,%edx # third argument: message length
  12. movl $msg,%ecx # second argument: pointer to message to write
  13. movl $1,%ebx   # first argument: file handle (stdout)
  14. movl $4,%eax   # system call number (sys_write)
  15. int $0x80      # call kernel

  16. # and exit

  17. movl $0,%ebx   # first argument: exit code
  18. movl $1,%eax   # system call number (sys_exit)
  19. int $0x80      # call kernel
二、系统调用过程

系统调用本质上是一个中断向量  《中断相关知识(powerpc版)》
 
文件linux_2_6_24/arch/ppc/kernel/head_fsl_booke.S
  1. SET_IVOR(0, CriticalInput);
  2. SET_IVOR(1, MachineCheck);
  3. SET_IVOR(2, DataStorage);
  4. SET_IVOR(3, InstructionStorage);
  5. SET_IVOR(4, ExternalInput);
  6. SET_IVOR(5, Alignment);
  7. SET_IVOR(6, Program);
  8. SET_IVOR(7, FloatingPointUnavailable);
  9. SET_IVOR(8, SystemCall);
  10. SET_IVOR(9, AuxillaryProcessorUnavailable);
  11. SET_IVOR(10, Decrementer);
  12. SET_IVOR(11, FixedIntervalTimer);
  13. SET_IVOR(12, WatchdogTimer);
  14. SET_IVOR(13, DataTLBError);
  15. SET_IVOR(14, InstructionTLBError);
  16. SET_IVOR(15, Debug);
  17. SET_IVOR(32, SPEUnavailable);
  18. SET_IVOR(33, SPEFloatingPointData);
  19. SET_IVOR(34, SPEFloatingPointRound);
  20. #ifndef CONFIG_E200
  21. SET_IVOR(35, PerformanceMonitor);
  22. #endif
  23. 。。。。省略N多。。。。。
  24.     /* System Call Interrupt */
        START_EXCEPTION(SystemCall)
        NORMAL_EXCEPTION_PROLOG
        EXC_XFER_EE_LITE(0x0c00, DoSyscall)

使用汇编语句sc会产生一个SystemCall中断,接着根据中断向量中的地址去执行handler,即DoSyscall。

有关DoSyscall,它在文件arch/ppc/kernel/entry.S 中定义。
它根据sc执行时所用的系统调用编号来检索系统调用表,进行系统调用。
  1. _GLOBAL(DoSyscall)
  2. stw r3,ORIG_GPR3(r1)
  3. li r12,0
  4. stw r12,RESULT(r1)
  5. lwz r11,_CCR(r1) /* Clear SO bit in CR */
  6. rlwinm r11,r11,0,4,2
  7. stw r11,_CCR(r1)
  8. #ifdef SHOW_SYSCALLS
  9. bl do_show_syscall
  10. #endif /* SHOW_SYSCALLS */
  11. rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
  12. lwz r11,TI_FLAGS(r10)
  13. andi. r11,r11,_TIF_SYSCALL_T_OR_A
  14. bne- syscall_dotrace
  15. syscall_dotrace_cont:
  16. cmplwi 0,r0,NR_syscalls
  17. lis r10,sys_call_table@h
  18. ori r10,r10,sys_call_table@l
  19. slwi r0,r0,2
  20. bge- 66f
  21. lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
  22. mtlr r10
  23. addi r9,r1,STACK_FRAME_OVERHEAD
  24. PPC440EP_ERR42
  25. blrl /* Call handler */

系统调用表名为 sys_call_table,在 linux_2_6_24/arch/powerpc/kernel/systbl.S 中定义。
linux_2_6_24/include/asm-powerpc/systbl.h

系统调用表包含有实现每个系统调用的函数的地址。
  1. SYSCALL(restart_syscall)
  2. SYSCALL(exit)
  3. PPC_SYS(fork)
  4. SYSCALL_SPU(read)
  5. SYSCALL_SPU(write)
  6. COMPAT_SYS_SPU(open)
  7. SYSCALL_SPU(close)
  8. COMPAT_SYS_SPU(waitpid)
  9. COMPAT_SYS_SPU(creat)
  10. SYSCALL_SPU(link)
  11. SYSCALL_SPU(unlink)
  12. COMPAT_SYS(execve)
  13. SYSCALL_SPU(chdir)
  14. COMPAT_SYS_SPU(time)
  15. SYSCALL_SPU(mknod)
  16. SYSCALL_SPU(chmod)
当DoSyscall 找到正确的系统调用地址后,它把调用指定的系统调用函数。如要做系统ioctl调用,对应的系统调用号为54,它把调用函数sys_ioctl()。

当函数调用完毕之后,返回到 DoSyscall(),它把控制权切换给 ret_from_except(在 arch/ppc/kernel/entry.S 中定义)。
它会去检查那些在切换回用户空间之前需要完成的任务。如果没有需要做的事情,那么就通过 restore 函数恢复用户进程的状态,并把控制权交还给用户程序。
阅读(15289) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~