I'm doing some research on the clone() system call and I was hoping someone could explain to me why a caller is allowed to pass multiple arguments at the end of this system call?
Looking at the documentation in the Linux man-pages the syntax for the system call is as follows:
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
/* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
It appears to me, the first parameter expected is a function address that returns an integer int
and that function can only accept one argument, a void pointer (void *)
. However, following the last parameter, void *arg
which I believe is the void pointer you would want to pass to your function, there is an ellipsis operator ...
which I thought in C indicates that multiple arguments can be specified.
Given that the function you pass in the first parameter can only take in one argument, how would the caller take advantage of any more arguments added to the end of this system call?
To better my understanding I compiled and ran the code below. It works just fine, as far as I can tell, but I have no idea how or why anyone would have a use for something like extraParm
#define STACK 8192
int do_something(void *somevar){
printf("Parent pid: %d\n Child pid : %d\n", getppid(), getpid());
printf("Our variable passed : %d\n", *(int *)somevar);
return 0;
}
int main() {
void *stack = malloc(STACK);
int inputParm = 11;
void *inputPtr = &inputParm;
char extraParm[ ] = "Extra Parameter";
if(!stack) {
perror("Malloc Failed");
exit(0);
}
if( clone( &do_something, (char *)stack + STACK, SIGCHLD, inputPtr, extraParm) < 0 ){
perror("Clone Failed");
exit(0);
}
printf("Clone call current pid : %d\n", getpid());
sleep(1);
free(stack);
return 0;
}
Output:
Clone call current pid : 545
Parent pid: 545
Child pid : 546
Our variable passed : 11
I must be misinterpreting something, any clarification would be greatly appreciated
The additional arguments are optional arguments used to specify additional operations of the clone operation. They're only used if particular flags are set in the flags
argument. If you don't set any of those flags, you don't need to supply the additional arguments.
If you set the CLONE_PARENT_SETTID
flag, the child's thread ID will be stored in the location that parent_tid
points to in the parent process.
If you set the CLONE_SETTLS
flag, the tls
argument will be used as the address of the thread-local storage descriptor.
If you set the CLONE_CHILD_SETTID
flag, the child's thread ID will be stored in the location that child_tid
points to in the child process.
It's done this way for backward compatibility. These arguments weren't in the original clone()
system call, but were added in later Linux versions. They're optional so that older code will continue to compile.