Итак, краткое резюме: у меня есть программа, которая рекурсивно ищет файл с определенным расширением. Каждый раз, когда он его находит, он создает копию, вносит некоторые изменения в копию, создает патч (используя diff и execvp()) и удаляет исходный файл.
Проблема, с которой я столкнулся, заключается в том, что после нескольких сотен файлов fork() возвращается с сообщением «Ресурс временно недоступен». Я добавил счетчик, чтобы увидеть, сколько процессов все еще выполняется, когда происходит этот сбой, и похоже, что ни один из них не был закрыт - количество открытых процессов всегда совпадает с количеством обработанных файлов.
Теперь у меня сложилось впечатление, что поток должен идти примерно так- fork();//создает дочерний процесс dostuff();//в дочернем процессе _exit(1);//возвращаем управление родителю
но все оказывается не так просто. Возможно, кто-то здесь заметит что-то очевидное, чего мне не хватает в коде.
Я разместил функцию «очистки», которая отвечает за разветвление и исправление — остальное разделено на несколько файлов, так что, надеюсь, этого достаточно.
(аргумент «имя» — исходное имя файла, а «новое имя» — измененная копия.)
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
, не будет работать, если вызов не завершится ошибкой. - person Some programmer dude   schedule 09.07.2014wait()
? Если нет, вы создаете кучу зомби, заполняющих таблицу процессов. - person Jens   schedule 09.07.2014exec
, так это заменяет текущий процесс процессом из загруженной программы. Когда вы вызовете его, ваш текущий код просто перестанет существовать для процесса. - person Some programmer dude   schedule 09.07.2014exec
дочерний процесс выполняет совершенно другую программу. Когда он завершается, дочерний процесс завершается, он не возвращается к вашему коду. - person Barmar   schedule 09.07.2014wait
в блокеelse
if (patch_pid == 0)
. - person Barmar   schedule 09.07.2014execvp
, и этот код никогда не запустится. - person Some programmer dude   schedule 09.07.2014wait
илиwaitpid
(или родственные функции), вы можете использоватьSIGCHLD
signal, чтобы узнать, когда завершился дочерний процесс. - person Some programmer dude   schedule 09.07.2014@
перед его именем. В противном случае они не будут уведомлены о том, что вы отправили им сообщение. - person Barmar   schedule 09.07.2014waitpid
для ожидания любого процесса, и он возвращает pid процесса. Сохраните информацию (имена файлов, выделенную память и т. д.) в таблице вместе с pid и рабочим статусом. Как только процесс завершается, обработчик сигнала устанавливает запись в таблице для этого процесса как не работающую, а родительский процесс в своем основном цикле (или аналогичном) очищает ресурсы дочернего процесса. - person Some programmer dude   schedule 09.07.2014system
для запуска команды оболочки (там вы можете использовать перенаправление>
). - person Per Johansson   schedule 09.07.2014