Почему мой родительский процесс также аварийно завершает работу после exec ()? - PullRequest
0 голосов
/ 29 сентября 2018

Я пытаюсь использовать clone () для создания дочернего процесса для exec () некоторых программ.Я знаю, что exec () заменяет исходный процесс, и процесс, который его вызывает, должен заканчиваться этим, поэтому я использую дочерний процесс для вызова exec ().Однако, по некоторым причинам, после exec () мой родительский процесс также падает.Может кто-нибудь сказать мне, почему это происходит?(если я заменю клон на форк или 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, который создает новый процесс, и конец процесса chile не повлияет на родительский?

Спасибо !!!

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Это происходит потому, что вы никогда не звоните 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);
}
0 голосов
/ 29 сентября 2018

clone(…CLONE_THREAD…) - это не clone(), который вы ищете.Он создает новый процесс в той же группе потоков, что и родительский процесс, и:

Если какой-либо из потоков в группе потоков выполняет execve(2), то все потоки, кроме лидера группы потоковзавершаются, и новая программа выполняется в лидере группы потоков.

Если вы ищете способ запустить процесс без использования fork(), рассмотрите возможность использования posix_spawn() вместо.

Кроме того, указатель стека, который вы передаете clone(), недействителен.Размер выделяемого стека составляет 10 000 байт, но указатель стека находится на 100 000 байт за пределами начала стека и 90 000 байт за его конец.

...