Почему мой родительский процесс также аварийно завершает работу после exec ()?

Я пытаюсь использовать 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 не повлияет на родительский?

Спасибо!!!

настоятельно рекомендую: 1) включить предупреждения при компиляции, а затем исправить эти предупреждения. 2) прочтите / поймите страницу MAN для clone()

user3629249 29.09.2018 20:00

А также прочтите страницу руководства для strchr()

wildplasser 29.09.2018 20:04

Не используйте клон (2). Оставьте это гуру реализациянитки (7). Вы еще не один! Используйте вилка (2) для создания процесса и pthread_create (3) для создания потока posix

Basile Starynkevitch 29.09.2018 20:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
182
2

Ответы 2

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);
}

Другие вопросы по теме