首页 > 系统相关 >linux 系统调用分析

linux 系统调用分析

时间:2024-04-30 10:33:06浏览次数:25  
标签:__ 调用 SYSCALL openat 系统 oflag mode linux INLINE

一、linux系统调用介绍

linux系统调用是linux为用户空间与内核空间交换提供的一组标准API,这些api能够让用户态进程访问内核代码,从而实现系统资源、硬件、文件读写的访问。需要注意的是,系统调用是用户态进入内核态的唯一入口,为了保证linux内核运行的稳定性,用户程序不能随意的访问内核,必须是经过校验、满足访问权限的程序才能调用相应的系统调用。 linux系统调用又被称为syscall,是通过中断方式实现,在arm平台上通过swi软中断实现系统调用。Linux系统调用主要分为以下几类: 1、文件操作:例如open、read、write、close等,用于对文件进行读写和其他操作。 2、进程管理:例如fork、exec、wait等,用于创建新进程、执行新程序、等待子进程结束等。 3、信号处理:例如kill、signal、sigaction等,用于发送信号、处理信号等。 4、网络通信:例如socket、bind、listen、accept、connect、send、recv等,用于创建套接字、绑定地址、监听连接、建立连接、发送和接收数据等。 5、系统信息获取:例如getpid、getppid、getuid、getgid等,用于获取当前进程ID、父进程ID、用户ID、组ID等信息。 6、时间操作:例如time、sleep等,用于获取当前时间、延迟进程执行等。其他操作:例如chmod、chown、mkdir、rmdir等,用于改变文件权限、改变文件所有者、创建目录、删除目录等。 7、Linux系统调用是应用程序与内核之间的关键接口,它们使得应用程序能够利用操作系统的底层功能和服务,实现各种复杂的操作。对于Linux程序员来说,了解和熟悉系统调用的使用方法和机制是非常重要的。

二、linux系统调用流程(基于kernel-5.10)

当用户态执行系统调用时,会根据用户的操作,例如open转化为宏__NR_openat(注意最新glibc的open底层是由openat实现),然后在glibc中的linux/arm/arch-syscall.h找到对应的系统调用号,然后将系统调用号填入系统调用寄存器R7中,然后调用系统软中断swi,陷入内核态,然后在根据内核中断异常表(内核编译时读取arch/arm/tools/syscall.tbl生成的arch/arm/include/generated/calls-oabi.S or calls-eabi.S),调用相应的内核api接口sys_open。 下面是open函数从用户态到内核态的详细调用流程(基于glibc-2.34):

1、step1 

open->
 weak_alias (__libc_open, open)-> //open函数的别名为__libc_open
  __libc_open->
   SYSCALL_CANCEL (openat, AT_FDCWD, file, oflag, mode)->
    INLINE_SYSCALL_CALL (__VA_ARGS__)

2、step2 展开宏INLINE_SYSCALL_CALL

INLINE_SYSCALL_CALL (__VA_ARGS__)->
 INLINE_SYSCALL_CALL(openat, AT_FDCWD, file, oflag, mode)->

#define INLINE_SYSCALL_CALL(...) \
  __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)

3、step3 展开宏__INLINE_SYSCALL_DISP

INLINE_SYSCALL_CALL(openat, AT_FDCWD, file, oflag, mode)->
 __INLINE_SYSCALL_DISP (__INLINE_SYSCALL,openat, AT_FDCWD, file, oflag, mode)

#define __INLINE_SYSCALL_DISP(b,...) \
  __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)

4、step4展开宏__SYSCALL_CONCAT

__INLINE_SYSCALL_DISP (__INLINE_SYSCALL,openat, AT_FDCWD, file, oflag, mode)->
  __SYSCALL_CONCAT(__INLINE_SYSCALL,__INLINE_SYSCALL_NARGS(openat, AT_FDCWD, file, oflag, mode))(openat, AT_FDCWD, file, oflag, mode)->
    __SYSCALL_CONCAT(__INLINE_SYSCALL,__INLINE_SYSCALL_NARGS_X (openat, AT_FDCWD, file, oflag, mode,7,6,5,4,3,2,1,0,))(openat, AT_FDCWD, file, oflag, mode)->
      __SYSCALL_CONCAT(__INLINE_SYSCALL,4)(openat, AT_FDCWD, file, oflag, mode)->
         __SYSCALL_CONCAT_X (__INLINE_SYSCALL,4)(openat, AT_FDCWD, file, oflag, mode) 
 
