调用者如何通过指定多个参数正确使用 clone() 系统调用?
How can a caller properly use the clone() system call by specifying multiple arguments?
我正在研究 clone() 系统调用,我希望有人能向我解释为什么允许调用者在此系统调用结束时传递多个参数?
查看 Linux 手册页中的文档,系统调用的语法如下:
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
/* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
在我看来,预期的第一个参数是一个函数地址 returns 一个整数 int
并且该函数只能接受一个参数,一个空指针 (void *)
。但是,在最后一个参数 void *arg
之后,我认为这是您想要传递给函数的空指针,有一个省略号运算符 ...
我认为在 C 中表示可以指定多个参数.
鉴于您在第一个参数中传递的函数只能接受一个参数,调用者将如何利用添加到此系统调用末尾的更多参数?
为了更好地理解我编译并 运行 下面的代码。据我所知,它工作得很好,但我不知道如何或为什么有人会使用 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;
}
输出:
Clone call current pid : 545
Parent pid: 545
Child pid : 546
Our variable passed : 11
我一定是误解了什么,任何澄清将不胜感激
附加参数是可选参数,用于指定克隆操作的附加操作。只有在 flags
参数中设置了特定标志时才会使用它们。如果您不设置任何这些标志,则不需要提供额外的参数。
如果设置CLONE_PARENT_SETTID
标志,子线程ID将存储在parent_tid
指向父进程的位置。
如果设置CLONE_SETTLS
标志,tls
参数将用作线程本地存储描述符的地址。
如果设置了CLONE_CHILD_SETTID
标志,子进程的线程ID将存储在子进程中child_tid
指向的位置。
这样做是为了向后兼容。这些参数不在最初的 clone()
系统调用中,而是在后来的 Linux 版本中添加的。它们是可选的,因此旧代码将继续编译。
我正在研究 clone() 系统调用,我希望有人能向我解释为什么允许调用者在此系统调用结束时传递多个参数?
查看 Linux 手册页中的文档,系统调用的语法如下:
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
/* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
在我看来,预期的第一个参数是一个函数地址 returns 一个整数 int
并且该函数只能接受一个参数,一个空指针 (void *)
。但是,在最后一个参数 void *arg
之后,我认为这是您想要传递给函数的空指针,有一个省略号运算符 ...
我认为在 C 中表示可以指定多个参数.
鉴于您在第一个参数中传递的函数只能接受一个参数,调用者将如何利用添加到此系统调用末尾的更多参数?
为了更好地理解我编译并 运行 下面的代码。据我所知,它工作得很好,但我不知道如何或为什么有人会使用 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;
}
输出:
Clone call current pid : 545
Parent pid: 545
Child pid : 546
Our variable passed : 11
我一定是误解了什么,任何澄清将不胜感激
附加参数是可选参数,用于指定克隆操作的附加操作。只有在 flags
参数中设置了特定标志时才会使用它们。如果您不设置任何这些标志,则不需要提供额外的参数。
如果设置CLONE_PARENT_SETTID
标志,子线程ID将存储在parent_tid
指向父进程的位置。
如果设置CLONE_SETTLS
标志,tls
参数将用作线程本地存储描述符的地址。
如果设置了CLONE_CHILD_SETTID
标志,子进程的线程ID将存储在子进程中child_tid
指向的位置。
这样做是为了向后兼容。这些参数不在最初的 clone()
系统调用中,而是在后来的 Linux 版本中添加的。它们是可选的,因此旧代码将继续编译。