系统调用的解释

来源:互联网 发布:收单数据保密协议 编辑:程序博客网 时间:2024/06/06 03:51

http://bbs.chinaunix.net/thread-1917458-3-1.html

1,系统调用只是进程状态发生切换,并没有进程之间的切换,当调用系统调用时,只是一个进程从用户太到内核态的转换,而且还是要保存进程在用户态的各个寄存器的值,因为从内核态返回的时候不能保证能返回到这个进程中.从用户态传递参数到系统调用在x86中是通过寄存器传递的.

2,每个进程都有两个栈:用户态的栈和核心态的栈。在什么态下运行,就用相应的栈

3,要明白 进程切换 与  进程上下文切换的 区别 ?
进程上下文切换就是 cpu寄存器,内存栈,内存映射都发生切换。 用户态和核心态之间就会发生,当然进程间切换也是这种情况。
进程切换是从一个进程切换的到另一个进程。

4,当进程调用系统调用或者发生中断时,CPU从用户模式(用户态)切换成内核模式(内核态),此时,无论是系统调用程序还是中断服务程序,都处于当前进程的上下文中,并没有发生进程上下文切换。
当系统调用或中断处理程序返回时,CPU要从内核模式切换回用户模式,此时会执行操作系统的调用程序。如果发现就需队列中有比当前进程更高的优先级的进程,则会发生进程切换:当前进程信息被保存,切换到就绪队列中的那个高优先级进程;否则,直接返回当前进程的用户模式,不会发生上下文切换。

5,每个进程都拥有两个堆栈:用户空间的堆栈和内核空间堆栈
用户进程:执行用户空间的代码的程序,使用用户堆栈
系统进程:执行内核空间代码(系统调用或中断)的程序,使用内核堆栈(系统堆栈)
这里的用户进程和系统进程使用同一个PCB,他们并不是两个实体进程,而是同一个进程的两个侧面。当调用系统调用或发生中断时,CPU切换到内核态,用户进程“变身”系统进程,此时的寄存器上下文保存在系统进程的堆栈上,以便系统调用返回后的恢复。


1,用户态

pid_t
__getpid (void)
{
#ifdef NOT_IN_libc
  INTERNAL_SYSCALL_DECL (err);
  pid_t result = INTERNAL_SYSCALL (getpid, err, 0);
#else
  pid_t result = THREAD_GETMEM (THREAD_SELF, pid);
  if (__builtin_expect (result <= 0, 0))
    result = really_getpid (result);
#endif
  return result;
}

Sysdep.h (sysdeps\unix\sysv\linux\i386):

# define INTERNAL_SYSCALL(name, err, nr, args...) \
  ({      \
    register unsigned int resultvar;      \
    EXTRAVAR_##nr      \
    asm volatile (      \
    LOADARGS_##nr      \
    "movl %1, %%eax\n\t"      \
    "int $0x80\n\t"      \
    RESTOREARGS_##nr      \
    : "=a" (resultvar)      \
    : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");     \

    (int) resultvar; })


2,内核态

1)ISR定义

calls.S (arch\arm\kernel):   //todo

/* 0 */ CALL(sys_restart_syscall)
CALL(sys_exit)
CALL(sys_fork)
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)


2)ISR的实现

Syscalls.h (include\linux):

#define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0);\
asmlinkage long sys_##sname(void)


#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__)


SYSCALL_DEFINE0(getgid)
{
/* Only we change this so SMP safe */
return from_kgid_munged(current_user_ns(), current_gid());
}



0 0
原创粉丝点击