arm64系统调用之getdents64

分析getdents64系统调用

在头文件include/uapi/asm-generic/unistd.h 中是所有内核支持的系统调用。通过_SYSCALL宏来定义。

#ifndef __SYSCALL
#define __SYSCALL(x, y)
#endif
 

/* fs/readdir.c */
#define __NR_getdents64 61
__SYSCALL(__NR_getdents64, sys_getdents64)
 

arch/arm64/kernel/sys.c 

#undef __SYSCALL
#define __SYSCALL(nr, sym)    asmlinkage long __arm64_##sym(const struct pt_regs *);
#include 

#undef __SYSCALL
#define __SYSCALL(nr, sym)    [nr] = __arm64_##sym,

const syscall_fn_t sys_call_table[__NR_syscalls] = {
    [0 ... __NR_syscalls - 1] = __arm64_sys_ni_syscall,
#include   //arch/arm64/include/asm/unistd.h
};

include包含:

arch/arm64/include/asm/unistd.h

        arch/arm64/include/uapi/asm/unistd.h

                 include/uapi/asm-generic/unistd.h

系统调用的具体实现通过SYSCALL_DEFINEx宏定义:

linux/syscalls.h

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__) #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) #define SYSCALL_DEFINE_MAXARGS 6 
#define SYSCALL_DEFINEx(x, sname, ...) \ 
        SYSCALL_METADATA(sname, x, __VA_ARGS__) \
        __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

__SYSCALL_DEFINEx:

arch/arm64/include/asm/syscall_wrapper.h

#define __SYSCALL_DEFINEx(x, name, ...)                        \
    asmlinkage long __arm64_sys##name(const struct pt_regs *regs);        \
    ALLOW_ERROR_INJECTION(__arm64_sys##name, ERRNO);            \
    static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));        \
    static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));    \
    asmlinkage long __arm64_sys##name(const struct pt_regs *regs)        \
    {                                    \
        return __se_sys##name(SC_ARM64_REGS_TO_ARGS(x,__VA_ARGS__));    \
    }                                    \
    static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))        \
    {                                    \
        long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));    \
        __MAP(x,__SC_TEST,__VA_ARGS__);                    \
        __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));        \
        return ret;                            \
    }                                    \
    static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))  

定义fs/readdir.c

SYSCALL_DEFINE3(getdents64, unsigned int, fd,
                struct linux_dirent64 __user *, dirent, unsigned int, count)
{
        return ksys_getdents64(fd, dirent, count);
}
 

展开后:

asmlinkage long __arm64_sysgetdents64(...)定义了一个函数和__SYSCALL宏申明的一致

asmlinkage long __arm64_sysgetdents64(...)

{

        ......省略内容.......
}

static long __se_sysgetdents64(...)

{

        ......省略内容.......
}

static inline long __do_sysgetdents64(__MAP(x,__SC_DECL,__VA_ARGS__))

下面是实现的部分在{}中
{

        return ksys_getdents64(fd, dirent, count);
}

 ls命令的测试:

ls实际上使用的就是getdents64系统调用

[root@localhost ~]# ls /proc
[  954.398303] ===proc_readdir_de
[  954.398309] CPU: 3 PID: 1197 Comm: ls Not tainted 4.19.0-fix-full-10+ #38
[  954.408129] Hardware name: PHYTIUM LTD D2000/D2000, BIOS  
[  954.413601] Call trace:
[  954.416039]  dump_backtrace+0x0/0x1b8
[  954.419688]  show_stack+0x24/0x30
[  954.422992]  dump_stack+0x90/0xb4
[  954.426296]  proc_readdir_de+0x29c/0x2a0
[  954.430205]  proc_readdir+0x30/0x40
[  954.433681]  proc_root_readdir+0x34/0x60
[  954.437592]  iterate_dir+0x8c/0x1a8
[  954.441067]  ksys_getdents64+0xa4/0x190
[  954.444890]  __arm64_sys_getdents64+0x28/0x38
[  954.449234]  el0_svc_handler+0x84/0x140
[  954.453057]  el0_svc+0x8/0xc
 

上述/proc根目录是静态定义的proc_dir_entry :fs/proc/root.c

static const struct file_operations proc_root_operations = {
	.read		 = generic_read_dir,
	.iterate_shared	 = proc_root_readdir,
	.llseek		= generic_file_llseek,
};

/*
 * proc root can do almost nothing..
 */
static const struct inode_operations proc_root_inode_operations = {
	.lookup		= proc_root_lookup,
	.getattr	= proc_root_getattr,
};

/*
 * This is the root "inode" in the /proc tree..
 */
struct proc_dir_entry proc_root = {
	.low_ino	= PROC_ROOT_INO, 
	.namelen	= 5, 
	.mode		= S_IFDIR | S_IRUGO | S_IXUGO, 
	.nlink		= 2, 
	.refcnt		= REFCOUNT_INIT(1),
	.proc_iops	= &proc_root_inode_operations, 
	.proc_fops	= &proc_root_operations,
	.parent		= &proc_root,
	.subdir		= RB_ROOT,
	.name		= "/proc",
};

目录的iterate_shared函数是generic_read_dir。

创建proc文件目录接口proc_mkdir:fs/proc/generic.c 

static const struct file_operations proc_dir_operations = {
        .llseek                 = generic_file_llseek,
        .read                   = generic_read_dir,
        .iterate_shared         = proc_readdir,
};


struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
                struct proc_dir_entry *parent, void *data)
{
        struct proc_dir_entry *ent;

        if (mode == 0)
                mode = S_IRUGO | S_IXUGO;

        ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
        if (ent) {
                ent->data = data;
                ent->proc_fops = &proc_dir_operations; -------对应目录默认的f_ops: proc_dir_operations 
                ent->proc_iops = &proc_dir_inode_operations;
                parent->nlink++;
                ent = proc_register(parent, ent);
                if (!ent)
                        parent->nlink--;
        }
        return ent;
}
EXPORT_SYMBOL_GPL(proc_mkdir_data);

struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
                                       struct proc_dir_entry *parent)
{
        return proc_mkdir_data(name, mode, parent, NULL);
}
EXPORT_SYMBOL(proc_mkdir_mode);

struct proc_dir_entry *proc_mkdir(const char *name,
                struct proc_dir_entry *parent)
{
        return proc_mkdir_data(name, 0, parent, NULL);
}
EXPORT_SYMBOL(proc_mkdir);

你可能感兴趣的:(linux,运维,服务器)