Linux 内核--系统调用

本文介绍了Linux内核的系统调用,它是用户进程与内核交互的接口,提供硬件抽象,确保系统安全稳定,并实现多任务和虚拟内存。在Linux中,系统调用是访问内核的唯一方式,通过特定的系统调用号识别,通常通过C库函数调用,并通过返回值和errno变量指示成功或错误。最新版Linux kernel-5.18.8包含440个系统调用,强调通用性和稳定性。
摘要由CSDN通过智能技术生成

在现代操作系统中,内核提供了用户进程与内核进行交互的一组接口。这些接口让应用程序受限地访问硬件设备,提供了创建新进程并与已有进程进行通信的机制,也提供了申请操作系统其他资源的能力。

这些接口在应用程序和内核之间扮演了使者的角色,应用程序发出各种请求,而内核负责满足这些请求(或者无法满足时返回一个错误)。实际上提供这些接口主要是为了保证系统稳定可靠,避免应用程序恣意妄行。

与内核通信

系统调用在用户空间进程和硬件设备之间添加了一个中间层。该层主要作用有三个。

首先,它为用户空间提供了一种硬件的抽象接口。举例来说,当需要读写文件的时候,应用程序就可以不去管磁盘类型和介质,甚至不用去管文件所在的文件系统到底是哪种类型。

第二,系统调用保证了系统的稳定和安全。作为硬件设备和应用程序之间的中间人,内核可以基于权限、用户类型和其他一些规则对需要进行的访问进行裁决。举例来说,这样可以避免应用程序不正确地使用硬件设备,窃取其他进程的资源,或做出其他危害系统的事情。

第三,每个进程都运行在虚拟系统中,而在用户空间和系统的其余部分提供这样一层公共接口,也是出于这种考虑。如果应用程序可以随意访问硬件而内核又对此一无所知的话,几乎就没法实现多任务和虚拟内存,当然也不可能实现良好的稳定性和安全性。

在 Linux 中,系统调用是用户空间访问内核的唯一手段﹔除异常和陷入外,它们是内核唯一的合法入口。实际上,其他的像设备文件和/proc之类的方式,最终也还是要通过系统调用进行访问的。而有趣的是,Linux 提供的系统调用却比大部分操作系统都少得多。

要访问系统调用(在 Linux 中常称作 syscall),通常通过C库中定义的函数调用来进行。它们通常都需要定义零个、一个或几个参数(输入)而且可能产生一些副作用,例如,写某个文件或向给定的指针拷贝数据等。系统调用还会通过一个long类型的返回值来表示成功或者错误。通常,但也不绝对,用一个负的返回值来表明错误。返回一个0值通常(当然仍不是绝对的)表明成功。系统调用在出现错误的时候C库会把错误码写人errno全局变量。通过调用perror()库函数,可以把该变量翻译成用户可以理解的错误字符串。

在 Linux 中,每个系统调用被赋予一个系统调用号。这样,通过这个独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就用来指明到底是要执行哪个系统调用;进程不会提及系统调用的名称。

系统调用说明

asmlinkage 限定词,这是一个编译指令,通知编译器仅从栈中提取该函数的参数。

函数返回 long,为了保证 32 位和 64 位系统的兼容,系统调用在用户空间和内核空间有不同的返回值类型,在用户空间为 int,在内核空间为 long。

假设系统调用在内核空间定义为 sys_ioctl,那么该系统调用的用户空间接口为 ioctl

Linux kernel-5.18.8 有 440 个系统调用,这些系统调用讲究通用性,一旦固定,很少修改,保证 Linux 系统的稳定性和兼容性。

/include/linux/syscalls.h

#ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx);
asmlinkage long sys_io_destroy(aio_context_t ctx);
asmlinkage long sys_io_submit(aio_context_t, long,
   struct iocb __user * __user *);
asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
         struct io_event __user *result);
asmlinkage long sys_io_getevents(aio_context_t ctx_id,
    long min_nr,
    long nr,
    struct io_event __user *events,
    struct __kernel_timespec __user *timeout);
asmlinkage long sys_io_getevents_time32(__u32 ctx_id,
    __s32 min_nr,
    __s32 nr,
    struct io_event __user *events,
    struct old_timespec32 __user *timeout);
asmlinkage long sys_io_pgetevents(aio_context_t ctx_id,
    long min_nr,
    long nr,
    struct io_event __user *events,
    struct __kernel_timespec __user *timeout,
    const struct __aio_sigset *sig);
asmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id,
    long min_nr,
    long nr,
    struct io_event __user *events,
    struct old_timespec32 __user *timeout,
    const struct __aio_sigset *sig);
asmlinkage long sys_io_uring_setup(u32 entries,
    struct io_uring_params __user *p);
