以下程序既不会将程序加载到子进程也不会打印"之前"和"之后"。 但是,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);
}
我不能发布整个代码,因为它很长,需要解释。我很可能遇到指针分配问题,我错误地认为这是正确的方法。非常感谢任何帮助
答案 0 :(得分:0)
(剧透:您的名字else
中forkk
的{{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 cases:cpid== -1
(您忘了处理!),cpid== 0
,cpid> 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
名称太相似。