“Linux内核分析”实验四

系统调用(上)

作者:何振豪

原创作品转载请注明出处 http://www.cnblogs.com/scoyer/p/6556391.html 

《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000

 

看了一些关于系统调用的博客和资料,感觉受益匪浅!

 

Linux的运行模式分为内核态和用户态,我们使用操作系统的时候一般在用户态,当我们需要使用系统功能的时候,例如创建文件,创建进程等,需要申请资源,这时候系统就切换内核态帮助我们执行,其中OS接受请求,就会利用系统调用帮助我们实现这个请求。

更专业一点的定义:系统调用是操作系统提供给用户与硬件进行交互的一层接口。

 

为什么需要系统调用呢?

1.让操作系统检查请求合法性,保证操作系统的正常运作;

2.给用户提供方便,毕竟谁也不想一直使用汇编进行编程;

 

先科普一些相关术语:

什么是封装例程(wrapper routine)?

在标准C库函数中,为每个系统调用设置了一个封装例程,当一个用户程序执行一个系统调用的时候,就会调用C函数中的相对应的封装例程。

 

什么是服务例程(service routine)?

实际上系统调用只是一个接口,所需要的系统功能由内核函数去执行,这些执行系统功能的内核函数就是服务例程。

 

以getpid函数为例,简单说是系统调用执行getpid函数时,详细一点就是在用户态执行模式调用getpid这个封装例程,利用系统调用进入内核态执行sys_getpid服务例程。

 

实验的前置知识:想要用汇编进行系统调用的话,需要设置好相应的参数到寄存器中,eax使用来存放系统调用号,每个内核函数都有唯一的编号,实现不同的功能,系统调用号列表可以参考:

http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/syscall_32.tbl

此外ebx,ecx,edx,esi,edi都是用来存放需要的参数的,假设需要的参数如果大于六个的话,那么需要传的是内存的地址,将参数存放在内存中。设置好参数之后,需要使用中断指令进行系统调用,系统的调用的结果会返回到eax寄存器。

 

理论知识介绍完就开始进行实验了,这次实验要做的是使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用。

 

我要实现的系统调用是24号服务例程getuid,这个函数返回的是进程所在的用户id,很简单的一个函数。

下面是c代码:

下面是相应的汇编代码:

执行结果如下图所示:

上面这两个函数执行结果一样,说明调用的是同一个服务例程。

 总结

下面简单描述一下系统调用的过程,这一节先粗略一讲,后面在进行详细叙述每个过程:

1.应用程序调用一个封装例程;

2.封装例程里面产生软中断,开始系统调用;

3.通过系统调用切换到内核态,调用服务例程;

4.调用完毕,关闭中断,返回系统调用;

5.从系统调用退出,从内核态切换到用户态;

 

用下述图片说明:

 参考资料(推荐)

http://wenku.baidu.com/link?url=S5LqsgYWgyLk6nmPnx8o2qfclPwxmqwT_2Jsg2Oe9ihJnSWDWp-XskICK_XxyyCumB8_IdGhVebBSfqrd4GY1zvPUSGrDguIlX-OCaA0d9q

posted @ 2017-03-15 21:00  scoyer  阅读(282)  评论(0编辑  收藏  举报