#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 работает по назначению.
Спасибо всем за вашу помощь.