Чтение / запись struct to fifo в C
Я пытаюсь передавать структуры между процессами с помощью именованных каналов. Я застрял при попытке открыть трубу в неблокирующем режиме. Вот мой код для записи в fifo:
void writeUpdate() {
// Create fifo for writing updates:
strcpy(fifo_write, routing_table->routerName);
// Check if fifo exists:
if(access(fifo_write, F_OK) == -1 )
fd_write = mkfifo(fifo_write, 0777);
else if(access(fifo_write, F_OK) == 0) {
printf("writeUpdate: FIFO %s already existsn", fifo_write);
//fd_write = open(fifo_write, O_WRONLY|O_NONBLOCK);
}
fd_write = open(fifo_write, O_WRONLY|O_NONBLOCK);
if(fd_write < 0)
perror("Create fifo error");
else {
int num_bytes = write(fd_write, routing_table, sizeof(routing_table));
if(num_bytes == 0)
printf("Nothing was written to FIFO %sn", fifo_write);
printf("Wrote %d bytes. Sizeof struct: %dn", num_bytes,sizeof(routing_table)+1);
}
close(fd_write);
}
Routing_table-это указатель на мою структуру, он выделен, поэтому нет проблем с именем fifo или smth, как это. Если я открываю fifo без опции O_NONBLOCK, он записывает smth в первый раз, но затем блокирует, потому что у меня тоже возникают проблемы с чтением структуры. А после первого раза ... первоначальный ФИФО создается, но появляются другие ФИФО, названные '.', '..". С установленным параметром O_NONBLOCK он создает fifo, но всегда выдает ошибку: "нет такого устройства или адреса". Есть идеи, почему это происходит? Спасибо.
EDIT: хорошо, теперь мне ясно, как открыть fifo, но у меня есть еще одна проблема, на самом деле чтение/запись структуры в fifo была моей проблемой с самого начала. Мой код для чтения структуры:
void readUpdate() {
struct rttable *updateData;
allocate();
strcpy(fifo_read, routing_table->table[0].router);
// Check if fifo exists:
if(access(fifo_read, F_OK) == -1 )
fd_read = mkfifo(fifo_read, 777);
else if(access(fifo_read, F_OK) == 0) {
printf("ReadUpdate: FIFO %s already existsn Reading from %sn", fifo_read, fifo_read);
}
fd_read = open(fifo_read, O_RDONLY|O_NONBLOCK);
int num_bytes = read(fd_read, updateData, sizeof(updateData));
close(fd_read);
if(num_bytes > 0) {
if(updateData == NULL)
printf("Read data is null: yes");
else
printf("Read from fifo: %s %dn", updateData->routerName, num_bytes);
int result = unlink(fifo_read);
if(result < 0)
perror("Unlink fifo errorn");
else {
printf("Unlinking successful for fifo %sn", fifo_read);
printf("Updating table..n");
//update(updateData);
print_table_update(updateData);
}
} else
printf("Nothing was read from FIFO %sn", fifo_read);
}
Он открывает ФИФО и пытается читать, но кажется, что в нем ничего нет. fifo, хотя в writeUpdate в первый раз он говорит, что написал 4 байта (это тоже кажется неправильным). При чтении, первый раз он печатает 'A' и затем число_байт всегда
Моя структура выглядит так:
typedef struct distance_table {
char dest[20]; //destination network
char router[20]; // via router..
int distance;
} distance_table;
typedef struct rttable {
char routerName[10];
char networkName[20];
struct distance_table table[50];
int nrRouters;
} rttable;
struct rttable *routing_table;
1 ответ:
"Нет такого устройства или адреса" - это сообщение об ошибке
ENXIO
. Если вы посмотрите наopen
man page, вы увидите, что эта ошибка сообщается, в частности, если:Что в точности соответствует вашей ситуации. Таким образом, поведение, которое вы видите, является нормальным: вы не можете писать (без блокировки) в канал, который не имеет считывателей. Ядро не будет буферизоваться ваши сообщения, если ничего не подключено к трубе для чтения.O_nonblock / O_WRONLY установлен, именованный файл-это FIFO, а не процесс файл открыт для чтения. (...)
Поэтому убедитесь, что вы запускаете " потребитель (ы) "перед вашим" производителем", или удалите неблокирующую опцию на производителе.
Кстати: использование
access
в большинстве случаев означает открытие себя для времени проверки до времени использования проблем. Не используйте его. Попробуйтеmkfifo
- если это работает, Вы хороши. Если это не удается сEEXISTS
, Вы тоже хороши. Если это не сработает в противном случае, убирайтесь и спасайтесь.Для второй части ваш вопрос, это действительно полностью зависит от того, как именно структурированы данные, которые вы пытаетесь отправить. Сериализация случайной структуры в языке C совсем не проста, особенно если она содержит переменные данные (например,
char *
s).Если ваша структура содержит только примитивные типы (и никаких указателей), и обе стороны находятся на одной машине (и компилируются одним компилятором), то raw
write
с одной стороны иread
с другой из всей структуры должны работать.Вы можете посмотреть на методы C - сериализации для более сложных типов данных, например.
Что касается вашего конкретного примера: вы путаетесь между указателями на ваши структуры и простыми структурами.
На стороне записи у вас есть:
int num_bytes = write(fd_write, routing_table, sizeof(routing_table));
Это неверно, так как
routing_table
является указателем. Вам нужно:int num_bytes = write(fd_write, routing_table, sizeof(*routing_table)); // or sizeof(struct rttable)
То же самое на стороне чтения. На размер приема вы также не выделяете
updateData
, насколько я могу судить. Вам тоже нужно это сделать (сmalloc
, и помните освободить его).struct rttable *updateData = malloc(sizeof(struct rrtable));