#define __INLINE_SYSCALL_NARGS(...) \
  __INLINE_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
#define __INLINE_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X (a, b)

5、step5展开宏__SYSCALL_CONCAT_X

__SYSCALL_CONCAT_X (__INLINE_SYSCALL,4)(openat, AT_FDCWD, file, oflag, mode) -> 
  __INLINE_SYSCALL4(openat, AT_FDCWD, file, oflag, mode)

#define __INLINE_SYSCALL4(name, a1, a2, a3, a4) INLINE_SYSCALL (name, 4, a1, a2, a3, a4)

6、step6展开宏__INLINE_SYSCALL4

__INLINE_SYSCALL4(openat, AT_FDCWD, file, oflag, mode)->
  INLINE_SYSCALL (openat, 4 , AT_FDCWD, file, oflag, mode)

#define INLINE_SYSCALL(name, nr, args...)                \
  ({                                    \
    long int sc_ret = INTERNAL_SYSCALL (name, nr, args);        \
    __glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (sc_ret))        \
    ? SYSCALL_ERROR_LABEL (INTERNAL_SYSCALL_ERRNO (sc_ret))        \
    : sc_ret;                                \
  })

7、step7展开宏INLINE_SYSCALL到这里就与CPU架构相关了,以arm为例)

INLINE_SYSCALL (openat, 4 , AT_FDCWD, file, oflag, mode)->
  INTERNAL_SYSCALL (openat, 4, AT_FDCWD, file, oflag, mode)
  
#define INTERNAL_SYSCALL(name, nr, args...)            \
    INTERNAL_SYSCALL_RAW(SYS_ify(name), nr, args)

8、step8展开宏INTERNAL_SYSCALL

INTERNAL_SYSCALL (openat, 4, AT_FDCWD, file, oflag, mode)->
  INTERNAL_SYSCALL_RAW(SYS_ify(openat), 4, AT_FDCWD, file, oflag, mode)
 
#define SYS_ify(syscall_name)    (__NR_##syscall_name)

9、step9展开宏SYS_ify

INTERNAL_SYSCALL_RAW(SYS_ify(openat), 4, AT_FDCWD, file, oflag, mode)->
 INTERNAL_SYSCALL_RAW(__NR_openat,4, AT_FDCWD, file, oflag, mode)

10、step10 宏展开完毕,进入汇编

define INTERNAL_SYSCALL_RAW(name, 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; })

INTERNAL_SYSCALL_RAW(__NR_openat,4, AT_FDCWD, file, oflag, mode)
------->
{
    register int _a1 asm ("r0"), _nr asm ("r7");
    LOAD_ARGS_##nr (args) //展开args,然后设置到相应的寄存器中
    _nr = name;
    //执行swi软中断,根据系统调用号,执行对应的内核函数
    asm volatile ("swi    0x0    @ syscall " #name    \                  
               :     "=r" (_a1)                \
                 : "r" (_nr) ASM_ARGS_##nr            \
                 : "memory");                \
    _a1; 
} 

11、step11  中断编号查找

__NR_openat的系统调用号,可以在glibc-2.34源码sysdeps/unix/sysv/linux/arm/arch-syscall.h找到

 系统调用号在内核的调用函数,可以在arch/arm/tools/syscall.tbl中找到

标签:__,调用,SYSCALL,openat,系统,oflag,mode,linux,INLINE
From: https://www.cnblogs.com/linux-dafei/p/18167396

