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