Re[2]: Нужна консультация fork, pipe, execvp
От: Saddam Россия http://saddam.narod.ru
Дата: 13.03.17 21:35
Оценка:
Здравствуйте, Masterspline, Вы писали:

M>У тебя в массиве Pipes остаются файловые дескрипторы в открытом состоянии (причем как в детях, кроме тех fd, которые заменяются на stdin/out, так и в мастере, прием в нем все fd остаются открытыми), а их нужно закрыть. Иначе программа, читающая из канала не знает когда ей закончить, т.к. в каком-то процессе есть еще открытый файловый дескриптор от пишущего конца канала, хотя процесс, который писал уже завершился.

M>Т.е. происходит следующее (для "who | sort | uniq -c" ):
M>1. создаются дескрипторы для pipe в мастере, затем три ребенка (в которых тоже есть эти дескрипторы).
M>2. первый ребенок меняет и закрывает дескриторы Pipes[0], но оставляет открытыми Pipes[1], затем exec, который пишет и успешно заканчивает работу
M>3. второй ребенок меняет Pipes[1], но сохраняет Pipes[0] и читает что надо, но так как есть еще незакрытые копии файловых дескрипторов для нулевого pipe (в мастере и третьем ребенке), то его записывающий конец не закрыт и sort продолжает пытаться читать. Нужно закрыть все пишущие концы канала в мастере и других детях, чтобы при выходе "who" и закрытии им своего пишущего конца sort на читающем конце считал все, что есть и завершил чтение, т.к. данных больше нет, пишущий конец закрыт.
Очень похоже, но не выходит каменный цветок... Я по-всякому пробовал закрывать дескрипторы....
Я так уже пробовал. Результат ниже (до строки PID... — валит в stderr):
uniq: ошибка чтения '-'
sort: операция stat завершилась неудачно: -: Неправильный дескриптор файла
sort: операция stat завершилась неудачно: -: Неправильный дескриптор файла
who: ошибка записи: Обрыв канала
 PID:2170 Count:1
 PID:2171 Count:2
 PID:2172 Count:3
 PID:2173 Count:4
Waiting for 4
Waiting for 3
PID: 2172 terminated 
Waiting for 2
PID: 2173 terminated 
Waiting for 1
PID: 2171 terminated 
Master is finished!

Дескрипторы куда-то пролюбливаются....
M>Вот мой пропатченный вариант:
M>На самом деле, я бы поправил алгоритм, потому что хранить массив файловых дескрипторов, который передается в ребенка, не очень надежное решение. Например, можно создавать pipe непосредственно перед форком и передавать наследнику только два нужных файловых дескриптора от его пайпов. Наследник для них сделает dup2 и close, а родитель сразу после форка сделает close ненужным концам пайпов. Таким образом не будет создаваться мусора из ненужных файловых дескрипторов, которые еще и нужно закрывать, но в разных местах по разному, чтобы не закрыть чего нужного.
Тоже думал над этим. Пожалуй, завтра утром так и попробую сделать (красивее код получиться должен).
- Вы знаете — жаль, просто по-человечески жаль Памелу Андерсон, которая никогда не сможет сыграть на баяне...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.