arm系统调用

本文详细探讨了ARM体系结构中系统调用的工作原理,包括用户接口、如何陷入内核、系统调用号的传递方式、如何从汇编跳转到C代码的机制,以及如何添加自定义系统调用。对于理解Linux内核和系统级编程具有重要意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 系统调用用户接口

1 int open(const char *filename, int oflag,mode_t mode);
打开file,方式为oflag("O_RDONLY"即0,"O_WRONLY"即1,"O_RDWR"即2),mode是仅当创建新文件才使用,一般可缺省不要。(返回值:成功fd;失败-1)
2 int close(int file);
关闭一个打开的文件file。(返回值:成功0;失败-1)
3 ssize_t read(int fd,void * buf ,size_t count);
参数fd所指的文件传送count个字节到buf指针所指的内存中。文件读写位置会随读取到的字节移动。(返回值:成功返回实际读到的字节数;失败-1)
4 ssize_t write (int fd,const void * buf,size_t count);
把参数buf所指的内存写入count个字节到参数fd所指的文件内。文件读写位置也会随之移动。(返回值:成功返回实际写入的字节数;失败-1)

 

二 陷入内核

关于x86的陷入方式,一说再说,抄来一段。int $0x80指令的目的是产生一个编号为0x80的编程异常,这个编程异常对应的是中断描述符表IDT中的第128项——也就是对应的系统门描述符。门描述符中含有一个预设的内核空间地址,它指向了系统调用处理程序:system_call()(别和系统调用服务程序混淆,这个程序在entry.S文件中用汇编语言编写)。system_call()检查系统调用号,该号码告诉内核进程请求哪种服务。内核进程查看系统调用表sys_call_table找到所调用的内核函数入口地址。arm也类似,是通过软中断SWI陷入svc模式的。下面分析具体过程,前提是有一份glibc的代码。
io/fcntl.h中有open()的定义,这个open()就是应用程序的open啊。
extern int open (__const char *__file, int __oflag, ...) __nonnull ((1));
intl/loadmsgcat.c中继续找,原来是个宏;
  # define open(name, flags) open_not_cancel_2 (name, flags)
sysdeps/unix/sysv/linux/not-cancel.h
  #define open_not_cancel_2(name, flags) \
  INLINE_SYSCALL (open, 2, (const char *) (name), (flags))
sysdeps/unix/sysv/linux/arm/sysdep.h找到这里看看INLINE_SYSCALL宏是个什么东西。
/* not __ASSEMBLER__ */

/* Define a macro which expands into the inline wrapper code for a system
   call.  */
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...)				\
  ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);	\
     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))	\
       {								\
	 __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));		\
	 _sys_result = (unsigned int) -1;				\
       }								\
     (int) _sys_result; })

#undef INTERNAL_SYSCALL
#define INTERNAL_SYSCALL(name, err, nr, args...)		\
	INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
#undef SYS_ify
#define SYS_ify(syscall_name)	(__NR_##syscall_name)
#if defined(__thumb__)
/* We can not expose the use of r7 to the compiler.  GCC (as
   of 4.5) uses r7 as the hard frame pointer for Thumb - although
   for Thumb-2 it isn't obviously a better choice than r11.
   And GCC does not support asms that conflict with the frame
   pointer.

   This would be easier if syscall numbers never exceeded 255,
   but they do.  For the moment the LOAD_ARGS_7 is sacrificed.
   We can't use push/pop inside the asm because that breaks
   unwinding (i.e. thread cancellation) for this frame.  We can't
   locally save and restore r7, because we do not know if this
   function uses r7 or if it is our caller's r7; if it is our caller's,
   then unwinding will fail higher up the stack.  So we move the
   syscall out of line and provide its own unwind information.  */
# undef INTERNAL_SYSCALL_RAW
# define INTERNAL_SYSCALL_RAW(name, err, nr, args...)		\
  ({								\
      register int _a1 asm ("a1");				\
      int _nametmp = name;					\
      LOAD_ARGS_##nr (args)					\
      register int _name asm ("ip") = _nametmp;			\
      asm volatile ("bl      __libc_do_syscall"			\
                    : "=r" (_a1)				\
                    : "r" (_name) ASM_ARGS_##nr			\
                    : "memory", "lr");				\
      _a1; })
#else /* ARM */
# undef INTERNAL_SYSCALL_RAW
# define INTERNAL_SYSCALL_RAW(name, err, nr, args...)		\
  ({								\
       register int _a1 asm ("r0"), _nr asm ("r7");		\
       LOAD_ARGS_##nr (args)					\
       _nr = name;						\
       asm volatile ("swi	0x0	@ syscall " #name	\
		     : "=r" (_a1)				\
		     : "r" (_nr) ASM_ARGS_##nr			\
		     : "memory");				\
       _a1; })
#endif
#if defined(__thumb__)
/* We can not expose the use of r7 to the compiler.  GCC (as
   of 4.5) uses r7 as the hard frame pointer for Thumb - although
   for Thumb-2 it isn't obviously a better choice than r11.
   And GCC does not support asms that conflict with the frame
   pointer.

   This would be easier if syscall numbers never exceeded 255,
   but they do.  For the moment the LOAD_ARGS_7 is sacrificed.
   We can't use push/pop inside the asm because that breaks
   unwinding (i.e. thread cancellation) for this frame.  We can't
   locally save and restore r7, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值