码迷,mamicode.com
首页 > 其他好文 > 详细

系统调用

时间:2016-03-19 16:00:46      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:

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

 

一、用户态、内核态和中断

 技术分享技术分享

 

技术分享技术分享

 

二、系统调用概述

1、系统调用的意义

   操作系统为用户态进程与硬件设备进行交互提供了一组接口——系统调用
?·把用户从底层的硬件编程中解放出来
?·极大的提高了系统的安全性
?·使用户程序具有可移植性

 

2、API和系统调用

  ·应用编程接口(application program interface, API) 和系统调用是不同的
?  API只是一个函数定义
?  系统调用通过软中断向内核发出一个明确的请求
?·Libc库定义的一些API引用了封装例程(wrapper routine,唯一目的就是发布系统调用)
?  一般每个系统调用对应一个封装例程
?  库再用这些封装例程定义出给用户的API

   ·不是每个API都对应一个特定的系统调用。
?  API可能直接提供用户态的服务
?  如,一些数学函数
?  一个单独的API可能调用几个系统调用
?  不同的API可能调用了同一个系统调用
?·返回值
?  大部分封装例程返回一个整数,其值的含义依赖于相应的系统调用
?  -1在多数情况下表示内核不能满足进程的请求
?  Libc中定义的errno变量包含特定的出错码

3、应用程序、封装例程、系统调用处理程序及系统调用服务例程之间的关系

  技术分享

三、使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用(源自网络)

选择sysinfo库函数116号系统调用

库函数API代码百度自网络:

 

#include

#include

intmain(void)

{

structsysinfo info;

if(sysinfo(&info) < 0) 

{

perror( sysinfofailed );

return-1;

}

printf( uptime   %ld , info.uptime  );

printf( loads %.2f, %.2f,%.2f ,

     (double)info.loads[0] / (1<< SI_LOAD_SHIFT),

 (double)info.loads / (1 <<SI_LOAD_SHIFT),

 (double)info.loads / (1 <<SI_LOAD_SHIFT));

printf( totalram %ld , info.totalram );

printf( freeram  %ld , info.freeram );

printf( sharedram %ld ,info.sharedram);

printf( bufferram %ld ,info.bufferram);

printf( totalswap %ld ,info.totalswap);

printf( freeswap %ld , info.freeswap );

printf( procs    %d , info.procs   );

printf( totalhigh %ld ,info.totalhigh);

printf( freehigh %ld , info.freehigh );

printf( mem_unit %d ,  info.mem_unit);

 

return0;

}



编译运行程序得到系统信息结果

给出了总的可用的内存大小,还未被使用的内存大小,共享的存储器的大小,缓冲区大小,交换区大小,还可用的交换区大小, 当前进程数目等数据

C代码中嵌入汇编代码

 

编写嵌入汇编的版本

asm volatile( mov $0,%%ebx mov $0x80,%%eax ...);

事实上在系统调用时,system_call是linux系统调用的入口点。每个系统调用至少有一个参数,那就是eax,它负责传递系统调用号,同时获取返回值。

除了eax外,还允许至多6个参数,分别是ebx,ecx,edx,esi,edi,ebp。

另一方面,容易观察到,实际上time()函数除了自身的传入系统调用号(同时接收返回值)外,还传入了一个参数NULL。

结合上面的叙述,应该可以猜到,其实代码 mov $0,%eax 是相当于向ebx传入了一个参数NULL,也就是0。

同理,对于sysinfo这个库函数API,它也有一个返回值,表示是否成功,并且传递进来一个参数sys_info来接收系统的相关信息。因此,我们可以编写下面的代码:

// syscall_asm.c#include #include .h>int main() { struct sysinfo sys_info; int error; //error = sysinfo(&sys_info); asm volatile( movl %1, %%ebx movl $0x74, %%eax // sysinfo 的系统调用号是 116 所以十六进制为 0x74 int $0x80 movl %?x, %0 : =m (error) // eax来负责传递返回值,我们同样用error来接收 : b (&sys_info) // sysinfo的地址作为参数,传递进ebx中作为参数被修改接收系统信息 ); printf( code error=%d ,error); printf( Uptime = %lds Load: 1 min%ld / 5 min %ld / 15 min %ld RAM: total %ld / free %ld / shared%ld Memory in buffers = %ld Swap: total%ld / free%ld Number of processes = %d , sys_info.uptime, sys_info.loads[0], sys_info.loads, sys_info.loads, sys_info.totalram, sys_info.freeram, sys_info.sharedram, sys_info.bufferram, sys_info.totalswap, sys_info.freeswap, sys_info.procs); return 0;}

所以,最后的执行结果是一样的

 

系统调用

标签:

原文地址:http://www.cnblogs.com/qindingtao/p/5295118.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!