Определите размер канала без вызова read () - PullRequest
8 голосов
/ 16 сентября 2008

Мне нужна функция с именем SizeOfPipe (), которая должна возвращать размер канала. Я хочу только знать, сколько данных находится в канале, а не фактически читать данные из самого канала.

Я думал, что следующий код будет работать

fseek (pPipe, 0 , SEEK_END);
*pBytes = ftell (pPipe);
rewind (pPipe);

но fseek не работает над дескрипторами файлов. Другим вариантом было бы прочитать канал и записать данные обратно, но, если возможно, хотелось бы избежать этого, есть предложения?

Ответы [ 12 ]

17 голосов
/ 16 сентября 2008

В зависимости от вашей реализации Unix, ioctl / FIONREAD может сделать свое дело

err = ioctl(pipedesc, FIONREAD, &bytesAvailable);

Если это не возвращает код ошибки для "неверного аргумента" (или любой другой ошибки), bytesAvailable содержит объем данных, доступных для разблокирования операций чтения в это время.

5 голосов
/ 16 сентября 2008

Некоторые реализации UNIX возвращают количество байтов, которые можно прочитать в поле st_size после вызова fstat(), но это не переносимо.

4 голосов
/ 16 сентября 2008

К сожалению, система не всегда может знать размер канала - например, если вы перенаправляете длительный процесс в другую команду, исходный процесс может еще не завершиться. В этом случае нет никакого возможного способа (даже теоретически) узнать, сколько еще данных выйдет из него.

Если вы хотите узнать объем данных, в настоящее время доступных для чтения из канала, это может быть возможно, но это будет зависеть от буферизации ОС и других факторов, которые трудно контролировать. Наиболее распространенный подход здесь - просто продолжать чтение, пока не останется ничего (если вы не получите EOF, тогда процесс с исходным кодом еще не завершен). Однако я не думаю, что это то, что вы ищете.

Так что, боюсь, нет общего решения.

2 голосов
/ 16 сентября 2008

Почти никогда не нужно знать, сколько байтов находится в канале: возможно, вы просто хотите выполнить неблокирующее чтение () в канале, т.е. чтобы проверить, есть ли готовые байты, и если так, прочитайте их, но никогда не останавливайтесь и ждите , пока канал не будет готов.

Вы можете сделать это в два этапа. Сначала используйте системный вызов select (), чтобы узнать, доступны ли данные или нет. Пример здесь: http://www.developerweb.net/forum/showthread.php?t=2933

Во-вторых, если select сообщает, что данные доступны, вызовите read () один раз и только один раз с большим размером блока. Он будет читать только , сколько доступно байтов, или до размера вашего блока, в зависимости от того, что меньше. Если select () возвращает true, read () всегда вернется сразу.

2 голосов
/ 16 сентября 2008

Не существует универсального, портативного способа узнать, сколько данных доступно в канале, не читая их. По крайней мере, не в соответствии со спецификациями POSIX.

Трубы недоступны для поиска, и также невозможно вернуть данные в конец канала для чтения.

Трюки, специфичные для платформы, могут быть возможны. Если ваш вопрос зависит от платформы, измените его так, чтобы повысить шансы получить рабочий ответ.

2 голосов
/ 16 сентября 2008

Как правило, невозможно узнать объем данных, которые вы можете прочитать из канала только по одному дескриптору канала. Данные могут поступать через сеть или динамически генерироваться другим процессом. Если вам необходимо знать заранее, вы должны организовать отправку вам информации - через канал или вне канала - каким бы ни был процесс на другом конце канала.

0 голосов
/ 08 апреля 2009

Вы можете обернуть его в объект с буферизацией, которую можно перезаписать. Это было бы возможно только для небольших объемов данных.

Один из способов сделать это в C - это определить stuct и обернуть все функции, работающие на каналах, для вашей структуры.

0 голосов
/ 17 сентября 2008

В Windows вы всегда можете использовать PeekNamedPipe, но я сомневаюсь, что это то, что вы хотите сделать в любом случае.

0 голосов
/ 16 сентября 2008

Не существует портативного способа определить объем данных, поступающих из канала. Единственное, что вы можете сделать, - это читать и обрабатывать данные по мере поступления.

Для этого вы можете использовать что-то вроде кругового буфера

0 голосов
/ 16 сентября 2008

Если вы хотите узнать объем ожидаемых данных, вы всегда можете написать в начале каждого сообщения, отправляемого по каналам, размер сообщения. Так, напишите, например, 4 байта в начале каждого сообщения с длиной ваших данных, а затем прочитайте только первые 4 байта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...