Linux系统调用的过程

系统调用是Linux内核与用户程序交互的关键机制,包括文件操作、进程控制、内存管理等多个方面。当应用调用如open()这样的系统调用时,会通过软中断进入内核态,执行相应的处理函数(如sys_open),完成操作后返回用户态并提供结果,如文件描述符。
摘要由CSDN通过智能技术生成

Linux系统调用的过程

今日小米面试问到的问题,一下子没反应过来是中断的触发与状态恢复,太菜了,只回答了一个用户态到内核态的切换。太菜了,555,复盘记录一下答案。

1.什么是系统调用

系统调用(syscall)是linux内核为用户态程序提供的主要功能接口。通过系统调用,用户态进程能够临时切换到内核态,使用内核态才能访问的硬件和资源完成特定功能。系统调用由linux内核和内核模块实现,内核在处理系统调用时还会检查系统调用请求和参数是否正确,保证对特权资源和硬件访问的正确性。通过这种方式,linux在提供内核和硬件资源访问接口的同时,保证了内核和硬件资源的使用正确性和安全性。
syscall

2.常见系统调用

根据Linux系统调用的功能,下面列举一些常用的库函数,并按照功能进行分类:

文件操作类

- fopen()fclose():打开或关闭文件。
- fread()fwrite():从文件读取或向文件写入数据。
- fseek():移动文件指针。
- remove()rename():删除或重命名文件。

进程控制类

- getpid()getppid():获取当前进程ID或其父进程ID。
- fork():创建一个新进程。
- execv()execve():执行一个新程序。
- wait()waitpid():等待子进程退出或捕获信号。
- exit():退出当前进程

目录和文件管理类

- opendir()closedir():打开或关闭目录。
- readdir():读取目录中的项。
- mkdir()rmdir():创建或删除目录。

网络相关类

- socket()bind()listen()accept():创建并监听套接字,接受连接。
- connect():建立到远端主机的连接。
- read()write():从套接字读取或写入数据。

内存管理类

- malloc()calloc()realloc()free():分配或释放内存。
- mmap():将文件映射到内存中。

信号处理类

- signal()sigaction():安装信号处理函数。
- kill():向进程发送信号。

时间和日期类

- time():获取当前时间。
- localtime()gmtime():将时间转换为本地或UTC时间。
- strftime():将时间格式化为字符串形式。

进程间通信类

- pipe():创建管道。
- shmget()shmat()shmctl()shmdt():控制共享内存。
- semget()semop()semctl():控制信号量。

3.系统调用基本流程

syscall接口由glibc提供和实现,第一个参数number表示需要调用的系统调用编号,后续的可变参数根据系统调用类型确定。内核具体支持的系统调用号可在<sys/syscall.h>中查看。函数调用失败会返回-1,具体错误原因保存在errno中,errno的含义可参考<errno.h>

需要注意的是,这里的返回值和errno是glibc封装提供的,内核的系统调用响应函数本身不提供errno,返回值也不同。

#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <unistd.h>
#include <sys/syscall.h>   /* For SYS_xxx definitions */
int syscall(int number, ...);

Linux系统调用的基本流程大致如下所示:

  • 应用程序调用系统调用函数:当应用程序需要执行一个系统调用时,它会调用相应的系统调用函数,例如open()、read()等。这些系统调用函数包含在C库中,并提供了对应的系统调用号和参数。
  • 系统调用函数生成软中断:当应用程序调用系统调用函数时,相应的系统调用号和参数被传递给系统调用函数。系统调用函数会将这些参数打包成一个指令集,然后通过int 0x80、sysenter或syscall等指令生成软中断(也称为陷阱、内陷)。
  • 内核处理中断请求:当应用程序生成软中断后,处理器会暂停应用程序的运行,保存用户态堆栈信息,从用户态切换到内核态,并执行中断处理程序。在Linux中,中断处理程序位于内核代码空间,并由内核管理。
  • 内核处理系统调用:当内核接收到中断请求后,它会根据系统调用号和参数确定应该执行哪个系统调用,然后执行相应的系统调用处理程序。系统调用处理程序可以访问内核空间中的所有数据结构和设备。
  • 内核返回结果:当系统调用处理程序完成执行后,它将结果返回给应用程序,从内核态切换到用户态,并恢复之前保存的用户态堆栈信息。如果发生错误,系统调用处理程序会返回一个错误代码。
  • 应用程序继续执行:当应用程序收到系统调用函数的返回值后,它会根据返回值执行相应的操作,并继续执行程序的下一条指令。

4.举个栗子

下面以打开一个文件(面试被鞭打的题目)为例,介绍一下Linux系统调用的具体流程:

  • 应用程序调用open()函数:当应用程序需要打开一个文件时,它会调用open()系统调用函数,并传递相应的参数(例如文件名、打开模式等)。
  • open()函数生成软中断:当应用程序调用open()系统调用函数时,该函数会将参数打包成一个指令集,然后通过int 0x80、sysenter或syscall等指令生成软中断,并触发一次从用户态到内核态的切换。
  • 内核处理中断请求:处理器在接收到软中断请求后,会进入内核态,中断服务例程会检查请求的参数和权限,并根据系统调用号分派给不同的系统调用处理程序,对于open()系统调用,则将它分发给相应的sys_open函数进行处理。
  • 执行打开文件操作:当sys_open函数接收到open()系统调用请求后,它会检查参数合法性、文件是否存在等情况,如果一切正常则执行打开文件的操作,例如在内核建立一个文件结构体对象,分配文件描述符等。
  • 返回结果给应用程序:当sys_open函数执行完毕后,它将文件描述符等结果返回给中断服务例程,之后中断服务例程再将结果返回给应用程序调用open()函数的那个线程。返回结果后,处理器从内核态切换回用户态,并将控制权交还给应用程序。
  • 应用程序继续执行:当应用程序收到open()系统调用函数的返回值后,它会根据返回值执行相应的操作,并继续执行程序的下一条指令。

综上所述,Linux系统调用的过程是一个从用户态切换到内核态,执行系统调用处理程序并返回结果的过程。对于open()系统调用,它的过程是通过sys_open函数在内核中完成打开文件的操作,并返回相应的文件描述符给应用程序。

系统调用的过程是一个从用户态切换到内核态,执行系统调用处理程序并返回结果的过程。对于open()系统调用,它的过程是通过sys_open函数在内核中完成打开文件的操作,并返回相应的文件描述符给应用程序。

5. 许愿

八股背得好,offer追着跑!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值