简体   繁体   English

_syscallN宏在哪里进入 <linux/unistd.h> ?

[英]where did the _syscallN macros go in <linux/unistd.h>?

It used to be the case that if you needed to make a system call directly in linux without the use of an existing library, you could just include <linux/unistd.h> and it would define a macro similar to this: 过去的情况是,如果你需要在不使用现有库的情况下直接在linux中进行系统调用,你可以只包含<linux/unistd.h> ,它将定义一个类似于此的宏:

#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
  : "=a" (__res) \
  : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
      "d" ((long)(arg3))); \
if (__res>=0) \
  return (type) __res; \
errno=-__res; \
return -1; \
}

Then you could just put somewhere in your code: 然后你可以把代码放在你的代码中:

_syscall3(ssize_t, write, int, fd, const void *, buf, size_t, count);

which would define a write function for you that properly performed the system call. 这将为您正确执行系统调用定义一个write函数。

It seems that this system has been superseded by something (i am guessing that "[vsyscall]" page that every process gets) more robust. 似乎这个系统已经被某些东西所取代(我猜测每个进程得到的“[vsyscall]”页面更强大)。

So what is the proper way (please be specific) for a program to perform a system call directly on newer linux kernels? 那么一个程序直接在较新的Linux内核上执行系统调用的正确方法(具体而言)是什么? I realize that I should be using libc and let it do the work for me. 我意识到我应该使用libc并让它为我工作。 But let's assume that I have a decent reason for wanting to know how to do this :-). 但是我们假设我有一个很好的理由想要知道如何做到这一点:-)。

OK, So I looked into it further since I didn't get much of a response here, and found some good information. 好的,所以我进一步研究了一下,因为我没有得到很多回复,并找到了一些很好的信息。 First when an application is launched in linux, in addition to the traditional argc, argv, envp parameters. 首先是在linux上启动应用程序,除了传统的argc,argv,envp参数。 There is another array passed with some more data called auxv. 还有另一个数组传递了一些名为auxv的数据。 See here for details. 详情请见此处

One of these key/value pairs has a key equivalent to AT_SYSINFO . 其中一个键/值对具有与AT_SYSINFO等效的键。 Defined in either /usr/include/asm/auxvec.h or /usr/include/elf . /usr/include/asm/auxvec.h/usr/include/elf

The value associated with this key is the entry point to the system call function (in the "vdso" or "vsyscall" page mapped into every process. 与此键关联的值是系统调用函数的入口点(在映射到每个进程的“vdso”或“vsyscall”页面中)。

You could just replace the traditional int 0x80 or syscall instructions with a call to this address and it would actually do the system call. 您可以通过调用此地址来替换传统的int 0x80syscall指令,它实际上会进行系统调用。 Unfortunately, this is ugly. 不幸的是,这很难看。 So the libc folks come up with a nice solution. 所以libc人员提出了一个很好的解决方案。 When they allocate the TCB and assign it to the gs segment. 当他们分配TCB并将其分配给gs段时。 They put the value of AT_SYSINFO in some fixed offset in the TCB (unfortunately it isn't fixed across versions so you can't rely on the offset being a the same constant always). 他们将AT_SYSINFO的值放在TCB中的某个固定偏移量中(遗憾的是,它不是跨版本固定的,所以你不能总是依赖于偏移是一个相同的常量)。 So instead of a traditional int 0x80 you can just say call *%gs:0x10 which will call the system call routine found in the vdso section. 因此,您可以只call *%gs:0x10而不是传统的int 0x80 ,这将调用vdso部分中的系统调用例程。

I suppose the goal here is to make writing libc easier. 我想这里的目标是让libc更容易编写。 This allows the libc guys to write one block of code to deal with system calls and not have to worry about it ever again. 这允许libc人员编写一个代码块来处理系统调用,而不必再担心它。 The kernel guys can change how system calls are done at any point in time, they just need to change the contents of the vdso page to use the new mechanism and it's good to go. 内核人员可以在任何时间点改变系统调用的方式,他们只需要更改vdso页面的内容以使用新机制,这样做很好。 In fact, you wouldn't need to even recompile your libc! 实际上,您甚至不需要重新编译您的libc! However, this does make things a pain in the butt for us people writing inline assembly and trying to play with the things under the hood. 然而,这确实让我们的人们在编写内联汇编并尝试使用引擎盖下的东西时会感到痛苦。

Fortunately the old way still works too if you really want to do things manually :-). 幸运的是,如果你真的想手动做事,旧的方式仍然有效:-)。

EDIT: one thing I've noticed with my experiements is that AT_SYSINFO doesn't seem to be given to the program on my x86_64 box ( AT_SYSINFO_EHDR is, but i'm not sure how to make use of that yet). 编辑:我注意到的一件事我的经验是AT_SYSINFO似乎没有给我的x86_64盒子上的程序( AT_SYSINFO_EHDR是,但我不知道如何使用它)。 So I'm not 100% sure how the address of the system call function is determined in this situation. 所以我不能100%确定在这种情况下如何确定系统调用函数的地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM