我正在尝试使用clone()创建一个子进程来执行(某些程序)。我知道exec()会替换原始进程,并且调用它的进程应该以它结尾,因此我使用子进程来调用exec()。但是,由于某些原因,在exec()之后,我的父进程也崩溃了。有人可以告诉我为什么会这样吗? (如果我用fork或vfork替换克隆,它可以工作)
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sched.h>
void delNL(char * arry){ //A function to delete the newline at the end of the array
char * position;
position = strchr(arry,'\n');
*position = '\0';
}
int mySysC(char * command){ //clone funtion
char *cmd[10]={" "};
int nb=0;
int cnb=0;
while(command[nb]!='\0'){
char coa[10];
int cici=0;
while(command[nb]!=' ' && command[nb]!='\0'){
coa[cici]=command[nb];
nb++;
cici++;
}
coa[cici]='\0';
char *nad=(char *)malloc(10);
strcpy(nad,coa);
cmd[cnb]=nad;
cnb++;
if(command[nb]==' '){
nb++;
}
}
cmd[cnb]=NULL;
execvp(cmd[0],cmd);
exit(0);
}
void my_system_c(char * command){ //clone version
void * stack = (void *)malloc(10000);
void * stackTop = stack + 100000;
pid_t pid = clone((void *)mySysC(command),stackTop,CLONE_THREAD,NULL); //clone
waitpid(pid,NULL,0);
}
int main(){
char commdd[100];
char ex[10]="os_exit";
while(1){
printf("Please enter your command or enter \"os_exit\" to exit:\n");
fgets(commdd,100,stdin);
delNL(commdd);
if(strlen(commdd)>0 && strcmp(commdd,ex)!=0){
my_system_c(commdd); //select version
}
else if(strcmp(commdd,ex)==0) break;
else printf("Empty command\n");
}
return 0;
}
execvp(cmd [0],cmd);这就是使整个程序崩溃的原因。我添加了两个打印件,一个在打印之前,一个在打印之后,之后的一个从不运行。我不明白,因为我认为克隆的作用就像fork一样,它创建了一个新进程,而智利进程的结束不会影响父进程吗?
谢谢!!!
答案 0 :(得分:1)
clone(…CLONE_THREAD…)
不是您要的clone()
。它在与父进程相同的线程组中创建一个新进程,并且:
如果线程组中的任何一个线程执行
execve(2)
,则该线程组领导者以外的所有线程都将终止,并在线程组领导者中执行新程序。
如果您正在寻找不使用fork()
来启动流程的方法,请考虑使用posix_spawn()
。
此外,您传递给clone()
的堆栈指针无效。您分配的堆栈大10,000字节,但是堆栈指针比堆栈的开头超出100,000字节-超出堆栈的末尾90,000字节。
答案 1 :(得分:1)
之所以会这样,是因为您从未真正致电clone
。这部分:
clone((void *)mySysC(command), ...);
等效于:
int result = mSysC(command);
void* first = (void*) result;
clone(first, ...);
因此它在调用克隆之前先调用您的函数。您需要将其作为函数指针传递。
除此之外,您还应该从stackTop
中删除一个零以匹配malloc,并避免传递CLONE_THREAD
,因为您需要一个新进程:
void my_system_c(char * command){ //clone version
void * stack = (void *)malloc(10000);
void * stackTop = stack + 10000;
pid_t pid = clone(mySysC,stackTop,0,command); //clone
waitpid(pid,NULL,0);
}