相关文章

  • Linux Bridge和Tap关系详解
    本文分享自天翼云开发者社区《Linux Bridge和Tap关系详解》,作者:x****nLinux Bridge介绍Bridge(桥)是Linux上用来做TCP/IP二层协议交换的设备,与现实世界中的交换机功能相似。Bridge设备实例可以和Linux上其他网络设备实例连接,既attach一个从设备,类似于在现实世界中的交换机和一......
  • 测试新人,如何快速上手一个陌生的系统!
    大家好,我是狂师!作为刚不行不久的测试新人,面对一个陌生的系统时,可能会感到有些手足无措。面对一个全新的系统系统,如何快速上手并展开有效的测试工作是一个重要的挑战。本文将探讨测试新人如何通过一系列步骤和策略,快速熟悉并掌握新系统的测试要点,从而提高测试效率和质量。本文旨......
  • Linux基础——主机域名解析默认使用IPV6路由
    一、问题描述主机访问内网存储网段,发现域名默认解析的IPV6地址。ping访问ipv4地址正常通讯。主机本地解析/etc/resolv.conf的DNS配置正常。#ping域名默认解析IPV6地址Pingnasgroup.xxxx.xxxx.com#pingipv4地址正常ping-4nasgroup.xxxx.xxxx.com#查看本地DNS配......
  • m基于Yolov2深度学习网络的智能零售柜商品识别系统matlab仿真,带GUI界面
    1.算法仿真效果matlab2022a仿真结果如下:  2.算法涉及理论知识概要       YOLO(YouOnlyLookOnce)是一种实时的目标检测算法,YOLOv2则是其改进版本,由JosephRedmon和AliFarhadi于2016年提出。YOLOv2采用了端到端的方式直接从整幅图像预测边界框和类别概率,极大......
  • 在Linux中,如何使用vmstat和iostat命令?
    在Linux中,vmstat和iostat是两个非常有用的命令行工具,用于监控系统的性能,尤其是CPU使用率、内存使用情况、磁盘I/O以及进程状态。下面分别详细介绍这两个命令的使用方法。1.vmstat命令格式:vmstat[选项][时间间隔][次数]常用选项:不带选项时,vmstat默认显示自从系统......
  • linux遇到的问题
    1:红帽8添加另外一种类型的磁盘时,会遇到重装系统的问题原因:系统扫描硬盘的先后顺序不一样,所导致的如果添加的是同一种类型的磁盘的话,就不会出现重装系统的问题了如果添加其他的类型的磁盘的话,要进入到bios里面修改磁盘的优先级解决方法:1)先进入到bios里面2)找到boot选项卡,ha......
  • 在Linux中,如何监控系统资源使用情况?
    在Linux中,监控系统资源使用情况对于系统管理员来说是一项重要的任务,它有助于确保系统性能和及时发现潜在的瓶颈。以下是一些常用的命令和工具,用于监控不同类型的系统资源:1.CPU使用情况top:实时显示系统中各个进程对CPU资源的使用状况。tophtop:top的增强版本,提供了彩色界......
  • 在Linux中,如何在Linux中查看当前路径?
    在Linux中,查看当前工作目录(即你当前所在的目录)可以通过几种不同的命令实现。以下是一些常用的方法:1.使用pwd命令pwd(PrintWorkingDirectory)命令用于显示当前工作目录的完整路径。pwd2.使用echo命令echo命令可以输出环境变量的值,其中$PWD环境变量包含了当前工作目......
  • 在Linux中,如何监控磁盘I/O性能?
    在Linux中,可以使用iotop和iostat命令来监控磁盘的I/O性能。以下是如何使用这两个工具以及它们各自的特点:使用iotop命令:iotop是一个实时显示系统磁盘活动的工具,类似于top命令,但专注于I/O活动。它能够展示每个进程或线程的实时I/O使用情况,包括读写带宽,以及等待I/O操作所花费的时......
  • 在Linux中,如何使用top和htop命令?
    在Linux中,top和htop是两个用于实时监控系统资源使用情况的命令行工具,尤其是CPU、内存以及进程信息。下面详细介绍这两个命令的使用方法:1.top命令启动:打开终端,输入top命令并回车。这将立即显示一个实时更新的系统资源使用概览。界面解读:屏幕顶部显示了系统运行时间......