Linux系统调用如何实现

一、通过 glibc 提供的库函数
glibc 是 linux 下使用的开源的标准 c 库,它是 gnu 发布的 libc 库,即运行时库。glibc 为程序员提供丰富的 api(application programming interface),除了例如字符串处理、数学运算等用户态服务之外,最重要的是封装了操作系统提供的系统服务,即系统调用的封装。那么glibc提供的系统调用api与内核特定的系统调用之间的关系是什么呢?

通常情况,每个特定的系统调用对应了至少一个 glibc 封装的库函数,如系统提供的打开文件系统调用 sys_open 对应的是 glibc 中的 open 函数;

其次,glibc 一个单独的 api 可能调用多个系统调用,如 glibc 提供的 printf 函数就会调用如 sys_open、sys_mmap、sys_write、sys_close 等等系统调用;

另外,多个 api 也可能只对应同一个系统调用,如glibc 下实现的 malloc、calloc、free 等函数用来分配和释放内存,都利用了内核的 sys_brk 的系统调用。

举例来说,我们通过 glibc 提供的chmod 函数来改变文件 etc/passwd 的属性为 444:

#include #include #include #include int main(){  int rc;  rc = chmod("/etc/passwd", 0444);  if (rc == -1)    fprintf(stderr, "chmod failed, errno = %dn", errno);  else    printf("chmod success!n");  return 0;}

在普通用户下编译运用,输出结果为:

chmod failed, errno = 1
上面系统调用返回的值为-1,说明系统调用失败,错误码为1,在 /usr/include/asm-generic/errno-base.h 文件中有如下错误代码说明:

#define eperm       1                /* operation not permitted */
即无权限进行该操作,我们以普通用户权限是无法修改 /etc/passwd 文件的属性的,结果正确。

二、使用 syscall 直接调用
使用上面的方法有很多好处,首先你无须知道更多的细节,如 chmod 系统调用号,你只需了解 glibc 提供的 api 的原型;其次,该方法具有更好的移植性,你可以很轻松将该程序移植到其他平台,或者将 glibc 库换成其它库,程序只需做少量改动。
但有点不足是,如果 glibc 没有封装某个内核提供的系统调用时,我就没办法通过上面的方法来调用该系统调用。如我自己通过编译内核增加了一个系统调用,这时 glibc 不可能有你新增系统调用的封装 api,此时我们可以利用 glibc 提供的syscall 函数直接调用。该函数定义在 unistd.h 头文件中,函数原型如下:

long int syscall (long int sysno, …)

ViiTor实时翻译 ViiTor实时翻译

AI实时多语言翻译专家!强大的语音识别、AR翻译功能。

ViiTor实时翻译 116 查看详情 ViiTor实时翻译

每个系统调用都有一个独特的sysno系统调用号来进行标识。在sys/syscall.h中,所有可能使用的系统调用号都被定义为宏。

… 为剩余可变长的参数,为系统调用所带的参数,根据系统调用的不同,可带0~5个不等的参数,如果超过特定系统调用能带的参数,多余的参数被忽略。

返回值 该函数返回值为特定系统调用的返回值,在系统调用成功之后你可以将该返回值转化为特定的类型,如果系统调用失败则返回 -1,错误代码存放在 errno 中。

还以上面修改 /etc/passwd 文件的属性为例,这次使用 syscall 直接调用:

#include #include #include #include int main(){  int rc;  rc = syscall(sys_chmod, "/etc/passwd", 0444);  if (rc == -1)    fprintf(stderr, "chmod failed, errno = %dn", errno);  else    printf("chmod succeess!n");  return 0;}

在普通用户下编译执行,输出的结果与上例相同。

三、通过 int 指令陷入
如果我们知道系统调用的整个过程的话,应该就能知道用户态程序通过软中断指令int 0x80 来陷入内核态(在intel pentium ii 又引入了sysenter指令),参数的传递是通过寄存器,eax 传递的是系统调用号,ebx、ecx、edx、esi和edi 来依次传递最多五个参数,当系统调用返回时,返回值存放在 eax 中。

仍然以上面的修改文件属性为例,将调用系统调用那段写成内联汇编代码:

#include #include #include #include int main(){  long rc;  char *file_name = "/etc/passwd";  unsigned short mode = 0444;  asm(    "int $0x80"    : "=a" (rc)    : "0" (sys_chmod), "b" ((long)file_name), "c" ((long)mode)  );  if ((unsigned long)rc >= (unsigned long)-132) {    errno = -rc;    rc = -1;  }  if (rc == -1)    fprintf(stderr, "chmode failed, errno = %dn", errno);  else    printf("success!n");  return 0;}

如果 eax 寄存器存放的返回值(存放在变量 rc 中)在 -1~-132 之间,就必须要解释为出错码(在/usr/include/asm-generic/errno.h 文件中定义的最大出错码为 132),这时,将错误码写入 errno 中,置系统调用返回值为 -1;否则返回的是 eax 中的值。上面程序在 32位linux下以普通用户权限编译运行结果与前面两个相同!

