美文网首页
sys_reboot的定义

sys_reboot的定义

作者: 发条蛙 | 来源:发表于2017-11-09 19:13 被阅读0次

在阅读Android 4.4代码的过程中,分析recovery的过程中遇到函数sys_reboot的定义,发现其定义过程有大量的宏,因此将其记述于下。

函数sys_reboot定义

函数sys_reboot的定义在文件kernel/kernel/sys.c中:

/*
 * Reboot system call: for obvious reasons only root may call it,
 * and even root needs to set up some magic numbers in the registers
 * so that some mistake won't make this reboot the whole machine.
 * You can also set the meaning of the ctrl-alt-del-key here.
 *
 * reboot doesn't sync: do that yourself before calling this.
 */
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
        void __user *, arg)
{
    struct pid_namespace *pid_ns = task_active_pid_ns(current);
    char buffer[256];
    int ret = 0;

    /* We only trust the superuser with rebooting the system. */
    if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
        return -EPERM;

    /* For safety, we require "magic" arguments. */
    if (magic1 != LINUX_REBOOT_MAGIC1 ||
        (magic2 != LINUX_REBOOT_MAGIC2 &&
                    magic2 != LINUX_REBOOT_MAGIC2A &&
            magic2 != LINUX_REBOOT_MAGIC2B &&
                    magic2 != LINUX_REBOOT_MAGIC2C))
        return -EINVAL;

    /*
     * If pid namespaces are enabled and the current task is in a child
     * pid_namespace, the command is handled by reboot_pid_ns() which will
     * call do_exit().
     */
    ret = reboot_pid_ns(pid_ns, cmd);
    if (ret)
        return ret;

    /* Instead of trying to make the power_off code look like
     * halt when pm_power_off is not set do it the easy way.
     */
    if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
        cmd = LINUX_REBOOT_CMD_HALT;

    mutex_lock(&reboot_mutex);
    switch (cmd) {
    case LINUX_REBOOT_CMD_RESTART:
        kernel_restart(NULL);
        break;

    case LINUX_REBOOT_CMD_CAD_ON:
        C_A_D = 1;
        break;

    case LINUX_REBOOT_CMD_CAD_OFF:
        C_A_D = 0;
        break;

    case LINUX_REBOOT_CMD_HALT:
        kernel_halt();
        do_exit(0);
        panic("cannot halt");

    case LINUX_REBOOT_CMD_POWER_OFF:
        kernel_power_off();
        do_exit(0);
        break;

    case LINUX_REBOOT_CMD_RESTART2:
        if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
            ret = -EFAULT;
            break;
        }
        buffer[sizeof(buffer) - 1] = '\0';

        kernel_restart(buffer);
        break;

#ifdef CONFIG_KEXEC
    case LINUX_REBOOT_CMD_KEXEC:
        ret = kernel_kexec();
        break;
#endif

#ifdef CONFIG_HIBERNATION
    case LINUX_REBOOT_CMD_SW_SUSPEND:
        ret = hibernate();
        break;
#endif

    default:
        ret = -EINVAL;
        break;
    }
    mutex_unlock(&reboot_mutex);
    return ret;
}

SYSCALL_DEFINE4定义

看到这里的声明使用到了宏SYSCALL_DEFINE4,该宏实现在文件kernel/include/linux/syscalls.h中:

#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)

SYSCALL_DEFINEx定义

SYSCALL_DEFINEx也实现在文件kernel/include/linux/syscalls.h中:

#define SYSCALL_DEFINEx(x, sname, ...)              \
    SYSCALL_METADATA(sname, x, __VA_ARGS__)         \
    __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

SYSCALL_METADATA定义

SYSCALL_METADATA定义的定义如下:

#ifdef CONFIG_FTRACE_SYSCALLS
#define SYSCALL_METADATA(sname, nb, ...)            \
    static const char *types_##sname[] = {          \
        __MAP(nb,__SC_STR_TDECL,__VA_ARGS__)        \
    };                          \
    static const char *args_##sname[] = {           \
        __MAP(nb,__SC_STR_ADECL,__VA_ARGS__)        \
    };                          \
    SYSCALL_TRACE_ENTER_EVENT(sname);           \
    SYSCALL_TRACE_EXIT_EVENT(sname);            \
    static struct syscall_metadata __used           \
      __syscall_meta_##sname = {                \
        .name       = "sys"#sname,          \
        .syscall_nr = -1,   /* Filled in at boot */ \
        .nb_args    = nb,               \
        .types      = nb ? types_##sname : NULL,    \
        .args       = nb ? args_##sname : NULL, \
        .enter_event    = &event_enter_##sname,     \
        .exit_event = &event_exit_##sname,      \
        .enter_fields   = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
    };                          \
    static struct syscall_metadata __used           \
      __attribute__((section("__syscalls_metadata")))   \
     *__p_syscall_meta_##sname = &__syscall_meta_##sname;
#else
#define SYSCALL_METADATA(sname, nb, ...)
#endif

很明显是用于syscall的追踪,故这里不考虑。

__SYSCALL_DEFINEx定义

继续向下,__SYSCALL_DEFINEx也实现在文件kernel/include/linux/syscalls.h中:

