Chinaunix首页 | 论坛 | 博客
  • 博客访问: 570833
  • 博文数量: 61
  • 博客积分: 2438
  • 博客等级: 大尉
  • 技术积分: 871
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-28 08:04
文章分类
文章存档

2013年(1)

2012年(8)

2011年(15)

2010年(37)

分类: LINUX

2012-07-15 08:22:28

几个基本的关系:
1、系统调用 & API
应用程序编程接口(API)是一个函数定义,例如常见的sysinfo(),getpid(),open()等函数,这些函数说明了如何获得一个给定的服务;
系统调用是通过软中断向内核发出一个明确的请求。
有些API的实现调用了多组系统调用,而有些则不需要内核提供信息,就不用系统调用。
2、系统调用 & 系统命令
系统命令相对于API高一层,每个系统命令都是一个可执行程序,例如:ls等,这些命令都使用了系统调用。
3、系统调用 & 内核函数
内核函数与普通函数在形式上没有什么区别,只不过前者在内核实现,需要满足一些内核编程的要求;
系统调用是用户进入内核的接口层,它本身并非内核函数,它由内核函数实现。

进入内核后,不同的系统调用调用对应的内核函数,这些函数被称为系统调用的服务例程,例如getpid()实际调用的服务例程为sys_getpid()。现在用SYSCALL_DEFINE0代替。

点击(此处)折叠或打开

  1. #define SYSCALL_DEFINE0(name) asmlinkage long sys_##name(void)
现在来以sysinfo()系统调用为例来分析它的执行过程。
a、用户态下的sysinfo()函数
b、经过libc库的封装
c、经过int 0×80陷入内核
由硬件完成。
d、system_call处理找到对应的服务例程

点击(此处)折叠或打开

  1. ENTRY(system_call)
  2.         RING0_INT_FRAME # can't unwind into user space anyway
  3.         pushl %eax # save orig_eax
  4.         CFI_ADJUST_CFA_OFFSET 4
  5.         SAVE_ALL
  6.         GET_THREAD_INFO(%ebp)
  7.                                         # system call tracing in operation / emulation
  8.         testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
  9.         jnz syscall_trace_entry
  10.         cmpl $(nr_syscalls), %eax
  11.         jae syscall_badsys
  12. syscall_call:
  13.         call *sys_call_table(,%eax,4)
  14.         movl %eax,PT_EAX(%esp) # store the return value
  15. syscall_exit:
  16.             ......
首先保存系统调用号%eax;
SAVE_ALL:将系统调用的参数压到内核栈中.
e、经过上面的宏处理后到函数 SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info)

点击(此处)折叠或打开

  1. SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info)
  2. {
  3.         struct sysinfo val;

  4.         do_sysinfo(&val);

  5.         if (copy_to_user(info, &val, sizeof(struct sysinfo)))
  6.                 return -EFAULT;

  7.         return 0;
  8. }

该函数首先执行do_sysinfo()函数去填充val结构体,然后调用copy_to_user()函数将数据拷贝到用户态缓冲区中。

总结一下:系统调用首先通过libc库分装,然后通过int 0×80陷入内核,system_call处理,内核函数的实现,放回数据给用户。

其中有些细节没有说到,需要对应代码去一步步分析,例如上面提到的SAVE_ALL这个宏通过反汇编编译内核后的vmlinuz文件,在system_call处可以看到SAVE_ALL的具体执行过程。

转自:

阅读(3666) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~