Как читать длинное из трубы? - PullRequest
3 голосов
/ 06 июля 2011

Это касается безымянных каналов в межпроцессном взаимодействии. У меня есть канал, и один процесс хранит в нем значение, а другой хочет прочитать это значение числового типа int или long.

Здесь хорошо описано http://tldp.org/LDP/lpg/node11.html как создавать каналы в C. Мой вопрос - как читать long или int из канала.

выдержка из вышеупомянутой страницы:

/* Read in a string from the pipe */
int nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);

ну, в общем, я понятия не имею, как трактуется канал в C (это как файл?) И как я могу читать из него данные, отличные от строки.

Ответы [ 7 ]

2 голосов
/ 06 июля 2011

Вы не можете "действительно" прочитать long из трубы.Вы читаете последовательность байтов из канала, и если вы можете определить какой-либо протокол, для которого длинны представляют эти байты, то вы прочитали long.

Предполагая, что оба конца канала используют одно и то же хранилищепредставление для long, которым они являются, если они были скомпилированы с одним и тем же компилятором для одной и той же архитектуры, или в этом отношении с другими компиляторами, но с использованием одного и того же ABI, тогда вы можете write(fd, &src_long, sizeof(long)); на одном конце и read(fd, &dst_long, sizeof(long)); вдругой конец.Плюс или минус обычная путаница, чтобы гарантировать, что ввод / вывод не завершится раньше.

1 голос
/ 06 июля 2011

Поскольку оба конца вашей трубы находятся на одной машине, вам не нужно беспокоиться о различиях в архитектуре машины;если вы изменили вопрос, чтобы обсудить сокеты, вам придется об этом беспокоиться.

Вы можете записать long в канал, используя:

long l = 0x01020304L
if (write(pipe_w_fd, &l, sizeof(l)) != sizeof(l))
    ...handle error...

И вы можете прочитать значение изтруба с использованием:

long l;
if (read(pipe_r_fd, &l, sizeof(l)) != sizeof(l))
    ...handle error...

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

1 голос
/ 06 июля 2011

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

Вы прочитали бы структуру данных так же, как и из любого другого файла.Это можно сделать с помощью scanf, fstream >> или с помощью read () и объединения.

0 голосов
/ 06 июля 2011

Вы можете сделать это:

long l;

if (read(fd[0], &l, sizeof(l)) != sizeof(l))
{
   /* TODO: handle this */
}

Если ваш тип сериализации равен long, вы теряете здесь некоторую гибкость, поскольку вполне возможно, что тот, кто читает эти данные, получит другой порядок байтов илидругой размер для long.В качестве примера представьте, что вы fork и dup2(fd[1], 1) t в итоге exec получаете команду SSH в дочернем процессе ... Теперь данные потенциально поступают с другого компьютера, и будут проблемы.Чтобы избежать этого, вы можете сделать что-то вроде этого:

/* Type of l has a predictable size. */
uint32_t l;

if (read(fd[0], &l, sizeof(l)) != sizeof(l))
{
   /* TODO: handle this */
}

/* Convert byte order of what we just read */
l = ntohl(l);

На самом деле это немного странно для read с 32-битными приращениями ... Что вы должны рассмотреть, так это придумать формат сообщения ичитать большие куски данных за один раз.Хороший способ сделать это - для каждого количества информации иметь заголовок, который указывает размер последующего сообщения, тип сообщения и т. Д. Или, если вы не находите это привлекательным, вы можете рассмотреть вопрос о том, чтобы ваша сериализация была текстовой.Это также обеспечило бы достойный ответ на проблему с порядком байтов.

0 голосов
/ 06 июля 2011

Обрабатывается как файл.Я хотел бы прочитать на Scanf, чтобы увидеть, какие данные вы можете легко проанализировать.Такие вещи, как целые числа и целые числа в шестнадцатеричном или октавном выражении, могут быть легко проанализированы, даже указатели могут быть проанализированы.Длинные не так просты, но вы можете просто разобрать длинный из строки (% s) и сохранить его в длинном позже.

http://beej.us/guide/bgc/output/html/multipage/scanf.html

0 голосов
/ 06 июля 2011

ну, в общем, я понятия не имею, как трактуется канал в C (это как файл?)

Да.

и как я могу читать из него данные, кроме строки.

Это наивный случай, в котором предполагается, что long является двоичным и имеет одинаковый размер в системе. Если long был записан как строка, прочитайте строку и найдите long.

long mylong;
int nbytes = read(fd[0], &mylong, sizeof(long));
0 голосов
/ 06 июля 2011

Зависит от того, как оно отправлено.Если у вас есть какое-то соглашение о протоколе / кадрировании, вам придется прочитать фрейм, а затем извлечь int.Если вы отправляете только саму int, вы можете прочитать sizeof (int) байтов, а затем напрямую использовать байты в буфере:

int foo = *((int*) readbuffer);

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

...