• Linux系统调用分析


    在HelloWorld程序中,我们可以调用libc中的getpid函数获取当前进程的进程号。HelloWorld是运行在用户空间,那么它是如何通过系统调用切换到内核空间来获取PID的呢?原来,在unistd.h中声明了函数原型,正是由于这个声明,我们才能在HelloWorld中调用getpid函数。

    extern pid_t  getpid(void);

    很多Linux下C语言写的程序都需要包含 <unistd.h>这个文件,正是这个原因:它声明了大量的系统调用函数。所以说这个文件并不是C语言自己的,而是Linux系统的!

    在libc中,getpid是用汇编语言写的,将系统调用号__NR_getpid写入寄存器R7(对于其它系统调用,如果有参数,则保存在其它的寄存器中),然后执行ARM的SWI软中断指令进入内核模式,开始执行内核空间的代码。

    ENTRY(getpid)
        mov     ip, r7
        ldr     r7, =__NR_getpid
        swi     #0
        mov     r7, ip
        cmn     r0, #(MAX_ERRNO + 1)
        bxls    lr
        neg     r0, r0
        b       __set_errno
    END(getpid)

    系统调用号__NR_getpid的定义如下:

    #define __NR_getpid (__NR_SYSCALL_BASE+ 20)

    SWI的中断处理函数内部,会根据中断号去调用真正的sys_getpid函数,其定义在kernel/sys.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.
     */
    SYSCALL_DEFINE0(getpid)
    {
        return task_tgid_vnr(current);
    }


    至此,完整的调用链条浮出水面: HelloWorld(user space) --> getpid(libc) --> ISR(SWI) --> sys_getpid(kernel)。其实是libc帮我们封装好了系统调用的接口,如果我们不用libc,而是直接用汇编操作系统调用的接口,也是可以进行系统调用的。

    这里再讲一下系统调用的上下文,仍然属于进程上下文,不要因为软中断的概念而理解为中断上下文。其实可以这样理解:把swi看作一个函数调用,swi返回后,程序继续执行而返回getpid。只不过这个swi对应的函数调用具有特权权限,因此可以调用内核中的代码。

  • 相关阅读:
    相关系数的元分析,以及带调节变量的相关系数的元分析(R)
    共有地址网段类别的划分,几个特殊的私有地址,关于子网掩码,网关的小知识 (网络)
    在文件内夹内部建立子文件夹(python)(os)
    晶振, 机器周期,进位 (单片机)
    数码管动态显示,显示从1到9,每一位显示一个数字 (单片机)
    比较R平方的差值,比较两个回归方程的(R)
    react项目控制台报错data.slice.is not function
    useRef源码
    useReducer源码实现
    useContext源码解读
  • 原文地址:https://www.cnblogs.com/swnuwangyun/p/4022765.html
Copyright © 2020-2023  润新知