设为首页 收藏本站
查看: 1289|回复: 0

[经验分享] 用户态调用Xen超级调用与Linux内核系统调用

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-10-11 13:34:03 | 显示全部楼层 |阅读模式
一、从用户态访问系统调用
通常,系统调用靠C库支持。用户程序通过包含标准头文件并和C库链接,就可以使用系统调用。但如果你仅仅写出系统调用,glibc库恐怕并不提供支持。  这里有一个好消息还有一个坏消息,好消息是Linux本身提供了一组宏定义linux/include/asm-x86_64/unistd.h文件中。坏消息是在2.6.20之后的内核版本取消了这一系列的宏,导致一开始编译源文件的时候出错,最后在2.6.18中找到了这段代码。其实这段汇编主要的作用就是将系统调用号传递给EAX寄存器,同时将从EAX寄存器取出返回值。

//test.c
#include <stdio.h>
#include <syscall.h>
#include <linux/errno.h>
#include <errno.h>

#define __NR_foo 312
#define MAX_ERRNO 127
#define __syscall &quot;syscall&quot;
#define __syscall_clobber &quot;r11&quot;,&quot;rcx&quot;,&quot;memory&quot;
#define __syscall_return(type,res)\
do{\
if((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)){\
errno = -res;\
res = -1;\
}\
return (type)(res);\
}while(0)
#define _syscall0(type,name)\
type name(void){\
long __res;\
__asm__ volatile(__syscall\
: &quot;=a&quot; (__res)\
: &quot;0&quot; (__NR_##name) : __syscall_clobber );\
__syscall_return(type,__res);\
}
_syscall0(long,foo)
int main(int argc,char** argv)
{
long stack_size = 0;
stack_size = foo();
if(stack_size == -1)
perror(&quot;ERROR&quot;);
printf(&quot;The kernel stack size is %ld\n&quot;,stack_size);
return 0;
}
Output: The kernel stack size is 8192

  这里面有几点需要注意。
  (1)由于我所编译的环境的内核版本是3.2.6,而之前也已经介绍过在2.6.20之后unistd.h文件中不再存在有这些宏,因此宏需要自己声明。上面的宏声明是我从2.6.18内核中拷贝过来的。
  (2)除此之外还会遇到一个宏__syscall_return(type,res)用于返回系统调用执行后的返回&#20540;。
  (3)在_syscallX这一系列宏当中存在一个__syscall宏,在源文件的开始定义为“syscall”,曾经试图去找它的定义,但是没有发现。需要说明的是,在我最初用“int $0x80”而不是“syscall”的时候,系统调用不成功。ERROR返回错误:Dad Address
  (4)在声明_syscall0(long,foo)后面没有分号。
  下面的例子是从网上发现的。可以看到通过函数syscall将系统调用号传递进去。这样调用系统调用更方便。

//test1.c
#include <stdio.h>
#include <asm/unistd_64.h>
#include <syscall.h>
#include <sys/syscall.h>
#define __NR_foo 312
int main(int argc,char** argv)
{
long ret = 0;
ret = syscall(__NR_foo);
printf(&quot;Thread Stack Size is %ld\n&quot;,ret);
return 0;
}

Output: Thread Stack Size is 8192


二、从用户态访问超级调用
以下是在网上发现的一个用户态调用Xenhypervisor的例子。该例子中类&#20284;上面系统调用在Xen中新添加了一个超级调用。
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <xenctrl.h>
#include <xen/sys/privcmd.h>

#define __HYPERVISOR_print_string 39

int main(int argc,char** argv)
{
int fd = 0;
int ret = 0;
char* message = NULL;
if(argc != 2)
{
printf(&quot;Please input one parameter!\n&quot;);
return -1;
}
message = (char*)malloc(sizeof(char) * strlen(argv[1] + 1));
if (message == NULL) {
printf(&quot;malloc failed&quot;);
return -1;
}
strcpy(message,argv[1]);
privcmd_hypercall_t hcall = {__HYPERVISOR_print_string, {message,0,0,0,0}};
fd = open(&quot;/proc/xen/privcmd&quot;,O_RDWR);
if(fd < 0)
{
perror(&quot;open&quot;);
exit(1);
}
else
printf(&quot;fd=%d\n&quot;,fd);
ret = ioctl(fd,IOCTL_PRIVCMD_HYPERCALL,&hcall);
perror(&quot;ioctl err&quot;);
printf(&quot;ret = %d\n&quot;,ret);

close(fd);
return 0;
}

  之后便以Xen,重新加载Xen hypervisor,在xm dmesg命令下即可查看hypercall运行结果。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-125475-1-1.html 上篇帖子: xen安装及配置笔记 下篇帖子: xen kdb代码分析点滴
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表