Данные, записанные в канал Linux программой 1, иногда дважды считываются программой 2

#c #c #linux #pipe

#c #c #linux #канал

Вопрос:

Я пытаюсь установить межпроцессную связь в Linux с использованием именованных каналов. На первый взгляд кажется, что мой код работает, но я заметил, что иногда данные, записанные в канал «основным» процессом, дважды считываются «дочерним» процессом (на самом деле это две отдельные программы).

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

main.h

 const char * FSCpipe = "/tmp/fscpipe";
int counter = 1;
 

main()

 ::mkfifo(FSCpipe, 0666);
 

OnClick-функция

 QString data = "179.45";
int fd;
char msg[10];

fd = ::open(FSCpipe, O_WRONLY | O_NONBLOCK);
for(int i = 0; i < data.length(); i  ) {
    msg[i] = data.at(i).toLatin1();
}
msg[data.length()] = '';
::write(fd, msg, strlen(msg) 1);
::close(fd);
qDebug() << QString("Counter: %1").arg(counter);
counter  ;
 

Программа 2 (только для чтения, запускается второй) запускается в новом терминале. Код:

 int main(int argc, char **argv)
{    
   int fd;
   const char * FSCpipe = "/tmp/fscpipe";
   char data[10];
   size_t nbytes;
   nbytes = sizeof(data);
   while(1) {
      fd = open(FSCpipe, O_RDONLY);
      ssize_t bytesread = read(fd, data, nbytes);
      printf("received: %sn", data);
      close(fd);
      printf("Counter: %d ", counter);
      printf("chars: %dn", bytesread);
      counter  ;
   }
   return(0);
}
 

Иногда я замечал странное поведение, чувствуя, что считывается больше данных, чем записывается. Поэтому я реализовал независимый счетчик в обеих программах. Когда я нажимаю кнопку в программе 1, данные отправляются по каналу, и счетчик увеличивается. Когда программа 2 получает и выводит данные в терминал, ее счетчик также увеличивается. После нескольких нажатий на кнопку в программе 1 я вижу более высокое значение счетчика в программе 2, указывающее на то, что он читает чаще, чем записывает программа 1. Почему это так?

Кроме того, строка данных должна содержать специальные символы, закодированные в UTF-8, например:

 QString data = "197,45 xc2xb5m";
 

Как я должен преобразовать строку, чтобы правильно отправить ее по каналу?

Спасибо, что помогли мне!

Комментарии:

1. Вы не проводите никакой проверки ошибок.

2. Почему это не имеет значения? Строка C определяется как char значения, заканчивающиеся '' символьным значением. Когда вы оставляете это завершение выключенным, вы вызываете неопределенное поведение, потому что без этого завершения это не строка , и эта ссылка не применяется — strlen() вычисляется только длина строки.

3. read может не считывать 10 байт, вы должны проверить возвращаемое значение

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

5. 0 означает конец файла, поскольку ничего не было прочитано, буфер не изменился, поэтому его печать приведет к дублированию данных

Ответ №1:

Я нашел здесь некоторую полезную информацию, в которой говорится:

«Если все файловые дескрипторы, относящиеся к концу записи канала, были закрыты, то при попытке чтения (2) из канала будет отображаться конец файла (чтение (2) вернет 0)»

Я извлек fd = ::open(...); и ::close(fd); из моей onclick-функции в программе 1 и поместил их в mainwindow-constructor и mainwindow-close-function соответственно. Таким образом, конец записи всегда открыт, и программа 2 работает по назначению.

Спасибо всем за вашу помощь.