How do I get the output of a Linux System Call in

2019-08-07 17:24发布

问题:

I've added a simple helloworld system call to my Linux Kernel.

sys_helloworld

#include <linux/kernel.h>

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

It just print out Hello world to the kernel log.

I called sys_helloworld system call like so :

#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;
}

Above program successfully prints Hello world in kernel log.

My Question :

How do I get the output of sys_hello (which prints Hello world to the kernel log) in my program?

回答1:

You should add two arguments to your syscall: a buffer to write to, and its size. Then you can use snprintf() to print whatever string you want. You just have to make sure to use the right syscall definition macro. Since you will want 2 arguments, we need SYSCALL_DEFINE2 here:

#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;
}

For completeness, and depending on the context, you might want to change the return value to something that allows you to know whether the string was truncated or not.

User code could call it like this:

#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;
}

Note that it is generally better style to use the SYSCALL_DEFINE* macros to define your syscall, instead of manually typing in asmlinkage long ...., even for a syscall with no arguments (you would use SYSCALL_DEFINE0). These macros are defined in include/sys/syscall.h, and you should use them.