Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C syscall()无法接受无效指针_C_System Calls - Fatal编程技术网

C syscall()无法接受无效指针

C syscall()无法接受无效指针,c,system-calls,C,System Calls,我正在研究一种用go编写的动态语言。我使用C允许这种语言访问系统调用(至少对于linux)。C的any类型是void*,因此我认为可以将它们传递到系统调用中。我使用如下代码进行了测试: #include <stdio.h> #include <unistd.h> static inline long int vpsyscall(void* a0, void* a1, void* a2, void* a3) { return syscall(*((int*)a0)

我正在研究一种用go编写的动态语言。我使用C允许这种语言访问系统调用(至少对于linux)。C的
any
类型是
void*
,因此我认为可以将它们传递到系统调用中。我使用如下代码进行了测试:

#include <stdio.h>
#include <unistd.h>

static inline long int vpsyscall(void* a0, void* a1, void* a2, void* a3) {
    return syscall(*((int*)a0), a1, a2, a3);
}

int main() {
    int a_ = 1;
    void* a = &a_;
    int b_ = 1;
    void* b = &b_;
    char* c_ = "hello\n";
    void* c = &c_;
    int d_ = 6;
    void* d = &d_;
    long int ret = tusksyscall(a, b, c, d);
    printf("%ld\n", ret);
}
到控制台

相反,我得到了

-1
这(至少据我所知)意味着错误

奇怪的是,当我传递1个参数(ax)时,它就工作了

int _ax = 39;
void* ax = &_ax;
long int ret = vpsyscall(ax, 0, 0, 0);
printf("%ld\n", ret);

它给我所需的输出(在本例中,只是pid)。那么,这里发生了什么,我如何将void指针传递给系统调用(如果有任何方法的话)?

Linux系统调用接口只接受与指针大小相同的指针或整数值,并且可以安全地转换为它们。但您并没有传递这些对象,而是传递指向它们的指针。例如,不是要求操作系统写入文件描述符1,而是要求操作系统写入文件描述符
0x7fffdeadbef
或本地变量
b
的地址。显然,这不会成功

您需要使用
&
运算符强制转换而不是获取地址

您还可以创建类型为
int
的第一个参数,因为您知道它总是这样

试一试


我认为你把
void*
看作是一种“任意”类型是错误的。它可以是指向任何对象的指针,但不能与该对象互换。要取回对象,必须将指针强制转换到对象的类型并取消引用它。这就是您对
vpsyscall
的第一个参数所做的,这就是它工作的原因,尽管它不必要地复杂。

系统调用应该直接接受整数和指针参数,但您分别传递指向整数的指针和指向指针的指针。这与
put(c)
不打印“Hello”的原因相同。如果您坚持传递
void*
,那么您应该将指针和整数强制转换为该类型,而不是获取它们的地址。思考一下
syscall(1,1,“hello\n”,6)
为什么会起作用,以及
vpsyscall
函数为什么不起作用。这实际上与系统调用本身无关;如果您用任何其他函数替换了
syscall
,问题也会一样。这只是一个对象和一个指向该对象的指针之间的区别,你把它们混在一起了。如果无效指针不起作用,其他解决方案(允许未知类型)会起作用吗?
int _ax = 39;
void* ax = &_ax;
long int ret = vpsyscall(ax, 0, 0, 0);
printf("%ld\n", ret);

static inline long int vpsyscall(int a0, void* a1, void* a2, void* a3) {
    return syscall(a0, a1, a2, a3);
}


int main() {
    vpsyscall(1, (void *)1, "hello", (void *)6);
}