1 / 13

Implementing System Calls

Implementing System Calls. CS552 Kartik Gopalan & Dennis Foreman. Steps in writing a system call. Create an entry for the system call in the kernel’s syscall_table User processes trapping to the kernel (through SYS_ENTER or int 0x80) find the syscall function through this table.

pippa
Download Presentation

Implementing System Calls

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Implementing System Calls CS552 Kartik Gopalan & Dennis Foreman

  2. Steps in writing a system call • Create an entry for the system call in the kernel’s syscall_table • User processes trapping to the kernel (through SYS_ENTER or int 0x80) find the syscall function through this table. • Write the system call code as a kernel function • Be careful when reading/writing to user-space • Use copy_to_user or copy_from_user routines • Generate/Use a user-level system call stub • Hides the complexity of making a system call from user applications.

  3. /usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.s390x/arch/x86/kernel/syscall_table.S/usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.s390x/arch/x86/kernel/syscall_table.S ENTRY(sys_call_table) .long sys_restart_syscall /* 0 */ .long sys_exit .long sys_fork .long sys_read … .long sys_pselect6 .long sys_ppoll .long sys_unshare /* 310 */ .long sys_foo /* 311 */ /usr/include/asm/unistd.h /* * This file contains the system call numbers for aplications to use */ #define __NR_restart_syscall 0 #define __NR_exit 1 #define __NR_fork 2 #define __NR_read 3 #define __NR_write 4 … #define __NR_foo 311 #define NR_syscalls 312 /* increment by one */ Step 1: Create a sys_call_table entry

  4. Step 2: Write the system call (1) • No arguments, Integer return value asmlinkage int sys_foo(void) { printk (KERN_ALERT “I am foo. UID is %d\n”, current->uid); return current->uid; } • One primitive argument (in this case an int) asmlinkage int sys_foo(int arg) { printk (KERN_ALERT “This is foo. Argument is %d\n”, arg); return arg; } // Note, no comma after "KERN_ALERT"

  5. Verifying argument passed by user space asmlinkage long sys_close(unsigned int fd) { struct file * filp; struct files_struct *files = current->files; struct fdtable *fdt; spin_lock(&files->file_lock); fdt = files_fdtable(files); if (fd >= fdt->max_fds) goto out_unlock; filp = fdt->fd[fd]; if (!filp) goto out_unlock; … out_unlock: spin_unlock(&files->file_lock); return -EBADF; } Call-by-reference argument User-space pointer sent as argument. Data to be copied back using the pointer. asmlinkage ssize_t sys_read ( unsigned int fd, char __user * buf, size_t count) { … if( !access_ok( VERIFY_WRITE, buf, count)) return –EFAULT; … } Step 2: Write the system call (2)

  6. Example syscall implementation(code inside the kernel) asmlinkage int sys_foo(void) { static int count = 0; printk(KERN_ALERT "Hello World! %d\n", count++); //KERN_ALERT is a logging level return -EFAULT; // what happens to this return value? } EXPORT_SYMBOL(sys_foo);

  7. Step 3: Generate user-level stubUsing your new system call - the new way • Old way macros _syscall0, _syscall1, etc are now obsolete in the new kernels. • New way to invoke a system call is using the syscall(...) library function. • Do a "man syscall" for details. • For instance, for a no-argument system call named foo(), you'll call • ret = syscall(__NR_sys_foo); // Assuming you've defined __NR_sys_foo earlier • For a 1 argument system call named foo(arg), you call • ret = syscall(__NR_sys_foo, arg); • and so on for 2, 3, 4 arguments etc. • For this method, check • http://www.ibm.com/developerworks/linux/library/l-system-calls/

  8. Using your new system call - the new way (contd.) #include <stdio.h> #include <errno.h> #include <unistd.h> // --- note #include <linux/unistd.h> // --- note!!! // define the new syscall number. Standard syscalls are defined in linux/unistd.h int main(void) { int ret; while(1) {// making the system call ret = syscall(__NR_sys_foo); printf("ret = %d errno = %d\n", ret, errno); sleep(1); } return 0; }

  9. Using your new system call - the old way • You can still replicate the old _syscall0, _syscall1 etc assembly code stubs in your user program, but this is really not necessary anymore. • These stubs use the old method of raising "int 0x80" software interrupts • which are found to be quite slow on newer Pentium machines. • But this technique still works for backward compatibility. • For this method, check http://www.linuxjournal.com/article/1145

  10. Using your new system call - the old way(contd.) • _syscall0(type,name) • type : type of return value (e.g. void or int) • name : name of the system call (e.g. foo) • _syscall0(int,foo) • Defines syscall entry point for “asmlinkage int sys_foo(void)” • _syscall1(type,name,type1,arg1) • type and name same as before • type1 : type of first argument • name1 : name of first argument • _syscall1(void,foo,int,arg) • Defines syscall entry point for “asmlinkage void sys_foo(int arg)” • … and similarly for two arguments, three arguments and so on. • For definitions of _syscallN macros, check • include/asm/unistd.h • Also, pay attention to the usage and implementation of __syscall_return macro. What does it do?

  11. Using your new system call - the old way(contd.) #include <stdio.h> #include <errno.h> #include <unistd.h> #include <linux/unistd.h> // define the new syscall number. Standard syscalls are defined in linux/unistd.h // generate a user-level stub _syscall0(int,foo) int main(void) { int ret; while(1) { // making the system call ret = foo(); printf("ret = %d errno = %d\n", ret, errno); sleep(1); } return 0; }

  12. SYSENTER/SYSEXIT Method • This is the newest and fastest of all methods to make system calls in Pentium class machines. • Pentium machines have long supported these new instructions as a faster technique to enter and exit the kernel mode than the old technique based on raising the "int 0x80" software interrupt. Newer linux kernels have apparently adopted this technique. • The details of how this works is quite interesting and I may try to cover this briefly in the class. • Meanwhile you can read about the details in the following links and maybe even try it out using the example code. • http://manugarg.googlepages.com/systemcallinlinux2_6.html • http://www.win.tue.nl/~aeb/linux/lk/lk-4.html • http://manugarg.googlepages.com/aboutelfauxiliaryvectors

  13. Kernel Projects: Gary Nutt, Chapter 5, Part 2 Tons of material online if you Google. Reference

More Related