Я работаю над заданием для своего класса по распределенным системам. Я учусь в магистратуре по компьютерным наукам, но моя специальность в программировании — .NET, и я работаю над проектом, который требует довольно глубоких знаний Unix, что ставит меня в тупик.
Задание реализует API протокола флеш-канала. Поэтому я пишу небольшую библиотеку функций, которую другие приложения могут реализовать для использования обмена данными по каналу. Я настроил его так, что при вызове функции инициализации он разветвляет дочерний процесс, который действует как сервер для входящих сообщений. Дочерний процесс взаимодействует с родительским процессом, отправляя входящие данные родительскому процессу через канал.
Это работает нормально, если сообщения отправляются и принимаются по одному; например.,
отправить -> получить -> отправить -> получить -> и т.д.
Однако, если несколько сообщений отправлены до выполнения каких-либо приемов; например.,
отправить -> отправить -> отправить -> получить
потом запутается. Конкретно первое сообщение принимается корректно, но когда захожу получать второе сообщение, программа зависает и ее нужно убивать. Я много искал в Интернете и часами занимался этим, но не добился большого прогресса.
Программа в целом слишком велика, чтобы показывать ее здесь, но вот наиболее важные фрагменты. Вот часть, где я запускаю сервер и получаю сообщения. Обратите внимание на строку
write(fd[1], буфер, (strlen(буфер)+1));
-- Я думаю, что это хороший кандидат на роль источника проблемы здесь, но не уверен, что делать по-другому. (Пробовал fwrite(), и это вообще не сработало.)
fd = malloc(2 * sizeof(int));
int nbytes;
if (pipe(fd) < 0) {
perror("Could not create pipe");
return -1;
}
pID = fork();
if (pID < 0) {
perror("Failed to fork");
return -1;
} else if (pID == 0) { // child
close(fd[0]); // close input side of pipe
int cc;
int fsize;
struct sockaddr_in from;
int serials[500];
int i;
for (i = 0; i < 500; i++) serials[i] = 0;
char buffer[2048];
while (1) {
fsize = sizeof(from);
cc = recvfrom(socketNo, buffer, 2048, 0, (struct sockaddr*)&from, &fsize);
if (cc < 0) perror("Receive error");
datagram data = decodeDatagram(buffer);
if (serials[data.serial] == 0) {
write(fd[1], buffer, (strlen(buffer)+1));
serials[data.serial] = 1;
}
}
} else { // parent
close(fd[1]); // close output side of pipe
return 0;
}
(Массив «serials» предназначен для того, чтобы не пересылать повторяющиеся сообщения, поскольку сообщения отправляются несколько раз для повышения надежности. Я знаю, что фиксированный размер для этого массива не является хорошей практикой, но тесты для этого назначения не отправляют столько сообщений, поэтому в данном контексте нормально)
Начало функции приема выглядит так:
int fRecv(int* id, char* buf, int nbytes) {
checkDatagramTable(*id);
char* tbuf = malloc((nbytes + 9) * sizeof(char));
int rbytes = read(fd[0], tbuf, nbytes + 9);
«+9» предназначен для размещения дополнительной информации, которая упаковывается вместе с отправляемым сообщением для упорядочивания каналов с флешем. Это также довольно схематичная область, но выделение большего пространства для большей уверенности не помогло решить проблему.
Я знаю, что здесь довольно много посторонних вещей, ссылок на другие функции и т. д. Но проблема, безусловно, заключается в том, как я передаю данные, поэтому источник моей проблемы должен лежать где-то там.
Заранее спасибо за вашу помощь; это действительно ценится.
buffer
каждый проход по циклуwhile(1)
— почему? Я не понимаю, почему он распределяется динамически, а не распределяется в стеке, и я не понимаю, почему он сохраняется вне этой функции. - person sarnold   schedule 20.11.2011strace(1)
может быть действительно полезным при поиске проблем. Это как бесплатнаяprintf(3)
строка для каждого системного вызова. - person sarnold   schedule 20.11.2011