【问题标题】:Why does my parent process also crash after exec()?为什么我的父进程在 exec() 之后也会崩溃?
【发布时间】:2018-09-29 17:47:31
【问题描述】:

我正在尝试使用 clone() 创建一个子进程来 exec() 一些程序。我知道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);这就是使整个程序崩溃的原因。我在之前和之后添加了两个打印件,后一个从不运行。我不明白,因为我认为 clone 就像 fork 一样工作,它创建一个新进程,并且智利进程的结束不会影响父进程?

谢谢!!!

【问题讨论】:

  • 强烈建议:1) 编译时启用警告,然后修复这些警告。 2)阅读/理解clone()的MAN页面
  • 同时阅读strchr()的手册页
  • 不要使用clone(2)。把它留给大师实施 pthreads(7)。你还不是一个人!使用fork(2)创建进程,使用pthread_create(3)创建posix线程

标签: c fork exec clone


【解决方案1】:

clone(…CLONE_THREAD…) 不是您要查找的 clone()。它在与父进程相同的线程组中创建一个新进程,并且:

如果线程组中的任何线程执行execve(2),则除线程组领导者之外的所有线程都将终止,并在线程组领导者中执行新程序。

如果您正在寻找一种不使用fork() 来启动进程的方法,请考虑改用posix_spawn()

此外,您传递给clone() 的堆栈指针无效。您分配的堆栈有 10,000 字节大,但堆栈指针在堆栈开头之外 100,000 字节,在其结尾之外 90,000 字节。

【讨论】:

    【解决方案2】:

    发生这种情况是因为您从未真正致电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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 2012-06-04
      相关资源
      最近更新 更多