Linux下系统调用的组成与实现

主要包括三个部分:(1)唯一的系统调用号(System Call Number);(2)系统调用表中相应的表项,即具体的函数地址;(3)对应的具体函数,即系统调用函数体。

以getpid()POSIX接口举例如下:

(1)系统调用号在文件    include/asm-x86/unistd_32.h中,表现如下:

/*
 * This file contains the system call numbers.
 */

#define __NR_restart_syscall      0
#define __NR_exit         1
#define __NR_fork         2
#define __NR_read         3
#define __NR_write        4
#define __NR_open         5
#define __NR_close        6
#define __NR_waitpid          7
#define __NR_creat        8
#define __NR_link         9
#define __NR_unlink      10
#define __NR_execve      11
#define __NR_chdir       12
#define __NR_time        13
#define __NR_mknod       14
#define __NR_chmod       15
#define __NR_lchown      16
#define __NR_break       17
#define __NR_oldstat         18
#define __NR_lseek       19
#define __NR_getpid      20
#define __NR_mount       21
……
(2)系统调用表在系统中的位置是:   arch/avr32/kernel/syscall_table.S 

表现如下:

……
sys_call_table:
    .long   sys_restart_syscall
    .long   sys_exit
    .long   __sys_fork
    .long   sys_read
    .long   sys_write
    .long   sys_open        /* 5 */
    .long   sys_close
    .long   sys_umask
    .long   sys_creat
    .long   sys_link
    .long   sys_unlink      /* 10 */
    .long   __sys_execve
    .long   sys_chdir
    .long   sys_time
    .long   sys_mknod
    .long   sys_chmod       /* 15 */
    .long   sys_chown
    .long   sys_lchown
    .long   sys_lseek
    .long   sys_llseek
    .long   sys_getpid      /* 20 */
    .long   sys_mount
    .long   sys_umount
……

(3)具体的函数实现代码在系统中的位置是:kernel/timer.c

/**
 * sys_getpid - return the thread group id of the current process
 *
 * Note, despite the name, this returns the tgid not the pid.  The tgid and
 * the pid are identical unless CLONE_THREAD was specified on clone() in
 * which case the tgid is the same in all threads of the same group.
 *
 * This is SMP safe as current->tgid does not change.
 */
asmlinkage long sys_getpid(void)
{
    return task_tgid_vnr(current);
}


那么,我们在系统中如何使用这个函数呢流程如下:

getpid(void)  ------->    int 0x80进入内核(同时从寄存器eax获取超级调用号) --------->   system_call  ,  call *sys_ call_table(%eax, 4)(这里的动作是将PC值改为%eax * 4 + sys_call_table)  ----->  sys_getpid(void)  ------->   system_exit , resume_userspace ----->  给用户空间返回结果



posted @   javaadu  阅读(183)  评论(0编辑  收藏  举报
编辑推荐:
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
阅读排行:
· “你见过凌晨四点的洛杉矶吗?”--《我们为什么要睡觉》
· 编程神器Trae:当我用上后,才知道自己的创造力被低估了多少
· C# 从零开始使用Layui.Wpf库开发WPF客户端
· C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)
· 接口重试的7种常用方案!
点击右上角即可分享
微信分享提示