相关疑难解决方法(0)

如何从用户空间访问系统调用?

我读了LKD 1中的一些段落, 我无法理解下面的内容:

从用户空间访问系统调用

通常,C库提供对系统调用的支持.用户应用程序可以从标准头中提取函数原型并与C库链接以使用您的系统调用(或者库例程,而该库例程又使用您的系统调用).但是,如果您刚刚编写了系统调用,那么glibc已经支持它是值得怀疑的!

值得庆幸的是,Linux提供了一组用于包装系统调用访问的宏.它设置寄存器内容并发出陷阱指令.这些宏被命名,其中介于0和6之间.该数字对应于传递给系统调用的参数数量,因为宏需要知道预期的参数数量,从而推入寄存器.例如,考虑系统调用,定义为_syscalln()nopen()

long open(const char *filename, int flags, int mode)
Run Code Online (Sandbox Code Playgroud)

在没有显式库支持的情况下使用此系统调用的syscall宏将是

#define __NR_open 5
_syscall3(long, open, const char *, filename, int, flags, int, mode)
Run Code Online (Sandbox Code Playgroud)

然后,应用程序可以简单地调用open().

对于每个宏,有2 + 2×n个参数.第一个参数对应于系统调用的返回类型.第二个是系统调用的名称.接下来是系统调用顺序的每个参数的类型和名称.的__NR_open定义是在<asm/unistd.h>; 它是系统呼叫号码.的_syscall3宏扩展到与联汇编C函数; 程序集执行上一节中讨论的步骤,将系统调用号和参数推送到正确的寄存器中,并发出软件中断以陷入内核.将此宏放在应用程序中是使用open()系统调用所需的全部内容.

让我们编写宏来使用我们精彩的新foo()系统调用,然后编写一些测试代码来展示我们的努力.

#define __NR_foo 283
__syscall0(long, foo)

int main ()
{
        long stack_size;

        stack_size = foo ();
        printf ("The kernel stack size is %ld\n", stack_size);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

是什么 …

linux system-calls

17
推荐指数
2
解决办法
2万
查看次数

如何指示可以使用内联ASM参数*指向*的内存?

考虑以下小功能:

void foo(int* iptr) {
    iptr[10] = 1;
    __asm__ volatile ("nop"::"r"(iptr):);
    iptr[10] = 2;
}
Run Code Online (Sandbox Code Playgroud)

使用gcc,它将编译为

foo:
        nop
        mov     DWORD PTR [rdi+40], 2
        ret
Run Code Online (Sandbox Code Playgroud)

请特别注意,即在第一次写iptriptr[10] = 1根本不会发生:内联汇编nop是在函数的第一件事,只有最后写2(会出现ASM呼叫后)。显然,编译器决定只需要提供其iptr 自身值的最新版本,而不需要提供其指向的内存。

我可以告诉编译器,内存必须是最新的memory,就像这样:

void foo(int* iptr) {
    iptr[10] = 1;
    __asm__ volatile ("nop"::"r"(iptr):"memory");
    iptr[10] = 2;
}
Run Code Online (Sandbox Code Playgroud)

结果为预期的代码:

foo:
        mov     DWORD PTR [rdi+40], 1
        nop
        mov     DWORD PTR [rdi+40], 2
        ret
Run Code Online (Sandbox Code Playgroud)

但是,这太强了,因为它告诉编译器必须写入所有内存。例如,在以下功能中:

void foo2(int* iptr, long* …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc clang inline-assembly

5
推荐指数
1
解决办法
244
查看次数

at&t asm inline c ++问题

我的守则

const int howmany = 5046;
char buffer[howmany];
    asm("lea     buffer,%esi"); //Get the address of buffer
    asm("mov     howmany,%ebx");         //Set the loop number
    asm("buf_loop:");                      //Lable for beginning of loop
    asm("movb     (%esi),%al");             //Copy buffer[x] to al
    asm("inc     %esi");                   //Increment buffer address
    asm("dec     %ebx");                   //Decrement loop count
    asm("jnz     buf_loop");              //jump to buf_loop if(ebx>0)
Run Code Online (Sandbox Code Playgroud)

我的问题

我正在使用gcc编译器.出于某种原因,我的缓冲区/ howmany变量在我的asm眼中是不确定的.我不知道为什么.我只想将缓冲区数组的起始地址移动到esi寄存器中,在将每个元素复制到al寄存器时循环"howmany"次.

c x86 assembly gcc inline-assembly

1
推荐指数
1
解决办法
1444
查看次数

如何从C/C++应用程序进行Linux系统调用,而不使用汇编,并且以独立于CPU的方式?

我期待编写一个程序,需要对进程进行低级别的工作(即使用fork系统调用等).该程序用C++编写,只能在Linux上运行.理想情况下,这将是整个CPU架构(即86,x86_64和ARM)与只不过是重新编译更便携,但我只真正需要x86_64的支持.

由于每个Linux系统调用都需要许多参数并在cpu寄存器中返回许多参数(通常只有1个返回值),因此每个系统调用的C函数包装器很容易实现.另外,因为AFAIK,在内核中实现的系统调用具有相同的参数和返回值,如果是不同的汇编级实现,则可以公开相同的C接口.

这样的事情存在吗?如果是这样,我该如何访问它?

它的文档在哪里(可用函数列表,它们的解释参数以及函数的确切解释)?

c c++ linux assembly system-calls

0
推荐指数
1
解决办法
785
查看次数

标签 统计

assembly ×3

c ×3

gcc ×2

inline-assembly ×2

linux ×2

system-calls ×2

c++ ×1

clang ×1

x86 ×1