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());
}