如何在C / C ++中获取Linux系统调用的输出?

时间:2014-11-09 13:00:42

标签: c++ c linux linux-kernel system-calls

我在Linux内核中添加了一个简单的helloworld系统调用。

sys_helloworld

#include <linux/kernel.h>

asmlinkage long sys_helloworld(void)
{
        printk("Hello world\n");
        return 0;
}

它只会将Hello world打印到内核日志中。

我这样调用了sys_helloworld系统调用:

#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
   long int a = syscall(314); // 314 is the line number of sys_helloworld in syscall table
   printf("System call sys_helloworld returned %ld\n", a);
   return 0;
}

以上程序在内核日志中成功打印Hello world

我的问题:

如何在程序中获取sys_hello(将Hello world打印到内核日志中)的输出?

1 个答案:

答案 0 :(得分:3)

您应该向系统调用添加两个参数:要写入的缓冲区及其大小。然后,您可以使用snprintf()打印您想要的任何字符串。您只需确保使用正确的系统调用定义宏。由于您需要2个参数,因此我们需要SYSCALL_DEFINE2

#include <linux/kernel.h> /* For snprintf() */
#include <sys/syscall.h> /* For SYSCALL_DEFINE* macros */
SYSCALL_DEFINE2(sys_helloworld, char *, buff, size_t, buff_sz)
{
        snprintf(buff, buff_sz, "Hello world\n");
        return 0;
}

为了完整性,并且根据上下文,您可能希望将返回值更改为允许您知道字符串是否被截断的内容。

用户代码可以这样称呼它:

#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
   char buf[32];
   long int a = syscall(314, buf, sizeof(buf));
   printf("System call sys_helloworld returned %ld\n", a);
   printf("buf = %s\n", buf);
   return 0;
}

请注意,使用SYSCALL_DEFINE*宏来定义系统调用通常更好的方式,而不是手动输入asmlinkage long ....,即使对于没有参数的系统调用(您将使用{{1} })。这些宏在SYSCALL_DEFINE0中定义,您应该使用它们。