открывает FIFO (Write only),
пишет в FIFO,
закрывает FIFO.
Работа происходит в блокирующем режиме.
Проблема возникает при обмене маленьким обьемом данных.
В этом случае может возникнуть ситуация, когда поток1 блокируется на открытии FIFO, а поток 2 быстро выполняет всю работу и завершается, при этом поток 1 остается заблокированым на открытии.
Как побороть?
пусть поток 1 открывает FIFO не дожидаясь открытия его на запись, а потом блокируется при попытки чтения.
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
пусть поток 1 открывает FIFO не дожидаясь открытия его на запись, а потом блокируется при попытки чтения.
А как открыть файл FIFO без блокирования? Если open("FifoFile", O_RDWR), то функция read не вернет 0, когда поток 2 закончит работу, т.к. FIFO еще будет открыт для записи.
А как открыть файл FIFO без блокирования? Если open("FifoFile", O_RDWR),
O.o
Конечно не так. man open O_NONBLOCK или O_NDELAY
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
пусть поток 1 открывает FIFO не дожидаясь открытия его на запись, а потом блокируется при попытки чтения.
Я подумал, так точно не получиться. Не будет блокироваться при чтении, так как FIDO окажется пустым и не открытым на запись, и read вроде как сразу вернет 0
PS Вообще странно, Ваш код вроде как должен работать нормально, так как блокировка с открытия на чтения, должна сниматься прямо в момент открытия FIFO на запись (и наоборот). Вы уверены, что open во втором потоке срабатывает без ошибки?
Давайте ваш код целиком.
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
int main(int argc, char *argv[])
{
int fd[2]; // Это файловые дескрипторы канала
if (pipe(fd) < 0) // Создаем канал
err_sys("pipe error");
// Создаем дочерний процесс
if ( (pid = fork()) < 0) err_sys("fork error");
else if (pid > 0) { // Родитель
close(fd[0]); // Закрываем ненужный канал на чтение
write(fd[1], ...): // Пишем в канал
. . .
close(fd[1]); // Писанину закончили
if (waitpid(pid, NULL, 0) < 0) // Ждем дочку
err_sys("waitpid error");
exit(0); // Честно помираем
} else { // Дочка
close(fd[1]); // Закрываем ненужный канал на запись
if (execl(MyProg,...) < 0) // Запускаем нужную программу и передаем ей файловый дескриптор.
err_sys("execl error for %s", pager);
// А если оказались здесь, значит execl не отработал...
}
похоже что помогло, большое спасибо.
А тут не возникнет обратной ситуации, когда поток 1 быстренько открывает, читает 0 байт (т.к. еще поток2 не открыл) и закрывает FIFO,
а только после этого поток2 пытается открыть FIFO?
похоже что помогло, большое спасибо.
А тут не возникнет обратной ситуации, когда поток 1 быстренько открывает, читает 0 байт (т.к. еще поток2 не открыл) и закрывает FIFO,
а только после этого поток2 пытается открыть FIFO?
возникает
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
Мне кажется. что для такой простой задачи гораздо лучше подходит использование pipe канала.
к сожелению pipe не желателен, т.к. код производящий чтение может читать и из файла.
А писать 2 разные функции которые деляю одно и тоже - очень не хочется
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
Сразу не заметил это сообщения, прошу прощщения.
Код у меня большой слишком, там примешена и работа с сокетами и работа и БД и много еще чего. Думаю не стоит выкладывать.
все должно работать.
вы уверены, что никто больше не держит этот FIFO открытым на чтение?
набросал маленькую программку, все работает нормально, правда с процессами.
Код:
$mkfifo fifo.my
$ ./pfifo fifo.my 5 1
+ Son PID=12221: I am sleeping....1
= Parent PID=12220: I am sleeping....5
+ Son: I am open FIFO for write !!...T=1240398630
==== Parent: I am open FIFO for read !!!...T=1240398634
==== Parent: I am read !!!...T=1240398634
+ Son: I am write !!...T=1240398634
==== Parent: reading nbytes=6
==== Received string in parent:
Hello
+ Son: writing in pipe nbytes=6
+ Son: Message to parent: Hello
+ Son: END !!!....T=1240398634
= Parent: END ...T=1240398634
---------------------------------------------------------
$ ./pfifo fifo.my 1 5
+ Son PID=12223: I am sleeping....5
= Parent PID=12222: I am sleeping....1
==== Parent: I am open FIFO for read !!!...T=1240398660
+ Son: I am open FIFO for write !!...T=1240398664
+ Son: I am write !!...T=1240398664
+ Son: writing in pipe nbytes=6
+ Son: Message to parent: Hello
+ Son: END !!!....T=1240398664
==== Parent: I am read !!!...T=1240398664
==== Parent: reading nbytes=6
==== Received string in parent:
Hello
= Parent: END ...T=1240398664
попробуйте с разными задержками. ничего не должно виснуть
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
все должно работать.
вы уверены, что никто больше не держит этот FIFO открытым на чтение?
набросал маленькую программку, все работает нормально, правда с процессами.
Спасибо уважаемый nesk :-). С задержками - работает. Правда я ставил sleep(n) перед close(fd), чтобы гарантировать переключение контекcта с писателя на читателя.
Только жалко их ставить, получается сознательно снижается быстродействие.
И возникает подозрение: если в системе будет некий процесс потребляющий много процесороного времени sleep может и не помочь....
Наверное все-таки попробую вместо fifo - pipe.
FIFO создается и используется только моим процессом, уверен что больше некому его держать открытым.
chuk, я в примере использовал sleep до open (а не до close) что бы сымитировать ситуации когда первым канал открывает читатель, а писатель работает медленно и долго не открывает канал; и противоположную ситуацию, когда писатель первым открывает канал.
короче говоря, слипы я пытался использовать не для синхранизации, а наоборот, для того, что рассинхронизировать процессы и показать, что ничего виснуть не должно!
можете убрать все слипы и программа будет работать и не будет виснуть!
Попробуйте сымитировать на примере моей программы, Ваше зависание. Если сложно работать с Вашим большим кодом, давайте разберёмся с ошибкой на примере моего простого маленького кода.
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
chuk, я в примере использовал sleep до open (а не до close) что бы сымитировать ситуации когда первым канал открывает читатель, а писатель работает медленно и долго не открывает канал; и противоположную ситуацию, когда писатель первым открывает канал.
короче говоря, слипы я пытался использовать не для синхранизации, а наоборот, для того, что рассинхронизировать процессы и показать, что ничего виснуть не должно!
можете убрать все слипы и программа будет работать и не будет виснуть!
Попробуйте сымитировать на примере моей программы, Ваше зависание. Если сложно работать с Вашим большим кодом, давайте разберёмся с ошибкой на примере моего простого маленького кода.
Пример - работает, модернизировал для потоков - тоже все работает устойчиво.
Очень похоже, что действительно где-то еще это FIFO читается.
Надо подумать....
Пример - работает, модернизировал для потоков - тоже все работает устойчиво.
Очень похоже, что действительно где-то еще это FIFO читается.
Надо подумать....
Я вот подумал, когда файл открывается потоком, он же открывается для процесса целиком? или нет?
Открыт Ваш FIFO или нет можно посмотреть командой lsof
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.