当前位置: 首页 > news >正文

【操作系统】 Linux 系统调用(一)

目录

  • 一、系统调用
    • 1. 系统调用的工作机制
    • 2. 系统调用的分类
    • 3. 系统调用的实现
    • 4. 常见的系统调用示例
    • 5. 小结

一、系统调用

系统调用(System Call)是操作系统提供给用户程序的一组接口,用于执行需要内核权限的操作。这些操作通常涉及到硬件资源的访问或管理,例如文件I/O、进程控制、内存管理等。以下是对系统调用的详细解释,包括其工作机制、分类、实现方式及常见示例。

1. 系统调用的工作机制

  • 用户模式与内核模式

    • 用户模式:用户程序运行在此模式下,受到严格的权限限制,不能直接访问硬件或执行特权指令。
    • 内核模式:操作系统核心代码运行在此模式下,拥有完全的硬件访问权限和执行特权指令的能力。
  • 触发系统调用
    用户程序通过特定的编程接口(如C语言中的标准库函数)发起系统调用请求。常见的触发方式包括使用特定的系统调用指令(如x86架构下的 int 0x80syscall 指令)。

  • 参数传递
    系统调用所需的参数可以通过寄存器或栈传递。不同的操作系统和体系结构可能有不同的约定。例如,在Linux x86_64架构中,前6个参数通过寄存器传递(RDI, RSI, RDX, RCX, R8, R9),更多的参数则通过栈传递。

  • 模式切换
    当触发系统调用时,处理器会从用户模式切换到内核模式。这一步骤确保了安全性和稳定性,防止用户程序直接访问或修改关键系统资源。

  • 执行系统调用处理程序
    内核接收到系统调用请求后,根据系统调用号(每个系统调用都有一个唯一的编号)找到对应的处理程序并执行。

  • 返回结果
    执行完毕后,内核将结果返回给用户程序,并从内核模式切换回用户模式。

2. 系统调用的分类

系统调用可以根据其功能分为几大类:

  • 进程控制

    • 创建新进程(fork(), vfork()
    • 加载和执行新程序(exec()系列函数)
    • 终止进程(exit()
  • 文件管理

    • 文件打开、关闭(open(), close())
    • 文件读写(read(), write())
    • 文件定位(lseek())
    • 文件信息获取(stat()
  • 设备管理

    • 设备打开、关闭
    • 设备读写
  • 内存管理

    • 动态内存分配(malloc(), free() 背后的系统调用)
    • 内存映射(mmap()
  • 网络通信

    • 创建套接字(socket())
    • 连接到服务器(connect())
    • 发送/接收数据(send(), recv()
  • 信号类

    • signal/sigaction/kill

3. 系统调用的实现

  • 系统调用表
    Linux内核维护了一个系统调用表(sys_call_table),其中包含了所有可用系统调用的地址。每个系统调用都有一个唯一的编号(系统调用号),这个编号用于在系统调用表中查找对应的处理程序。

    • 定义:Linux内核中存储所有系统调用函数指针的数组。
    • 作用:当用户程序调用系统调用时,内核通过这个表找到对应的处理函数。
    • 位置:位于内核内存空间,通过 /proc/kallsyms 可以查看其地址。
      • /proc/kallsyms 文件内容:包含内核中所有符号的地址和名称。
      • 格式:地址 类型 符号名 [模块名]。
      • 权限:通常需要root权限才能查看完整信息。
      • 查看系统调用表:
        cat /proc/kallsyms | grep sys_call_table
        
  • 触发系统调用
    在x86架构下,常用的触发方式有两种:

    • 使用 int 0x80 中断指令(旧的方式)
    • 使用 syscall 指令(新的方式,效率更高)
  • 参数传递
    在x86_64架构中,系统调用号放在RAX寄存器中,参数按顺序放在RDI, RSI, RDX, RCX, R8, R9寄存器中。如果参数超过6个,则通过栈传递。

  • 错误处理
    如果系统调用成功,返回值通常是非负数;如果失败,则返回-1,并设置全局变量errno来指示具体的错误原因。

4. 常见的系统调用示例

  • 创建进程

    pid_t pid = fork(); // 创建子进程
    
  • 打开文件

    int fd = open("example.txt", O_RDONLY); // 以只读模式打开文件
    
  • 读取文件

    char buffer[1024];
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer)); // 从文件描述符fd读取数据
    
  • 发送网络数据

    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
    send(sockfd, "Hello, Server!", 13, 0); // 向服务器发送数据
    

5. 小结

系统调用是操作系统与用户程序之间的桥梁,它提供了安全且高效的方式来访问底层硬件资源和操作系统服务。理解系统调用的工作机制、分类及其实现细节,对于编写高效、可靠的软件至关重要。无论是进行基础的文件操作还是复杂的网络编程,掌握系统调用都是至关重要的技能。


by 久违

http://www.lryc.cn/news/585450.html

相关文章:

  • 线程通信与进程通信的区别笔记
  • c++11——左值、右值、完美转发、移动语义
  • 注意力机制十问
  • JavaAI时代:重塑企业级智能开发新范式
  • slam全局路径规划算法详解(Dijkstra、A*)
  • 【软考高项】信息系统项目管理师-第2章 信息技术发展(2.1 计算机软硬件)
  • Leaflet面试题及答案(21-40)
  • PLC框架-1.3- 汇川PN伺服(3号报文)
  • 全球化 2.0 | 印尼金融科技公司通过云轴科技ZStack实现VMware替代
  • 在HTML中CSS三种使用方式
  • Vue + Element UI 实现选框联动进而动态控制选框必填
  • WebSocket 重连与心跳机制:打造坚如磐石的实时连接
  • 千辛万苦3面却倒在性格测试?这太离谱了吧!
  • 飞算JavaAI:重塑Java开发的“人机协同“新模式
  • Mani-GS 运行指南
  • Cursor、飞算JavaAI、GitHub Copilot、Gemini CLI 等热门 AI 开发工具合集
  • django queryset 去重
  • Nginx服务器集群:横向扩展与集群解决方案
  • 巨人网络持续加强AI工业化管线,Lovart国内版有望协同互补
  • 《磁力下载工具实测:资源搜索+高速下载一站式解决方案》
  • DSSA(Domain-Specific Software Architecture)特定领域架构
  • 上位机知识篇---安装包架构
  • 麦迪逊悬架cad【14张】+三维图+设计说明书
  • 计算机基础:内存模型
  • Ubuntu2404修改国内镜像
  • Ubuntu 22.04安装SQL Server指南
  • 【Qt 学习之路】Qt Android开发环境搭建:Ubuntu的Vmware虚拟机中的踩坑实录
  • 数据结构:栈、队列、链表
  • AI技术重塑工业制造:从智能应用到大型模型落地
  • 从代码学习深度强化学习 - PPO PyTorch版