系统调用(System Call)是操作系统为在用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互提供的一组接口。当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系统调用函数。

下面介绍Linux 下三种发生系统调用的方法:

1、通过 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 函数来改变文件的属性为:

#include<stdio.h>
int main()
{int rc=chmod("./kali",0666);//这个必须是4个数字if(rc==-1){perror("chmod fail\n");}elseprintf("chmod succeed\n");return 0;
}

2、使用 syscall直接调用:

上面通过glibc的方法有很多好处,首先你无须知道更多的细节,如 chmod 系统调用号,你只需了解 glibc 提供的 API 的原型;其次,该方法具有更好的移植性,你可以很轻松将该程序移植到其他平台,或者将 glibc 库换成其它库,程序只需做少量改动。

但有点不足是,如果 glibc 没有封装某个内核提供的系统调用时,我就没办法通过上面的方法来调用该系统调用。如我自己通过编译内核增加了一个系统调用,这时 glibc 不可能有你新增系统调用的封装 API,此时我们可以利用 glibc 提供的syscall 函数直接调用。该函数定义在 unistd.h 头文件中,函数原型如下:

long int syscall (long int sysno, ...)

  • sysno :是系统调用号,每个系统调用都有唯一的系统调用号来标识。在 sys/syscall.h 中有所有可能的系统调用号的宏定义。
  • ... :剩余可变长的参数,为系统调用所带的参数,根据系统调用的不同,可带0~5个不等的参数,如果超过特定系统调用能带的参数,多余的参数被忽略。

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

以上面的修改文件属性为例,使用syscall:

#include<stdio.h>
#include<unistd.h>
#include<sys/syscall.h>
int main()
{//syscall在头文件unistd.h中,SYS_chmod在头文件syscall.h中int rc=syscall(SYS_chmod,"./kali",0777);if(rc==-1){perror("chmod fail\n");}elseprintf("chmod succeed\n");return 0;
}

3、通过 int 指令陷入:

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

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

#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <errno.h>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 = %d\n", errno);elseprintf("success!\n")return 0;
}

参考:

linux系统调用的三种方法_51CTO博客_linux系统调用

java使用linux系统调用_三种方法实现Linux系统调用_weixin_39667452的博客-CSDN博客

linux系统调用的三种方法相关推荐

  1. 为什么系统调用会消耗较多资源?系统调用的三种方法:软件中断(分析过程)、SYSCALL指令、vDSO(虚拟动态链接对象linux-vdso.so.1)

    Table of Contents 软件中断 汇编指令 vDSO 总结 参考文章 系统调用是计算机程序在执行的过程中向操作系统内核申请服务的方法,这可能包含硬件相关的服务.新进程的创建和执行以及进程调 ...

  2. Linux 下系统调用的三种方法

    系统调用(System Call)是操作系统为在用户态运行的进程与硬件设备(如CPU.磁盘.打印机等)进行交互提供的一组接口.当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系 ...

  3. 查看linux内核的三种方法

    想知道您的系统使用哪个 Linux内核版本吗?以下是在Linux终端中检查内核版本的几种方法. 当您需要了解系统上正在使用的确切Linux内核版本时,您可能会遇到这种情况.借助功能强大的Linux 命 ...

  4. 修改Linux主机的三种方法

    概述 日常工作中在安装一些系统时,需要修改hostname,比如安装Hadoop时需要修改主机名,而且主机名不能包含下划线. 实际上,主机名分三种(命令hostnamectl或hostnamectl ...

  5. 重启linux系统的三种方法,强制重启Linux系统的几种方法

    实际生产环境中某些情况下 Linux 服务器系统在出现致命错误需要远程进行重启,通过常规的 reboot.init 6 等方法无法正常重启(例如重启时卡在驱动程序里等情况),这时就需要通过下面介绍的几 ...

  6. linux redhat 版本查看,查看RedHat linux版本的三种方法

    查看linux的版本主要有三种方法: 1) 登录到服务器执行 lsb_release -a ,即可列出所有版本信息,例如: [root@3.5.5Biz-46 ~]# lsb_release -a L ...

  7. linux 已打开的文件夹里,打开linux文件的三种方法

    怎么打开linux文件,方法如下: 方法一(利用Vim文本编辑器): 1.打开终端.点击菜单,然后找到终端程序.程序的图标是一个黑色的方框,上面有一个白色的">_".点击它. ...

  8. 查看linux内核的三种方法介绍

    前言 当您需要了解系统上正在使用的确切Linux内核版本时,您可能会遇到这种情况.借助功能强大的Linux 行,您可以轻松地找到答案. 在本文中,我将向您展示各种了解内核版本以及这些数字实际含义的方法 ...

  9. 从U盘运行Linux操作系统的三种方法

    摘要: 从U盘运行Linux操作系统的三种方法 usb_linux_0 你或许听说过在U盘上运行live Linux操作系统,但你知不知道可以永久的保存运行时的数据,或者直接将Linux安装到U盘?本 ...

最新文章

  1. dynamodb java_使用Java扫描DynamoDB项目
  2. 21 个 curl 命令练习 | Linux 中国
  3. 移动前端webApp开发点滴积累20140524
  4. 【转】linux/unix下 pid文件作用浅析
  5. 第四讲 系统建模方法
  6. safari java插件故障_Safari Flash插件故障怎么办-Safari Flash插件故障解决方法 - 河东软件园...
  7. mediawiki mysql配置_MediaWiki 搭建与配置使用
  8. 1、spss中做相关分析
  9. python取excel单元格数值_python读取excel文件单元格中的数据返回类型
  10. 【浅谈爬虫】一名合格的Python爬虫工程师必须具备技能—具体了解四大Python爬虫分类以及爬虫基本原理实现
  11. ArcEngine编辑模块——将线段按距离、按比例分割成两部分
  12. Python笔记2_替换式文本加密
  13. (转) CS的顶级会议和期刊
  14. 计算机网络技术三级英文,计算机三级网络技术真题整理(国外英文资料).doc...
  15. iFIXIT认为 HTC One M8 是近年最难维修的手机之一
  16. 戴尔笔记本win10系统恢复出厂设置
  17. 虚拟机网络连通性选择
  18. Diversified Retrieval(多样性检索,MMR,DPP,VMIG)
  19. c语言求圆的面积周长体积,c语言求圆的面积和周长
  20. vgg16 清华镜像_Caffe vgg16网络结构

热门文章

  1. rk3288 设置imx6ull的lcd控制器的寄存器
  2. OpenSSL命令大全,CA证书生成,客户端证书生成实例
  3. HttpModule是如何工作的
  4. Swift Web 开发之 Vapor - 入门(一)
  5. arcsoft人脸识别sdk使用方法2(java版本)
  6. Android中获取手机 IMEI Mac地址 IP地址
  7. PostgreSQL无法创建用户
  8. 亚马逊运营,站外推广的五种方式 推广时需要注意什么?
  9. 谷歌地图地址地址自动完成框
  10. Mockplus实例之一看就会de五个交互功能