【发布时间】:2014-07-09 12:53:51
【问题描述】:
所以简短的摘要是-我有一个程序可以递归地搜索具有特定扩展名的文件。每次找到一个,它都会制作一个副本,对副本进行一些更改,创建一个补丁(通过使用 diff 和 execvp())并删除原始文件。
我遇到的问题是,在数百个文件之后,fork() 返回“资源暂时不可用”。我添加了一个计数器来查看发生此故障时仍有多少进程在运行,并且看起来没有一个已关闭 - 打开的进程数始终与处理的文件数相同。
现在,我的印象是流程应该是这样的—— fork();//创建子进程 dostuff();//在子进程中 _exit(1);//将控制权交还给父级
但事情似乎没有那么简单。也许这里有人可能会发现我在代码中遗漏了一些明显的东西。
我已经发布了负责分叉和修补的“清理”功能 - 其余部分被拆分为多个文件,所以希望这已经足够了。
(参数“name”是原始文件名,“newname”是修改后的副本。)
void cleanup (char * name, char * newname)
{
if (pf)
{
pid_t patch_pid;
char * const diffargs[5] = {thisdiff, "-u", newname, name, NULL};
char * patchname = malloc(strlen(name) + 6);
strcpy(patchname, name);
strcat(patchname, ".patch");
if((patch_pid = fork()) < 0 )
{
printf("fork failed.\n%s\nfilecount: %ld\nopen forks: %d\n", strerror(errno), filecount, pcount);
exit(-1);
}
pcount++;
if (patch_pid == 0)
{
FILE *pfp;
if ((pfp = fopen(patchname, "w")) == NULL)
{
printf("Error opening file \"%s\" for writing.\n%s\n", patchname, strerror(errno));
exit(-1);
}
dup2(fileno(pfp), STDOUT_FILENO);
fclose(pfp);
execvp(diffargs[0], diffargs);
free(patchname);
if (remove(name) != 0)
{
printf("Error removing file %s\n%s\n", name, strerror(errno));
exit(-1);
}
if (rename(newname, name) != 0)
{
printf("Error renaming file %s\n%s\n", newname, strerror(errno));
exit(-1);
}
pcount--;
_exit(1);
}
}
else if (!df && !xf)
{
if (remove(name) != 0)
{
printf("Error removing file %s\n%s\n", name, strerror(errno));
exit(-1);
}
if (rename(newname, name) != 0)
{
printf("Error renaming file %s\n%s\n", newname, strerror(errno));
exit(-1);
}
}
}
【问题讨论】:
-
您知道如果
exec系列函数成功,它们不会返回吗?这意味着您在execvp调用之后拥有的任何代码都不会运行,除非调用失败。 -
您是否使用
wait()在某处获得已退出进程的退出状态?如果没有,你会创建一堆僵尸来填满进程表。 -
除非出现错误,否则它们不会返回任何值......但它们最终肯定会完成并继续执行吗?
-
詹斯:不,我没有。我必须承认,我不知道 wait() 的合适位置在哪里。我猜在 cleanup() 例程的最后?
-
exec系列函数所做的是将当前进程替换为加载程序中的进程。当您调用它时,您当前的代码将不再存在于该进程中。