Fork不会在execv中加载程序

时间:2018-03-16 17:32:50

标签: process pipe fork execv socketpair

以下程序既不会将程序加载到子进程也不会打印"之前"和"之后"。 但是,ps aux显示了进程的创建(但没有加载args0程序)。我使用PIPE定义为socketpair。 args0 []保存子程序的可执行文件名,args1 []保存子程序的名称。 args2和args3是预定义的值,它们不会发生变化,应该作为参数发送给子节点。你可以假设char args2 [] =" 10" - >用户输入(数字)并转换为字符串。我只是不明白为什么至少printf("之前")没有打印出来。我读到了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);

}

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

1 个答案:

答案 0 :(得分:0)

(剧透:您的名字elseforkk的{​​{1}}分支永远不会被拍摄!)

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

  

execv(),execvp()和execvpe()函数提供了一个数组          指向以null结尾的字符串的指针,表示参数列表          可用于新计划。第一个论点,按照惯例,          应指向与正在执行的文件关联的文件名。          指针数组必须以空指针终止。

所以你至少应该编码:

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

文档也说

  

只有在发生错误时,exec()函数才会返回

所以在大多数情况下,没有必要继续这里,因为execv如果成功则不会返回。但是,你需要抓住失败。我建议您execv

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

你的write(myPipe->fd[0], &m, sizeof(server_message));闻起来很糟糕。当execv失败时,我认为没有必要(仅限)

BTW与strace(1)你可能会遇到这样的错误(缺少NULL的终止execv指针。

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

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

cpid = fork();

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

再次仔细阅读getpid(2)

  

getpid()返回调用进程的进程ID(PID)。

和(约getpid&amp; getppid):

  

这些功能始终成功

所以getpid 永远不会返回0(这就是为什么你的else 命名不佳的forkk分支的原因,包含execvp永不运行)。另请参阅credentials(7)

你的void main()也错了。 main应返回int。您通常将其定义为int main(int argc, char**argv) ...

PS。 养成

您的forkk名称非常差,与非常重要的fork名称太相似。