Linux系统调用如何实现(linux系统调用有哪些)

Linux系统调用如何实现(linux系统调用有哪些)

浏览次数:
信息来源: 用户投稿
更新日期: 2026-02-27
文章简介

一、通过glibc提供的库函数glibc是linux下使用的开源的标准c库,它是gnu发布的libc库,即运行时库。glibc为程序员提供丰富的api(applicationprogrammin

2025阿里云双十一服务器活动

一、通过glibc提供的库函数glibc是linux下使用的开源的标准c库,它是gnu发布的libc库,即运行时库。glibc为程序员提供丰富的api(applicationprogramminginterface),除了例如字符串处理、数学运算等用户态服务之外,最重要的是封装了操作系统提供的系统服务,即系统调用的封装。那么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<sys/types.h>

    #include<sys/stat.h>

    rc=chmod("/etc/passwd",0444);

    fprintf(stderr,"chmodfailed,errno=%d

    }

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

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

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

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

    longintsyscall(longintsysno,...)

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

  • Linux系统调用如何实现,linux系统调用有哪些

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

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

    #include<sys/syscall.h>

    rc=syscall(sys_chmod,"/etc/passwd",0444);

    fprintf(stderr,"chmodfailed,errno=%d

    }

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

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

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

    #include<sys/types.h>

    #include<sys/syscall.h>

    char*file_name="/etc/passwd";

    :"0"(sys_chmod),"b"((long)file_name),"c"((long)mode)

    if((unsignedlong)rc>=(unsignedlong)-132){

    fprintf(stderr,"chmodefailed,errno=%d

    }

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

    以上就是Linux系统调用如何实现的详细内容,更多请关注主机测评网其它相关文章!

    标签:
    数据中心故障的常见原因以及克服的方法(数据中心故障处理方式)
    « 上一篇
    返回列表
    下一篇 »

    如本文对您有帮助,就请抽根烟吧!