mirnalim
asked on
passing a function pointer through systam call
Hi,
I would like to pass a function pointer to a function returning a void and receiving one void* argument, i.e
void (*ptr_to_func) (void*)
as an argument to a system call. This is for linux 2.6.16 kernel.
The system call is called nb_request. I compiled the system call into the kernel image. The system call is:
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/sched.h>
#include <asm/current.h>
asmlinkage int sys_nb_request(int num, void (*nb_handler) (void *), void *handler_arg) {
printk(KERN_INFO "The number passed is %d.\n", num);
/* do something with current */
return 1;
}
The user space program that calls the system call, called invoker1.c, is:
#define __NR_nb_request 312
_syscall3(int, nb_request, int, num, void (*) (void *), nb_handler, void *, handler_arg);
void my_handler(void *p);
int main(int argc, char * argv){
void *a;
int j=8;
a =&j;
printf("a points to value %d\n", *((int *)a));
fprintf(stdout,"Executing system call... ");
nb_request(5, &my_handler, a);
fprintf(stdout,"Finished now\n");
return 0;
}
void my_handler(void *p)
{
//does something with p
}
My problem is that the compilation of the user-space program dies at line:
_syscall3(int, nb_request, int, num, void (*) (void *), nb_handler, void *, handler_arg);
and this is because I don't know how to define the pointer to a function in the _syscallN macro.
I'm using User Mode Linux, and I compile with
gcc -o invoke1 invoker.c -I./include
and invoker.c is placed in the root directory of the kernel tree.
Can someone, please, tell me how make this work?! I've been searching the web, but could not find anything except how to pass variables or void*
Mirna
I would like to pass a function pointer to a function returning a void and receiving one void* argument, i.e
void (*ptr_to_func) (void*)
as an argument to a system call. This is for linux 2.6.16 kernel.
The system call is called nb_request. I compiled the system call into the kernel image. The system call is:
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/sched.h>
#include <asm/current.h>
asmlinkage int sys_nb_request(int num, void (*nb_handler) (void *), void *handler_arg) {
printk(KERN_INFO "The number passed is %d.\n", num);
/* do something with current */
return 1;
}
The user space program that calls the system call, called invoker1.c, is:
#define __NR_nb_request 312
_syscall3(int, nb_request, int, num, void (*) (void *), nb_handler, void *, handler_arg);
void my_handler(void *p);
int main(int argc, char * argv){
void *a;
int j=8;
a =&j;
printf("a points to value %d\n", *((int *)a));
fprintf(stdout,"Executing system call... ");
nb_request(5, &my_handler, a);
fprintf(stdout,"Finished now\n");
return 0;
}
void my_handler(void *p)
{
//does something with p
}
My problem is that the compilation of the user-space program dies at line:
_syscall3(int, nb_request, int, num, void (*) (void *), nb_handler, void *, handler_arg);
and this is because I don't know how to define the pointer to a function in the _syscallN macro.
I'm using User Mode Linux, and I compile with
gcc -o invoke1 invoker.c -I./include
and invoker.c is placed in the root directory of the kernel tree.
Can someone, please, tell me how make this work?! I've been searching the web, but could not find anything except how to pass variables or void*
Mirna
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
void(int,void (void *), void *)
ASKER
I tried using it but still it doesn't work. Could you, please, write what the _syscall3 macro should look like? Do I need to change the definition of sys_nb_request?
how is it defined now?
how did you want to use it?
in the code above it looked more like a function declatation than a macro
how did you want to use it?
in the code above it looked more like a function declatation than a macro
ASKER
I talked with a friend and he figured out from your answer how I need to declare it. The problem was I didn't have a typdef for the function pointer. So the code now looks like this:
#include <asm/arch/unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
typedef void (*handler_ptr_type)(void*) ;
_syscall3(int, nb_request, int, num, handler_ptr_type, nb_handler, void*, handler_arg);
void my_handler(void *p);
int main(int argc, char * argv){
int *t;
void *a;
t = (int *)malloc(sizeof(int));
a = (void *)malloc(sizeof(int));
*t = 8;
*((int *)a) = 11;
printf("t points to value %d\n", *t);
printf("a points to value %d\n", *((int *)a));
fprintf(stdout,"Executing system call... ");
/*nb_request(5, &my_handler, a);*/
fprintf(stdout,"Finished now\n");
return 0;
}
void my_handler(void *p)
{
//does something with p
}
while the implementation of the syscall (sys_nb_request.c) is the same one. And this works.
Thank you very much for your help. I really appreciate it!
#include <asm/arch/unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
typedef void (*handler_ptr_type)(void*)
_syscall3(int, nb_request, int, num, handler_ptr_type, nb_handler, void*, handler_arg);
void my_handler(void *p);
int main(int argc, char * argv){
int *t;
void *a;
t = (int *)malloc(sizeof(int));
a = (void *)malloc(sizeof(int));
*t = 8;
*((int *)a) = 11;
printf("t points to value %d\n", *t);
printf("a points to value %d\n", *((int *)a));
fprintf(stdout,"Executing system call... ");
/*nb_request(5, &my_handler, a);*/
fprintf(stdout,"Finished now\n");
return 0;
}
void my_handler(void *p)
{
//does something with p
}
while the implementation of the syscall (sys_nb_request.c) is the same one. And this works.
Thank you very much for your help. I really appreciate it!
ASKER
_syscall3(int, nb_request, int, num, void (*) (void *), nb_handler, void *, handler_arg);
is in the user space function that wants to call nb_request system call.
(I know now that I shouldn't be passing variables that lie in the caller stack, but let's forget that for a moment.)
The system call implementation is in the arch/um/kernel/nb_request.
gcc complains that nb_handler is unrecognized. So my problem is, how do I declare the _syscall3 macro to pass a function pointer for the second argument.