Add a system call

本文详细介绍了Linux系统调用的执行流程,并通过具体实例展示了open、read、write、ioctl和close等核心系统调用的使用方式。文章还探讨了系统调用在实际开发中的应用,包括字符驱动程序的实现与管理。

kernel/arch/arm/kernel/entry-common.S

get_thread_info tskadr tbl, sys_call_table     @ load syscall table pointerldr ip, [tsk, #TI_FLAGS]        @ check for syscall tracing


    .type   sys_call_table, #objectENTRY(sys_call_table)#include "calls.S"



kernel/arch/arm/kernel/calls.S

/* *  linux/arch/arm/kernel/calls.S * *  Copyright (C) 1995-2005 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * *  This file is included thrice in entry-common.S *//* 0 */     CALL(sys_restart_syscall)        CALL(sys_exit)        CALL(sys_fork_wrapper)        CALL(sys_read)        CALL(sys_write)/* 5 */     CALL(sys_open)        CALL(sys_close)        CALL(sys_ni_syscall)        /* was sys_waitpid */        CALL(sys_creat)        CALL(sys_link)        ....../* 365 */   CALL(sys_recvmmsg)#ifndef syscalls_counted.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls#define syscalls_counted#endif.rept syscalls_padding        CALL(sys_ni_syscall).endr



kernel/arch/arm/include/asm/unistd.h

/* * This file contains the system call numbers. */              #define __NR_restart_syscall        (__NR_SYSCALL_BASE+  0)#define __NR_exit           (__NR_SYSCALL_BASE+  1)#define __NR_fork           (__NR_SYSCALL_BASE+  2)#define __NR_read           (__NR_SYSCALL_BASE+  3)#define __NR_write          (__NR_SYSCALL_BASE+  4)#define __NR_open           (__NR_SYSCALL_BASE+  5)#define __NR_close          (__NR_SYSCALL_BASE+  6)                    /* 7 was sys_waitpid */#define __NR_creat          (__NR_SYSCALL_BASE+  8)#define __NR_link           (__NR_SYSCALL_BASE+  9)#define __NR_unlink         (__NR_SYSCALL_BASE+ 10)#define __NR_execve         (__NR_SYSCALL_BASE+ 11)#define __NR_chdir          (__NR_SYSCALL_BASE+ 12)#define __NR_time           (__NR_SYSCALL_BASE+ 13)#define __NR_mknod          (__NR_SYSCALL_BASE+ 14)#define __NR_chmod          (__NR_SYSCALL_BASE+ 15)#define __NR_lchown         (__NR_SYSCALL_BASE+ 16)                      



kernel/ipc/syscall.c



kernel/include/linux/syscalls.h

asmlinkage long sys_lseek(unsigned int fd, off_t offset,              unsigned int origin);asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,            unsigned long offset_low, loff_t __user *result,            unsigned int origin);asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count);asmlinkage long sys_readahead(int fd, loff_t offset, size_t count);asmlinkage long sys_readv(unsigned long fd,              const struct iovec __user *vec,              unsigned long vlen);asmlinkage long sys_write(unsigned int fd, const char __user *buf,              size_t count);


kernel/System.map 

c02c2568 T sys_closec02c262c T fd_installc02c267c T do_sys_openc02c27d0 T sys_openatc02c27e4 T sys_openc02c280c T sys_creatc02c2828 t __dentry_openc02c2a7c T dentry_openc02c2b0c T nameidata_to_filpc02c2b6c T lookup_instantiate_filpc02c2c48 T sys_fallocatec02c2ca4 t chown_commonc02c2d34 T sys_fchownc02c2d94 T sys_fchmodc02c2e40 T sys_lchownc02c2ec0 T sys_fchownatc02c2f4c T sys_chownc02c2fcc T sys_fchmodatc02c3088 T sys_chmodc02c30a8 T sys_chrootc02c313c T sys_fchdirc02c31b4 T sys_chdir


kernel/fs/open.c:

/* * Install a file pointer in the fd array. * * The VFS is full of places where we drop the files lock between * setting the open_fds bitmap and installing the file in the file * array.  At any such point, we are vulnerable to a dup2() race * installing a file in the array before us.  We need to detect this and * fput() the struct file we are about to overwrite in this case. * * It should never happen - if we allow dup2() do it, _really_ bad things * will follow. */     void fd_install(unsigned int fd, struct file *file){    struct files_struct *files = current->files;    struct fdtable *fdt;    spin_lock(&files->file_lock);    fdt = files_fdtable(files);    BUG_ON(fdt->fd[fd] != NULL);    rcu_assign_pointer(fdt->fd[fd], file);    spin_unlock(&files->file_lock);}     EXPORT_SYMBOL(fd_install);     long do_sys_open(int dfd, const char __user *filename, int flags, int mode){    char *tmp = getname(filename);    int fd = PTR_ERR(tmp);         if (!IS_ERR(tmp)) {        fd = get_unused_fd_flags(flags);        if (fd >= 0) {            struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);            if (IS_ERR(f)) {                put_unused_fd(fd);                fd = PTR_ERR(f);            } else {                fsnotify_open(f->f_path.dentry);                fd_install(fd, f);            }        }        putname(tmp);    }    return fd;}     SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode){    long ret;         if (force_o_largefile())        flags |= O_LARGEFILE;         ret = do_sys_open(AT_FDCWD, filename, flags, mode);    /* avoid REGPARM breakage on x86: */    asmlinkage_protect(3, ret, filename, flags, mode);    return ret;}     SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,        int, mode){    long ret;         if (force_o_largefile())        flags |= O_LARGEFILE;         ret = do_sys_open(dfd, filename, flags, mode);    /* avoid REGPARM breakage on x86: */    asmlinkage_protect(4, ret, dfd, filename, flags, mode);    return ret;}

