Process 叉子不';t在execv中加载程序

Process 叉子不';t在execv中加载程序,process,pipe,fork,execv,socketpair,Process,Pipe,Fork,Execv,Socketpair,下面的程序既不将程序加载到子进程,也不打印“before”和“after”。 但是,ps aux显示进程的创建(但不加载args0程序)。我正在使用定义为socketpair的管道。args0[]保存子程序的可执行名称,args1[]保存子程序的名称。args2和args3是预定义的值,不会更改,应该作为参数发送给子级。您可以假设char args2[]=“10”-->用户输入(数字)并转换为字符串。我只是不明白为什么至少printf(“before”)没有被打印出来。我读过关于fflush和在

下面的程序既不将程序加载到子进程,也不打印“before”和“after”。 但是,ps aux显示进程的创建(但不加载args0程序)。我正在使用定义为socketpair的管道。args0[]保存子程序的可执行名称,args1[]保存子程序的名称。args2和args3是预定义的值,不会更改,应该作为参数发送给子级。您可以假设char args2[]=“10”-->用户输入(数字)并转换为字符串。我只是不明白为什么至少printf(“before”)没有被打印出来。我读过关于fflush和在每个printf上放置\n的内容,我确实读过。所以我节目里的一切 到目前为止打印正确

我非常感谢你的回答

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

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

(扰流器:您的
else
分支在您的
forkk
中从未被使用过!)

仔细阅读的文件。您应该提供一个
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);
您的
写入(myPipe->fd[0],&m,sizeof(服务器消息))闻起来很难闻。我认为这样做没有意义(只有在
execv
失败时)

顺便说一句,您可能会发现这样一个错误(缺少
execv
NULL
指针)

最后,你应该始终保持测试结果。看见因此,请替换:

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

当然,您需要:
cpid==-1
(您忘记处理!),
cpid==0
cpid>0

再次,请仔细阅读:

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

和(关于
getpid
getppid
):

这些功能总是成功的

因此,
getpid
从不返回0(这就是为什么
forkk中
else
分支的
execvp
函数名不好,包含
execvp
从不运行的原因)。另见

您的
void main()
也是错误的
main
应返回一个
int
。您通常将其定义为
intmain(intargc,char**argv)

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


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

使用所有警告和调试信息编译:
gcc-Wall-Wextra-g
with。改进代码以不获取警告。也使用。不要忘记在适当的位置调用
fflush
(可能是
fflush(NULL);
…)阅读文档;它通常不会返回(失败时除外),我没有警告。这不是一个完整的代码,所以您可能有。你认为我在发帖之前没有读过任何东西。我已经用gdb调试了5个小时了。我多次阅读exec系列组函数,并为execv传递正确的参数,但我没有看到和知道smth,这就是我在这里发布的原因。您是否使用了
strace
?这应该会有帮助。你应该在你的问题中提供一些,这个程序的某些部分对fork没有关键影响,我认为我提供的应该足以让专业人士看到错误(msg和myPipes也不会直接影响fork)。我没有用过strace,我会用的。程序分叉,从不转到问题本身的其他部分
 fork(); // WRONG
 cpid=getpid(); // always positive!