Я пытаюсь использовать clone () для создания дочернего процесса для exec () некоторых программ. Я знаю, что exec () заменяет исходный процесс, и вызывающий его процесс должен заканчиваться им, поэтому я использую дочерний процесс для вызова exec (). Однако по некоторым причинам после exec () мой родительский процесс тоже вылетает. Может кто-нибудь сказать мне, почему это происходит? (если я заменю clone на 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); это то, что разбило всю программу. Я добавляю два отпечатка: один до и один после, последний никогда не запускается. Я не понимаю, потому что думал, что clone работает так же, как fork, который создает новый процесс, и конец процесса chile не повлияет на родительский?
Спасибо!!!
А также прочтите страницу руководства для strchr()
Не используйте клон (2). Оставьте это гуру реализациянитки (7). Вы еще не один! Используйте вилка (2) для создания процесса и pthread_create (3) для создания потока posix





clone(…CLONE_THREAD…) - это не тот clone(), который вы ищете. Он создает новый процесс в той же группе потоков, что и родительский процесс, и:
If any of the threads in a thread group performs an
execve(2), then all threads other than the thread group leader are terminated, and the new program is executed in the thread group leader.
Если вы ищете способ запустить процесс без использования fork(), рассмотрите возможность использования вместо этого posix_spawn().
Кроме того, указатель стека, который вы передаете clone(), недействителен. Размер стека, который вы выделяете, составляет 10 000 байт, но указатель стека находится на 100 000 байт за пределами стека и на 90 000 байт за его концом.
Это происходит потому, что вы никогда не вызываете clone. Эта часть:
clone((void *)mySysC(command), ...);
эквивалентно:
int result = mSysC(command);
void* first = (void*) result;
clone(first, ...);
поэтому он вызывает вашу функцию еще до того, как вызовет clone. Вместо этого вам нужно передать его как указатель на функцию.
В дополнение к этому вы должны удалить один ноль из вашего 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);
}
настоятельно рекомендую: 1) включить предупреждения при компиляции, а затем исправить эти предупреждения. 2) прочтите / поймите страницу MAN для
clone()