#define __SYSCALL_DEFINEx(x, name, ...)                 \
    asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));  \
    static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));  \
    asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))   \
    {                               \
        long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));  \
        __MAP(x,__SC_TEST,__VA_ARGS__);             \
        __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));   \
        return ret;                     \
    }                               \
    SYSCALL_ALIAS(sys##name, SyS##name);                \
    static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))

__MAP定义

__MAP定义如下:

#define __MAP0(m,...)
#define __MAP1(m,t,a) m(t,a)
#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
#define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
#define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
#define __MAP(n,...) __MAP##n(__VA_ARGS__)

__SC_DECL定义

__SC_DECL定义如下:

#define __SC_DECL(t, a) t a

__PROTECT定义

__PROTECT定义如下:

#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)

总结

根据函数定义:

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
        void __user *, arg)

结合SYSCALL_DEFINE4的定义有:

SYSCALL_DEFINEx(4, _reboot, int, magic1, int, magic2, unsigned int, cmd,
        void __user *, arg)

再结合SYSCALL_DEFINEx则有:

SYSCALL_METADATA(_reboot, 4, int, magic1, int, magic2, unsigned int, cmd,
            void __user *, arg)
__SYSCALL_DEFINEx(4, _reboot, int, magic1, int, magic2, unsigned int, cmd,
            void __user *, arg)

去掉trace部分,也就是SYSCALL_METADATA部分,则为:

__SYSCALL_DEFINEx(4, _reboot, int, magic1, int, magic2, unsigned int, cmd,
            void __user *, arg)

再结合__SYSCALL_DEFINEx则有:

asmlinkage long sys_reboot(__MAP(4,__SC_DECL,__VA_ARGS__));  
static inline long SYSC_reboot(__MAP(4,__SC_DECL,__VA_ARGS__));  
asmlinkage long SyS_reboot(__MAP(4,__SC_LONG,__VA_ARGS__))   
{                               \
    long ret = SYSC_reboot(__MAP(4,__SC_CAST,__VA_ARGS__));          __MAP(4,__SC_TEST,__VA_ARGS__);             
    __PROTECT(x, ret,__MAP(4,__SC_ARGS,__VA_ARGS__));   
    return ret;                     
}                               
SYSCALL_ALIAS(sys_reboot, SyS_reboot);                
static inline long SYSC_reboot(__MAP(4,__SC_DECL,__VA_ARGS__))

再展开__MAP__SC_DECL__PROTECT得出:

asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user * arg);  
static inline long SYSC_reboot(int magic1, int magic2, unsigned int cmd, void __user * arg);  
asmlinkage long SyS_reboot(__MAP(4,__SC_LONG,__VA_ARGS__))   
{                               \
    long ret = SYSC_reboot((int)magic1, (int)magic2, (unsigned int)cmd, (void __user *)arg);          
    __MAP(4,__SC_TEST,__VA_ARGS__);             
    __PROTECT(x, ret, magic1, magic2, cmd, arg);
    return ret;                     
}                               
SYSCALL_ALIAS(sys_reboot, SyS_reboot);                
static inline long SYSC_reboot(int magic1, int magic2, unsigned int cmd, void __user * arg)

最终可知,外部调用的sys_reboot事实上是通过调用SYSC_reboot来实现的。

相关文章

  • sys_reboot的定义

    在阅读Android 4.4代码的过程中,分析recovery的过程中遇到函数sys_reboot的定义,发现其定...

  • 定义你的定义

    写作08 什么是定义 01 什么是定义?为什么定义重要? 我们很喜欢下定义,但从来没有思考过什么是定义。 定义好坏...

  • 哲学初始:定义的定义

    一切定义,都是无中生有。这是元定义。元定义即定义了“有——无”二元对立、连续、循环。 这是以往的哲学家们普遍忽视的...

  • %的定义

    可以猜下下图结果是什么: 结果如下: 原因是 a%b的余数的定义是(a/b)*b+a%b恒等于a。

  • kubernetes - 对象的定义(2)

    Pod的定义 Service的定义 Deployment的定义 Namespace的定义 ConfigMap的定义...

  • 基本办公文书转HTML工具

    定义段落 定义语气更为强烈的强调文本。 定义列表的项目 定义无序列表 定义表格中的主体内容 定义表格中的行 定义...

  • 标签

    定义粗体文本 定义大字号 定义着重文字 定义斜体文字 定义小号字 定义加重语气 定义下表字 定义上标字 定义插入...

  • 2-12. 表格标签中的其他标签

    | | 定义表格 || | 定义表格标题。 || | 定义表格的表头。 || | 定义表格的行。 ...

  • HTML5备忘录

    H5新增标签 ——定义文章 ——定义页面内容旁边的内容 ——定义声音内容 ——定义视频内容 ——定义图形 ——定义...

  • HTML5初试牛刀

    标签描述定义注释。 定义文档类型。定义锚。定义缩写。定义只取首字母的缩写。 定义客户端脚本。 定义 section...

网友评论

      本文标题:sys_reboot的定义

      本文链接:https://www.haomeiwen.com/subject/urkmmxtx.html