以上就是Linux系统调用如何实现的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/534918.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
如何使用 FabricJS 设置圆从左开始的位置?
上一篇 2025年11月9日 12:25:26
Win10系统崩溃如何使用U盘重装(详细教程)
下一篇 2025年11月9日 12:25:34

相关推荐

  • mysql安装完成后如何调整内存配置

    调整MySQL内存配置可提升性能,需修改配置文件中的关键参数:1. 设置innodb_buffer_pool_size为物理内存的50%~70%;2. 根据存储引擎合理配置key_buffer_size;3. 启用query_cache_size(5.7及以下);4. 调整tmp_table_siz…

    2026年9月11日
    000
  • Linux如何使用traceroute分析网络路径

    Linux如何使用traceroute分析网络路径Linux如何使用traceroute分析网络路径Linux如何使用traceroute分析网络路径Linux如何使用traceroute分析网络路径

    traceroute用于查看数据包路径并排查网络问题,通过递增TTL逐跳探测;2. 需手动安装,各发行版命令不同;3. 常用选项包括-I、-T、-n、-m等;4. 分析输出可判断延迟、中断或路由异常。 在Linux中使用 traceroute 可以查看数据包从本机到目标主机所经过的网络路径,帮助排查…

    2026年9月11日 用户投稿
    100
  • Linux怎么创建自定义的systemd服务

    Linux怎么创建自定义的systemd服务Linux怎么创建自定义的systemd服务Linux怎么创建自定义的systemd服务Linux怎么创建自定义的systemd服务

    答案:创建自定义systemd服务需编写.service文件并放置于/etc/systemd/system/,通过systemctl管理。具体步骤包括:使用绝对路径在[Service]中定义ExecStart,设置User、WorkingDirectory等参数,选择合适的Type类型(如simpl…

    2026年9月11日 用户投稿
    100
  • Linux如何查看文件系统使用情况

    Linux如何查看文件系统使用情况Linux如何查看文件系统使用情况Linux如何查看文件系统使用情况Linux如何查看文件系统使用情况

    使用df命令查看文件系统使用情况,如df -h以可读格式显示空间,df -i检查inode使用;用du -sh查看指定目录大小,结合watch实时监控变化,注意区分磁盘空间与inode占用。 在Linux中查看文件系统使用情况,最常用的方法是使用 df 命令。这个命令可以显示磁盘空间的总体使用情况,…

    2026年9月11日 用户投稿
    000
  • VSCode的代码错误和警告如何快速定位?

    使用问题面板和快捷键可快速定位代码错误与警告。按Ctrl+Shift+M打开问题面板,查看所有错误、警告并点击跳转;F8/Shift+F8逐条导航问题;代码行波浪线提示悬停查看详情;右侧滚动条标记助于长文件定位;安装语言扩展如ESLint提升检测精度并支持快速修复。 在 VSCode 中快速定位代码…

    2026年9月11日
    300
  • 如何使用Java中的Paths与Path操作路径

    Path是接口表示文件路径,Paths是创建Path实例的工具类;通过Paths.get()创建路径,支持跨平台分隔符处理;常用操作包括获取文件名、父路径、根路径,转换为绝对路径或真实路径,以及路径合并、解析相对路径等,提升代码可移植性。 在Java中处理文件路径时,Path 和 Paths 是 N…

    2026年9月11日
    000
  • Linux如何检测网络丢包情况

    Linux如何检测网络丢包情况Linux如何检测网络丢包情况Linux如何检测网络丢包情况Linux如何检测网络丢包情况

    使用ping检测基础丢包率,通过mtr定位中间链路节点问题,利用tcping测试TCP端口连通性,结合ifconfig或ip命令检查本地网卡丢包情况,分段排查可准确判断网络丢包原因。 Linux下检测网络丢包情况可以通过多种命令和工具实现,重点在于判断是本地网络问题、中间链路问题还是目标主机问题。以…

    2026年9月11日 用户投稿
    100
  • Linux怎么统计某段时间内的带宽使用

    答案是根据需求选择合适工具:长期趋势用vnstat,历史详细记录用sar,精确自定义统计则通过读取/proc/net/dev编写脚本实现,不同场景需分层处理以获得最佳效果。 在Linux上统计某段时间内的带宽使用,核心思路是利用系统提供的工具或接口,在时间段的起点和终点获取网络流量数据,然后计算差值…

    2026年9月11日
    000
  • 如何在Linux中添加用户到组 Linux usermod -G操作指南

    使用usermod -aG命令可安全地将用户添加到新组而不覆盖原有组。首先通过groups或id命令查看用户当前所属组,若直接使用usermod -G会替换所有附加组,导致权限丢失。-G用于设置附加组,-g用于修改主组。例如将alice主组改为developers并加入www和db组,应先执行use…

    2026年9月11日
    000
  • Linux如何配置用户登录欢迎信息

    9月1日起,人工智能生成合成内容标识、网络攻击事件判定、智能家电语音交互、电动自行车安全等一批涉及网络安全技术、智能家电等领域的国家标准正式实施,为规范新兴产业发展、保障安全提供支撑。 在Linux系统里,配置用户登录欢迎信息其实远不止是简单地改个文件那么简单,它涉及到系统安全、用户体验,甚至一点点…

    2026年9月11日
    000
  • Linux怎么使用firewalld管理端口开放

    答案是通过firewalld的区域概念配置端口开放与网络规则。首先确认firewalld运行并启用,使用–add-port或–add-service在指定区域(如public)开放端口或服务,配合–permanent实现永久生效,并执行–reload应…

    2026年9月11日
    100
  • Linux如何卸载deb软件包并清理配置文件

    Linux如何卸载deb软件包并清理配置文件Linux如何卸载deb软件包并清理配置文件Linux如何卸载deb软件包并清理配置文件Linux如何卸载deb软件包并清理配置文件

    使用apt purge可彻底卸载deb包并清除配置文件,配合autoremove清理残留依赖,必要时手动删除遗留文件以保持系统整洁。 在Linux系统中,尤其是基于Debian的发行版(如Ubuntu),使用 .deb 包安装软件非常常见。当你需要彻底卸载一个deb软件包并清除其配置文件时,可以使用…

    2026年9月11日 用户投稿
    100
  • Workerman怎么进行资源隔离?Workerman资源限制设置?

    Workerman通过多进程模型实现操作系统级资源隔离,每个Worker进程独立运行,互不影响,主进程可监控并重启异常进程以保障服务稳定。为防止资源滥用,可通过PHP的memory_limit限制单个进程内存,结合Worker::$max_request参数定期重启进程以释放内存;CPU资源则依赖操…

    2026年9月11日
    100
  • VSCode的悬浮窗口可以固定吗?

    可通过快捷键Ctrl+K Ctrl+I(Win/Linux)或Cmd+K Cmd+I(macOS)手动打开更稳定的提示窗口,实现类似固定悬浮窗的效果。 VSCode 的悬浮窗口(比如鼠标悬停时出现的提示框)默认是临时显示的,会随着鼠标移开或点击编辑器其他区域而消失。目前 VSCode 原生并不支持直…

    2026年9月11日
    100
  • Linux命令行编辑器vim快捷键总结

    答案是掌握Vim的核心在于理解其模式设计与快捷键逻辑,通过沉浸式练习形成肌肉记忆,利用动词-名词命令结构提升编辑效率,从而在键盘驱动下实现高效文本操作。 Vim快捷键是Linux命令行下高效文本编辑的核心,它们将编辑操作转化为一种近乎本能的语言,一旦掌握,能极大提升开发和系统管理效率。虽然初学时其独…

    2026年9月11日
    200
  • Linux如何查看软件包的依赖关系树

    Linux如何查看软件包的依赖关系树Linux如何查看软件包的依赖关系树Linux如何查看软件包的依赖关系树Linux如何查看软件包的依赖关系树

    在Linux中查看软件包依赖树需根据发行版选择命令:Debian/Ubuntu用apt-cache depends或apt depends;RHEL/CentOS/Fedora用dnf repoquery –requires –tree;Arch Linux用pactree(…

    2026年9月11日 用户投稿
    200
  • Linux如何强制某个用户下线

    强制下线Linux用户需终止其所有进程,先用ps或pkill命令查找并结束进程,推荐先发SIGTERM信号优雅终止,无效再用SIGKILL;可通过锁定账户或修改shell防止再次登录,操作需root权限并注意数据丢失与系统稳定风险。 强制Linux用户下线,其实就是终止该用户的所有进程。理解这一点,…

    2026年9月11日
    200
  • Linux怎么监控实时网络流量

    Linux怎么监控实时网络流量Linux怎么监控实时网络流量Linux怎么监控实时网络流量Linux怎么监控实时网络流量

    使用iftop可实时查看各IP连接的带宽使用情况;2. nethogs按进程显示流量,便于定位高占用程序;3. sar每秒刷新网卡收发速率,适合性能分析;4. vnstat记录长期流量统计,资源消耗低,适合日常监控组合使用。 监控Linux系统的实时网络流量有多种实用方法,常用的是通过命令行工具快速…

    2026年9月11日 用户投稿
    100
  • VSCode的窗口边框和标题栏颜色能否进行深度自定义?

    答案:VSCode通过workbench.colorCustomizations和window.titleBarStyle可自定义标题栏颜色,边框颜色仅Linux等平台支持,深度定制需CSS注入。 VSCode 的窗口边框和标题栏颜色支持一定程度的深度自定义,但具体能力取决于操作系统和设置方式。 1…

    2026年9月11日
    400
  • Linux怎么使用netstat查看端口占用

    Linux怎么使用netstat查看端口占用Linux怎么使用netstat查看端口占用Linux怎么使用netstat查看端口占用Linux怎么使用netstat查看端口占用

    netstat是Linux中用于查看网络连接、端口占用等信息的工具,需安装net-tools包;使用netstat -tuln可查看监听端口,加-p参数显示进程信息,如netstat -tulnp | grep :80可查80端口被哪个进程占用;推荐替代命令为ss和lsof。 在Linux系统中,n…

    2026年9月11日 用户投稿
    000

发表回复

登录后才能评论
关注微信