Fork 不加载 execv 中的程序

Fork doesn't load the program in execv

下面的程序既不将程序加载到 child 进程也不打印 "before" 和 "after"。 但是 ps aux 显示了进程的创建(但没有加载 args0 程序)。我正在使用定义为 socketpair 的 PIPE。 args0[] 保存 child 程序的可执行名称,args1[] 保存 child 程序的名称。 args2 和 args3 是预定义的值,不会改变,应该作为参数发送给 children。您可以假设 char args2[] = "10" --> 用户输入(数字)并转换为字符串。我只是不明白为什么至少不打印 printf("before") 。我阅读了有关 fflush 并将 \n 放在每个 printf 的信息,我做到了。所以我程序中的所有内容 到目前为止已正确打印。

非常感谢您的回复。

char args2[];
char args3[];
//creating pipe
int forkk(pipes *myPipe, server_message *m, char args0[],char args1[]) {
pid_t cpid;

//pipe passed myPipe[i]
if (PIPE(myPipe->fd) == -1) {
    perror("pipe error\n");
    return -1;
}
 fork();
 cpid=getpid();
if (cpid == -1) {
    perror("fork error\n");
    return -1;
}
if (cpid) {
    close(myPipe->fd[1]);
    return 1;//closing one end of parent

} else {

    for (int i = 3; i <= myPipe->fd[0]; i++) {
        close(i);
    }

    dup2(myPipe->fd[1], 0); //redirecting stdin of child
    dup2(myPipe->fd[1], 1); //redirecting stdout of child
    close(myPipe->fd[1]);
    myPipe->cpid = cpid;
    char *newargs[3];
    newargs[0]=args1;
    newargs[1]=args2;
    newargs[2]=args3;
    printf("before\n");
    //fflush(stdout);
    execv(args0,newargs);
    printf("after execv\n");
    write(myPipe->fd[0], &m, sizeof(server_message));  //send the server_msg immediately (pass an array or msg)

}
    return 2;

}

void main(){
....
scanf("%d %d", &width, &height);
sprintf(args2,"%d",height); //converting into to string
sprintf(args3,"%d",width);
char *args0 = "./prey";
char *args1 = "prey";
int r= forkk(&myPipes[2], &msg, args0,args1);

}

我无法 post 完整的代码,因为它很长并且需要解释。我很可能遇到指针分配问题,我错误地认为这是正确的方法。非常感谢任何形式的帮助

(剧透:你的 else 分支在你命名不当的 forkk 中从未被占用!)

仔细阅读 execv(3) 的文档。您应该提供一个 NULL 终止数组。

The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer.

所以你至少应该编码:

char *newargs[4];
newargs[0]=args1;
newargs[1]=args2;
newargs[2]=args3;
newargs[3] = NULL; // mandatory last NULL pointer
execv(args0,newargs);

顺便说一句,第一个参数一般应该是程序名。所以你真的想要:

char *newargs[5];
newargs[0] = args0;
newargs[1]=args1;
newargs[2]=args2;
newargs[3]=args3;
newargs[4] = NULL; // mandatory last NULL pointer
execv(args0,newargs);

并且文档还说

The exec() functions return only if an error has occurred.

所以在大多数情况下,没有必要在这里继续,因为如果成功,execv 不会 return。但是,您需要捕获失败。我推荐你 execv

perror(arg0); // or perhaps perror("execv");
exit(EXIT_FAILURE);

你的 write(myPipe->fd[0], &m, sizeof(server_message)); 闻起来很臭。当 execv 失败

时,我认为(仅)这样做没有意义

顺便说一句,使用 strace(1) 你可能会遇到这样的错误(缺少 execv 的终止 NULL 指针)。

最后,你总是应该保留fork(2). See this的结果。所以替换:

 fork(); // WRONG
 cpid=getpid(); // always positive!

cpid = fork();

当然需要handle the three casescpid== -1(忘记处理了!),cpid== 0cpid> 0.

再次请仔细阅读getpid(2):

getpid() returns the process ID (PID) of the calling process.

和(关于 getpid & getppid):

These functions are always successful

所以getpid从不returns 0(这就是为什么你的else分支在你的forkk 命名不当的函数,包含 execvp 从不运行 )。另见 credentials(7)

你的void main()也是错误的。 main 应该 return 一个 int。您通常将其定义为 int main(int argc, char**argv) ...

PS。 养成阅读仔细您正在使用的每个函数的文档的习惯

您的 forkk 命名非常糟糕,与非常重要的 fork 名称太相似了。