所以简短的总结是 - 我有一个程序,递归搜索具有特定扩展名的文件。每次找到一个,它都会复制,对副本进行一些更改,创建一个补丁(通过使用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);
}
}
}
答案 0 :(得分:0)
两个建议:
答案 1 :(得分:0)
您可能希望在else
之后使用fork
子句来处理父进程。像下面这样的东西可能会起作用;
void cleanup (char * name, char * newname)
{
if (pf)
{
/* SNIP - unchanged */
if (patch_pid == 0) /* child */
{
FILE *pfp;
if ((pfp = fopen(patchname, "w")) == NULL)
{
printf("Error opening file \"%s\" for writing.\n%s\n",
patchname, strerror(errno));
exit(EXIT_FAILURE);
}
dup2(fileno(pfp), STDOUT_FILENO);
fclose(pfp);
execvp(diffargs[0], diffargs);
perror("execvp");
exit(EXIT_FAILURE);
}
else /* parent */
{
pid_t rc;
int stat;
free(patchname);
rc = waitpid(patch_pid, &stat, 0);
if (rc < 0)
{
perror("waitpid");
/* do something appropriate here */
}
else
{
/* if you care about your children */
if (WIFEXITED(stat))
{
printf("%d exited with status %d\n",
(int)rc, WEXITSTATUS(stat));
}
else if (WIFSIGNALED(stat))
{
printf("%d terminated because of signal %d\n",
(int)rc, WTERMSIG(stat));
}
else if (WIFSTOPPED(stat))
{
printf("%d was STOPPED with signal %d\n",
(int)rc, WSTOPSIG(stat));
}
}
pcount--;
if (remove(name) != 0)
{
printf("Error removing file %s\n%s\n", name, strerror(errno));
exit(EXIT_FAILURE);
}
if (rename(newname, name) != 0)
{
printf("Error renaming file %s\n%s\n", newname, strerror(errno));
exit(EXIT_FAILURE);
}
}
}
}
我还强烈推荐已故的W. Richard Stevens在UNIX环境中阅读高级编程。实际上,您应该添加 UNIX网络编程第1卷和第1版。 2 也列入你的清单;)
我注意到的另一件事是你有与patchname
相关的内存管理错误。 malloc
调用未考虑字符串末尾的额外NUL
字符。