访问字符驱动的系统调用流程:open,read , write , ioctl和close等系统调用通过输入的字符设备文件指向该设备文件驱动代码中的相应函数。

static struct file_operations query_fops ={    .owner = THIS_MODULE,    .open = my_open,    .release = my_close,    .ioctl = my_ioctl,    .read = my_read,    .write = my_write};

 I/O Control in Linux



Adding A System Call


http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-5.html


http://www.tldp.org/LDP/lkmpg/2.4/html/x939.html


http://www.cmpe.boun.edu.tr/courses/cmpe322/summer2012/Tutorials/Kernel_Compilation_and_System_Call_Tutorial_v3.2.2.pdf


Linux Kernel architecture for device drivers


系统调用执行过程示意图


API: open , close , read , write 例子


现在我在完成xv6相关实验,请根据实验指南给我详细的实验指导,具体到每一个步骤,以下是实验指南: System call tracing (moderate) In this assignment you will add a system call tracing feature that may help you when debugging later labs. You'll create a new trace system call that will control tracing. It should take one argument, an integer "mask", whose bits specify which system calls to trace. For example, to trace the fork system call, a program calls trace(1 << SYS_fork), where SYS_fork is a syscall number from kernel/syscall.h. You have to modify the xv6 kernel to print out a line when each system call is about to return, if the system call's number is set in the mask. The line should contain the process id, the name of the system call and the return value; the number of times the system call is traced; you don't need to print the system call arguments. The trace system call should enable tracing for the process that calls it and any children that it subsequently forks, but should not affect other processes. We provide a trace user-level program that runs another program with tracing enabled (see user/trace.c). When you're done, you should see output like this: $ trace 32 grep hello README 3: syscall read(trace counts: 1) -> 1023 3: syscall read(trace counts: 2) -> 961 3: syscall read(trace counts: 3) -> 321 3: syscall read(trace counts: 4) -> 0 $ $ trace 2147483647 grep hello README 5: syscall trace(trace counts: 1) -> 0 5: syscall exec(trace counts: 1) -> 3 5: syscall open(trace counts: 1) -> 3 5: syscall read(trace counts: 5) -> 1023 5: syscall read(trace counts: 6) -> 961 5: syscall read(trace counts: 7) -> 321 5: syscall read(trace counts: 8) -> 0 5: syscall close(trace counts: 1) -> 0 $ $ grep hello README $ $ trace 2 usertests forkforkfork usertests starting 9: syscall fork(trace counts: 1) -> 10 test forkforkfork: 9: syscall fork(trace counts: 2) -> 11 11: syscall fork(trace counts: 3) -> 12 12: syscall fork(trace counts: 4) -> 13 12: syscall fork(trace counts: 5) -> 14 13: syscall fork(trace counts: 6) -> 15 ... $ In the first example above, trace invokes grep tracing just the read system call. The 32 is 1<<SYS_read. In the second example, trace runs grep while tracing all system calls; the 2147483647 has all 31 low bits set. In the third example, the program isn't traced, so no trace output is printed. In the fourth example, the fork system calls of all the descendants of the forkforkfork test in usertests are being traced. Your solution is correct if your program behaves as shown above (though the process IDs may be different). Meanwhile, all of these examples show how many times these system calls were traced. Some hints: Add $U/_trace to UPROGS in Makefile Run and you will see that the compiler cannot compile user/trace.c, because the user-space stubs for the system call don't exist yet: add a prototype for the system call to user/user.h, a stub to user/usys.pl, and a syscall number to kernel/syscall.h. The Makefile invokes the perl script user/usys.pl, which produces user/usys.S, the actual system call stubs, which use the RISC-V ecall instruction to transition to the kernel. Once you fix the compilation issues, run ; it will fail because you haven't implemented the system call in the kernel yet. make qemutrace 32 grep hello README Add a sys_trace() function in kernel/sysproc.c that implements the new system call by remembering its argument in a new variable in the proc structure (see kernel/proc.h). The functions to retrieve system call arguments from user space are in kernel/syscall.c, and you can see examples of their use in kernel/sysproc.c. Modify fork() (see kernel/proc.c) to copy the trace mask from the parent to the child process. Modify the syscall() function in kernel/syscall.c to print the trace output. You will need to add an array of syscall names to index into. You may need to add an array in kernel/syscall.c to count the number of times the system call is traced. If a test case passes when you run it inside qemu directly but you get a timeout when running the tests using make grade, try testing your implementation on Athena. Some of tests in this lab can be a bit too computationally intensive for your local machine (especially if you use WSL).
最新发布
11-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值