Systemkald i Unix/Linux 1
Operativsystemet Fra proces: OS som værktøjskasse: tilgængelig via systemkald... OS som resurseadministrator, abstrakt/virtuel maskine: CPU: processer, tråde, schedulering I/O: device drivere, filsystemer Lager: virtuelt lager, segmentering 2
Udvalgte POSIX.1 systemkald Beskriver grænseflade mellem OS og applikationer 3
Rettigheder og tilstande Bruger- og OS-aktiviteter har forskellige rettigheder Kernel Mode (x86 ring 0) og User Mode (x86 ring 3) 4
Udførelse af systemkald Et dilemma: En bruger-proces, som skal udføre et systemkald, udføres i User Mode, men systemkaldet skal udføres i Kernel Mode. Mulige løsninger: Skift fra User Mode til Kernel Mode i eksisterende proces. Start en ny kerne-tråd, som udfører systemkaldet. 5
Sikkerhedsproblem Et problem: Bruger-kode må aldrig kunne udføres i Kernel Mode, så en bruger-instruktion, der blot skifter tilstand er farlig En typisk løsning: Brug en specialiseret instruktion som laver et trap 6
[Click] Et problem: Bruger-kode må aldrig kunne udføres i Kernel Mode, så en bruger-instruktion, der blot skifter tilstand er farlig. Kunne man ikke bare...? A... checke at bruger-koden er OK? B... skifte til Kernel Mode og hoppe til samme sted hver gang? C... gå tilbage til User Mode hvis ikke programmet straks hopper til kode i kernen? D... udføre hele systemkaldet i User Mode? E. Ved ikke 7
Re: Traps En intern hændelse for CPU en (ofte en fejl): Implicit: division med 0, lagertilgang, Eksplicit: systemkald (supervisory call / SVC) 8
Udførelse af et systemkald Biblioteksproceduren (kern_func) kaldes ofte for en stub... 9
Udførelse af systemkaldet read read( fd, &buffer, nbytes ) 10
Udførelse af systemkaldet read Kalder en biblioteksprocedure (en stub) for read (trin 1-4)... stub'en ligger i User Space... Stub'en forbereder og udfører trap til kernen (trin 4-5)... skifter til Kernel Mode og fortsætter udførelsen fra fast sted i Kernel Space... Kernen identificerer og udfører read i Kernel Mode (trin 7-8) Kernen returnerer til Stub'en(trin 9)... skifter til User Mode og fortsætter udførelsen i User Space... Stub'en returnerer til kalderen (trin 10-11) 11
Impl. af systemkald i Linux Tilgængelige systemkald, argumenter til trap, defineres i arch/i386/kernel/entry.s include/asm-i386/unistd.h Implementeres i den øvrige kerne-kildetekst f.eks read i fs/read_write.c 12
arch/i386/kernel/entry.s.data ENTRY(sys_call_table).long SYMBOL_NAME(sys_ni_syscall) /* 0.. */.long SYMBOL_NAME(sys_exit).long SYMBOL_NAME(sys_fork).long SYMBOL_NAME(sys_read).long SYMBOL_NAME(sys_write).long SYMBOL_NAME(sys_open) /* 5 */.long SYMBOL_NAME(sys_close)....long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SYMBOL_NAME(sys_vfork) /* 190 */ /* * NOTE!! This doesn't have to be exact - we just have * to make sure we have _enough_ of the "sys_ni_syscall" * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */.rept NR_syscalls-190.long SYMBOL_NAME(sys_ni_syscall).endr 13
include/asm-i386/unistd.h /* * This file contains the system call numbers. */ #define NR_exit 1 #define NR_fork 2 #define NR_read 3 #define NR_write 4 #define NR_open 5 #define NR_close 6... #define NR_sendfile 187 #define NR_getpmsg 188 /*.. */ #define NR_putpmsg 189 /*.. */ #define NR_vfork 190 Linux kernen version 2.2.14 tilbyder 190 systemkald 14
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 15
fs/read_write.c prototype asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 15
fs/read_write.c prototype asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; asmlinkage: struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); argumenter på stak lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 15
fs/read_write.c prototype asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; asmlinkage: struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); argumenter på stak lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) goto: hop, indenfor ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) funktion ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 15
fs/read_write.c prototype asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; asmlinkage: struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); argumenter på stak lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) goto: hop, indenfor ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) funktion ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: label: mål for goto unlock_kernel(); return ret; 15
fs/read_write.c prototype asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; asmlinkage: struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); argumenter på stak lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) locks: ignore goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) goto: hop, indenfor ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) funktion ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: label: mål for goto unlock_kernel(); return ret; 15
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 16
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; critical section 16
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 17
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; allocate/deallocate resource 17
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 18
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 18
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 18
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 18
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 18
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; the real work 18
fs/read_write.c asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); lock_kernel(); ret = -EBADF; file = fget(fd); if (!file) goto bad_file; if (!(file->f_mode & FMODE_READ)) ret = locks_verify_area(flock_verify_read, file->f_dentry->d_inode, file, file->f_pos, count); if (ret) ret = -EINVAL; if (!file->f_op!(read = file->f_op->read)) ret = read(file, buf, count, &file->f_pos); out: fput(file); bad_file: unlock_kernel(); return ret; 19
Tilføjelse af systemkald i Linux int my_gettime(int flag, struct timeval *tv); Skriv aktuel tid i tv og udskriv til skærm hvis flag er TRUE Tilføj definition af systemkald til entry.s og unistd.h Tilføj implementation passende sted i kildeteksten Oversæt og genstart dopsys-linux maskinen med ny kerne 20
diff -Naur -X /root/dontdiff linux-2.2.14/arch/i386/kernel/entry.s onsdag_uge47/ --- linux-2.2.14/arch/i386/kernel/entry.s Mon Sep 9 18:03:12 2002 +++ torsdag_uge44/arch/i386/kernel/entry.s Tue Nov 17 07:31:10 2008 @@ -562,6 +562,7 @@.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SYMBOL_NAME(sys_vfork) /* 190 */ +.long SYMBOL_NAME(sys_my_gettime) /* 191 */ /* * NOTE!! This doesn't have to be exact - we just have @@ -569,6 +570,6 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ -.rept NR_syscalls-190 +.rept NR_syscalls-191.long SYMBOL_NAME(sys_ni_syscall).endr diff -Naur -X /root/dontdiff linux-2.2.14/include/asm-i386/unistd.h onsdag_uge47/ --- linux-2.2.14/include/asm-i386/unistd.h Mon Sep 9 18:03:01 2002 +++ torsdag_uge44/include/asm-i386/unistd.h Tue Nov 17 07:31:50 2008 @@ -195,6 +195,7 @@ #define NR_getpmsg 188 /* some people actually want streams */ #define NR_putpmsg 189 /* some people actually want streams */ #define NR_vfork 190 +#define NR_my_gettime 191 /* #define NR_ugetrlimit 191 SuS compliant getrlimit */ #define NR_mmap2 192 #define NR_truncate64 193 diff -Naur -X /root/dontdiff linux-2.2.14/kernel/time.c torsdag_uge44/kernel/time.c --- linux-2.2.14/kernel/time.c Mon Sep 9 18:04:28 2002 +++ torsdag_uge44/kernel/time.cwed A p r 2 3 0 7 : 3 4 : 2 7 2 0 0 8 @@ -421,3 +421,34 @@ ret = do_adjtimex(&txc); return copy_to_user(txc_p, &txc, sizeof(struct timex))? -EFAULT : ret; + +/**********************************************************************/ +/* implementation of my_gettime system call */ +/**********************************************************************/ + +asmlinkage int sys_my_gettime(int flag, struct timeval *tv) +{ + int write_failed; + struct timeval ktv; + + /* get timeval from global variable xtime */... 21
diff -Naur -X /root/dontdiff linux-2.2.14/arch/i386/kernel/entry.s onsdag_uge47/ --- linux-2.2.14/arch/i386/kernel/entry.s Mon Sep 9 18:03:12 2002 +++ torsdag_uge44/arch/i386/kernel/entry.s Tue Nov 17 07:31:10 2008 @@ -562,6 +562,7 @@.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SYMBOL_NAME(sys_vfork) /* 190 */ +.long SYMBOL_NAME(sys_my_gettime) /* 191 */ /* * NOTE!! This doesn't have to be exact - we just have @@ -569,6 +570,6 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system funktion call. i kernen */ -.rept NR_syscalls-190 +.rept NR_syscalls-191.long SYMBOL_NAME(sys_ni_syscall).endr diff -Naur -X /root/dontdiff linux-2.2.14/include/asm-i386/unistd.h onsdag_uge47/ --- linux-2.2.14/include/asm-i386/unistd.h Mon Sep 9 18:03:01 2002 +++ torsdag_uge44/include/asm-i386/unistd.h Tue Nov 17 07:31:50 2008 @@ -195,6 +195,7 @@ #define NR_getpmsg 188 /* some people actually want streams */ #define NR_putpmsg 189 /* some people actually want streams */ #define NR_vfork 190 +#define NR_my_gettime 191 /* #define NR_ugetrlimit 191 SuS compliant getrlimit */ #define NR_mmap2 192 #define NR_truncate64 193 diff -Naur -X /root/dontdiff linux-2.2.14/kernel/time.c torsdag_uge44/kernel/time.c --- linux-2.2.14/kernel/time.c Mon Sep 9 18:04:28 2002 +++ torsdag_uge44/kernel/time.cwed A p r 2 3 0 7 : 3 4 : 2 7 2 0 0 8 @@ -421,3 +421,34 @@ ret = do_adjtimex(&txc); return copy_to_user(txc_p, &txc, sizeof(struct timex))? -EFAULT : ret; + +/**********************************************************************/ +/* implementation of my_gettime system call */ +/**********************************************************************/ + +asmlinkage int sys_my_gettime(int flag, struct timeval *tv) +{ + int write_failed; + struct timeval ktv; + + /* get timeval from global variable xtime */... Tilføj adressen på den nye 21
diff -Naur -X /root/dontdiff linux-2.2.14/arch/i386/kernel/entry.s onsdag_uge47/ --- linux-2.2.14/arch/i386/kernel/entry.s Mon Sep 9 18:03:12 2002 +++ torsdag_uge44/arch/i386/kernel/entry.s Tue Nov 17 07:31:10 2008 @@ -562,6 +562,7 @@.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SYMBOL_NAME(sys_vfork) /* 190 */ +.long SYMBOL_NAME(sys_my_gettime) /* 191 */ /* * NOTE!! This doesn't have to be exact - we just have @@ -569,6 +570,6 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ -.rept NR_syscalls-190 +.rept NR_syscalls-191 af tabellen.long SYMBOL_NAME(sys_ni_syscall).endr diff -Naur -X /root/dontdiff linux-2.2.14/include/asm-i386/unistd.h onsdag_uge47/ --- linux-2.2.14/include/asm-i386/unistd.h Mon Sep 9 18:03:01 2002 +++ torsdag_uge44/include/asm-i386/unistd.h Tue Nov 17 07:31:50 2008 @@ -195,6 +195,7 @@ #define NR_getpmsg 188 /* some people actually want streams */ #define NR_putpmsg 189 /* some people actually want streams */ #define NR_vfork 190 +#define NR_my_gettime 191 /* #define NR_ugetrlimit 191 SuS compliant getrlimit */ #define NR_mmap2 192 #define NR_truncate64 193 diff -Naur -X /root/dontdiff linux-2.2.14/kernel/time.c torsdag_uge44/kernel/time.c --- linux-2.2.14/kernel/time.c Mon Sep 9 18:04:28 2002 +++ torsdag_uge44/kernel/time.cwed A p r 2 3 0 7 : 3 4 : 2 7 2 0 0 8 @@ -421,3 +421,34 @@ ret = do_adjtimex(&txc); return copy_to_user(txc_p, &txc, sizeof(struct timex))? -EFAULT : ret; + +/**********************************************************************/ +/* implementation of my_gettime system call */ +/**********************************************************************/ + +asmlinkage int sys_my_gettime(int flag, struct timeval *tv) +{ + int write_failed; + struct timeval ktv; + + /* get timeval from global variable xtime */... Juster antal tomme pladser i slutningen 21
diff -Naur -X /root/dontdiff linux-2.2.14/arch/i386/kernel/entry.s onsdag_uge47/ --- linux-2.2.14/arch/i386/kernel/entry.s Mon Sep 9 18:03:12 2002 +++ torsdag_uge44/arch/i386/kernel/entry.s Tue Nov 17 07:31:10 2008 @@ -562,6 +562,7 @@.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SYMBOL_NAME(sys_vfork) /* 190 */ +.long SYMBOL_NAME(sys_my_gettime) /* 191 */ /* * NOTE!! This doesn't have to be exact - we just have @@ -569,6 +570,6 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ -.rept NR_syscalls-190 +.rept NR_syscalls-191.long SYMBOL_NAME(sys_ni_syscall).endr diff -Naur -X /root/dontdiff linux-2.2.14/include/asm-i386/unistd.h onsdag_uge47/ --- linux-2.2.14/include/asm-i386/unistd.h Mon Sep 9 18:03:01 2002 +++ torsdag_uge44/include/asm-i386/unistd.h Tue Nov 17 07:31:50 2008 @@ -195,6 +195,7 @@ #define NR_getpmsg 188 /* some people actually want streams */ #define NR_putpmsg 189 /* some people actually want streams */ #define NR_vfork 190 +#define NR_my_gettime 191 /* #define NR_ugetrlimit 191 SuS compliant getrlimit */ #define NR_mmap2 192 #define NR_truncate64 193 diff -Naur -X /root/dontdiff linux-2.2.14/kernel/time.c torsdag_uge44/kernel/time.c --- linux-2.2.14/kernel/time.c Mon Sep 9 18:04:28 2002 +++ torsdag_uge44/kernel/time.cwed A p r 2 3 0 7 : 3 4 : 2 7 2 0 0 8 @@ -421,3 +421,34 @@ ret = do_adjtimex(&txc); return copy_to_user(txc_p, &txc, sizeof(struct timex))? -EFAULT : ret; + +/**********************************************************************/ +/* implementation of my_gettime system call */ +/**********************************************************************/ + +asmlinkage int sys_my_gettime(int flag, struct timeval *tv) +{ + int write_failed; + struct timeval ktv; + + /* get timeval from global variable xtime */... Annoncér navnet på det nye systemkald 21
diff -Naur -X /root/dontdiff linux-2.2.14/arch/i386/kernel/entry.s onsdag_uge47/ --- linux-2.2.14/arch/i386/kernel/entry.s Mon Sep 9 18:03:12 2002 +++ torsdag_uge44/arch/i386/kernel/entry.s Tue Nov 17 07:31:10 2008 @@ -562,6 +562,7 @@.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */.long SYMBOL_NAME(sys_vfork) /* 190 */ +.long SYMBOL_NAME(sys_my_gettime) /* 191 */ /* * NOTE!! This doesn't have to be exact - we just have @@ -569,6 +570,6 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ -.rept NR_syscalls-190 +.rept NR_syscalls-191.long SYMBOL_NAME(sys_ni_syscall).endr diff -Naur -X /root/dontdiff linux-2.2.14/include/asm-i386/unistd.h onsdag_uge47/ --- linux-2.2.14/include/asm-i386/unistd.h Mon Sep 9 18:03:01 2002 +++ torsdag_uge44/include/asm-i386/unistd.h Tue Nov 17 07:31:50 2008 @@ -195,6 +195,7 @@ #define NR_getpmsg 188 /* some people actually want streams */ #define NR_putpmsg 189 /* some people actually want streams */ #define NR_vfork 190 +#define NR_my_gettime 191 /* #define NR_ugetrlimit 191 SuS compliant getrlimit */ #define NR_mmap2 192 #define NR_truncate64 193 diff -Naur -X /root/dontdiff linux-2.2.14/kernel/time.c torsdag_uge44/kernel/time.c --- linux-2.2.14/kernel/time.c Mon Sep 9 18:04:28 2002 +++ torsdag_uge44/kernel/time.cwed A p r 2 3 0 7 : 3 4 : 2 7 2 0 0 8 @@ -421,3 +421,34 @@ ret = do_adjtimex(&txc); return copy_to_user(txc_p, &txc, sizeof(struct timex))? -EFAULT : ret; + +/**********************************************************************/ +/* implementation of my_gettime system call */ +/**********************************************************************/ + +asmlinkage int sys_my_gettime(int flag, struct timeval *tv) +{ + int write_failed; + struct timeval ktv; + + /* get timeval from global variable xtime */... Tilføj koden for den nye funktion 21
Anvendelse af nyt systemkald Brug generisk stub via syscall-systemkaldet: #include <sys/syscall.h>... syscall(191, 1, &tv);... eller lav stub vha. _syscall-makroen... #include <linux/unistd.h>... _syscall2(int, my_gettime, int, flag, struct timeval *, tv);... my_gettime(1, &tv); 22
Anvendelse af nyt systemkald Brug generisk stub via syscall-systemkaldet: Husk at lave symlink /usr/src/linux til at pege på rette kildetekst $ cd /usr/src #include $ rm <sys/syscall.h> linux... $ ln -s mygettime linux syscall(191, 1, &tv);... eller lav stub vha. _syscall-makroen... #include <linux/unistd.h>... _syscall2(int, my_gettime, int, flag, struct timeval *, tv);... my_gettime(1, &tv); 22
mygettime_test.c #include <stdio.h> #include <stdlib.h> #include <sys/syscall.h> #include <sys/time.h> #include <linux/unistd.h> _syscall2(int, my_gettime, int, flag, struct timeval *, tv); int main() { int val; struct timeval tv; val = syscall(191, 1, &tv); val = my_gettime(1, &tv); val = my_gettime(1, NULL); return 0; tv_sec: 1035982305 tv_usec: 307024 tv_sec: 1035982305 tv_usec: 317024 my_gettime: Cannot write into user space 23
Opsummering Systemkald adskiller ISA-niveauet fra brugerkode nødvendige for at sikre systeminvarianter ( sundhed ) realiseres med traps Case: Linux-systemkald annonceres til brugerkode (unistd.h) opsættes i adressetabel til brug i kernen (entry.s) implementeres i kernen kald i brugerkode skal etableres (syscall, _syscalln) 24