asmlinkage long sys_io_uring_enter(unsigned int fd, u32 to_submit,
    u32 min_complete, u32 flags,
    const void __user *argp, size_t argsz);
asmlinkage long sys_io_uring_register(unsigned int fd, unsigned int op,
    void __user *arg, unsigned int nr_args);

/* fs/xattr.c */
asmlinkage long sys_setxattr(const char __user *path, const char __user *name,
        const void __user *value, size_t size, int flags);
asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name,
         const void __user *value, size_t size, int flags);
asmlinkage long sys_fsetxattr(int fd, const char __user *name,
         const void __user *value, size_t size, int flags);
asmlinkage long sys_getxattr(const char __user *path, const char __user *name,
        void __user *value, size_t size);
asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name,
         void __user *value, size_t size);
asmlinkage long sys_fgetxattr(int fd, const char __user *name,
         void __user *value, size_t size);
asmlinkage long sys_listxattr(const char __user *path, char __user *list,
         size_t size);
asmlinkage long sys_llistxattr(const char __user *path, char __user *list,
          size_t size);
asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size);
asmlinkage long sys_removexattr(const char __user *path,
    const char __user *name);
asmlinkage long sys_lremovexattr(const char __user *path,
     const char __user *name);
asmlinkage long sys_fremovexattr(int fd, const char __user *name);

/* fs/dcache.c */
asmlinkage long sys_getcwd(char __user *buf, unsigned long size);

/* fs/cookies.c */
asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user *buf, size_t len);

/* fs/eventfd.c */
asmlinkage long sys_eventfd2(unsigned int count, int flags);

/* fs/eventpoll.c */
asmlinkage long sys_epoll_create1(int flags);
asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
    struct epoll_event __user *event);
asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
    int maxevents, int timeout,
    const sigset_t __user *sigmask,
    size_t sigsetsize);
asmlinkage long sys_epoll_pwait2(int epfd, struct epoll_event __user *events,
     int maxevents,
     const struct __kernel_timespec __user *timeout,
     const sigset_t __user *sigmask,
     size_t sigsetsize);

/* fs/fcntl.c */
asmlinkage long sys_dup(unsigned int fildes);
asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags);
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
#if BITS_PER_LONG == 32
asmlinkage long sys_fcntl64(unsigned int fd,
    unsigned int cmd, unsigned long arg);
#endif

/* fs/inotify_user.c */
asmlinkage long sys_inotify_init1(int flags);
asmlinkage long sys_inotify_add_watch(int fd, const char __user *path,
     u32 mask);
asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd);

/* fs/ioctl.c */
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd,
    unsigned long arg);

/* fs/ioprio.c */
asmlinkage long sys_ioprio_set(int which, int who, int ioprio);
asmlinkage long sys_ioprio_get(int which, int who);

/* fs/locks.c */
asmlinkage long sys_flock(unsigned int fd, unsigned int cmd);

/* fs/namei.c */
asmlinkage long sys_mknodat(int dfd, const char __user * filename, umode_t mode,
       unsigned dev);
asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, umode_t mode);
asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag);
asmlinkage long sys_symlinkat(const char __user * oldname,
         int newdfd, const char __user * newname);
asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
      int newdfd, const char __user *newname, int flags);
asmlinkage long sys_renameat(int olddfd, const char __user * oldname,
        int newdfd, const char __user * newname);

/* fs/namespace.c */
asmlinkage long sys_umount(char __user *name, int flags);
asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name,
    char __user *type, unsigned long flags,
    void __user *data);
asmlinkage long sys_pivot_root(const char __user *new_root,
    const char __user *put_old);

/* fs/nfsctl.c */

/* fs/open.c */
asmlinkage long sys_statfs(const char __user * path,
    struct statfs __user *buf);
asmlinkage long sys_statfs64(const char __user *path, size_t sz,
    struct statfs64 __user *buf);
asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf);
asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz,
    struct statfs64 __user *buf);
asmlinkage long sys_truncate(const char __user *path, long length);
asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
#if BITS_PER_LONG == 32
asmlinkage long sys_truncate64(const char __user *path, loff_t length);
asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);
#endif
asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len);
asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode);
asmlinkage long sys_faccessat2(int dfd, const char __user *filename, int mode,
          int flags);
asmlinkage long sys_chdir(const char __user *filename);
asmlinkage long sys_fchdir(unsigned int fd);
asmlinkage long sys_chroot(const char __user *filename);
asmlinkage long sys_fchmod(unsigned int fd, umode_t mode);
asmlinkage long sys_fchmodat(int dfd, const char __user * filename,
        umode_t mode);
asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
        gid_t group, int flag);
asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group);
asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
      umode_t mode);
asmlinkage long sys_openat2(int dfd, const char __user *filename,
       struct open_how *how, size_t siz
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值