#c #process #fork
Вопрос:
У меня проблема с программой, которая использует вилки. Я должен сыграть в простую игру, в которой у меня есть 2 космических корабля, один из которых управляется пользователем (только вверх и вниз), а другой-компьютером (который подпрыгивает каждый раз, когда касается края). Каждый космический корабль должен управляться другим процессом. В дополнение к кораблям должна быть возможность стрелять (пуля управляется другим процессом). Я все понял, единственная проблема в том, что я не понимаю, почему космический корабль, управляемый пользователем, не стреляет, может кто-нибудь сказать мне, где я ошибаюсь?
#include lt;stdio.hgt; #include lt;curses.hgt; #include lt;stdlib.hgt; #include lt;unistd.hgt; #define SHOOT 32 /*Sparare */ #define UP 65 /* Cursore sopra */ #define DW 66 /* Cursore sotto */ #define MAXX 80 /* Dimensione dello schermo di output (colonne) */ #define MAXY 20 /* Dimensione dello schermo di output (righe) */ #define DELAY 80000 /* Ritardo nel movimento delle vespe (da adattare) */ /* Prototipi funzioni adoperate */ void Enemy(int pipeout); void Spaceship(int pipeout); void Area(int pipein); void Proiettile(int pipeout, int x, int y); /* Struttura adoperata per veicolare le coordinate */ struct position { char c; /* Identificatore dell'entità che invia i dati */ int x; /* Coordinata X */ int y; /* Coordinata Y */ }; /* ---------------------------------------------------------------------- Funzione principale del programma ---------------------------------------------------------------------- */ int main() { int p[2]; /* Descrittori pipe */ int pidN; /* Pid 'Enemy' */ int pidA; /* Pid 'Spaceship' */ initscr(); /* Inizializza schermo di output */ noecho(); /* Imposta modalità della tastiera */ curs_set(0); /* Nasconde il cursore */ pipe(p); /* Creazione pipe */ /* Creo il primo processo figlio 'Enemy' */ pidN = fork(); /* Se il pid == 0 -gt; si tratta del processo 'Enemy' */ if(pidN==0) { /* ed eseguo quindi la relativa funzione di gestione */ close(p[0]); /* chiusura del descrittore di lettura */ Enemy(p[1]); /* invocazione funzione nemico */ } else { /* Altrimenti sono ancora nel processo padre e creo il processo 'Spaceship' */ pidA=fork(); /* Se il pid == 0 -gt; si tratta del processo 'Spaceship' */ if(pidA==0) { /* Visualizzo L'Spaceship nella posizione iniziale */ mvprintw(MAXY/2,0,"#"); /* ed eseguo quindi la relativa funzione di gestione */ close(p[0]); /* chiusura del descrittore di lettura */ Spaceship(p[1]); /* invocazione funzione astronave */ } else { /* Sono ancora nel processo padre */ close(p[1]); /* chiusura del descrittore di scrittura */ Area(p[0]); /* invocazione funzione area */ } } /* Termino i processi Spaceship e Enemy */ kill(pidN,1); kill(pidA,1); /* Ripristino la modalità di funzionamento usuale */ endwin(); /* Termino il gioco ed esco dal programma */ printf("nnnGAME OVERnnn"); return 0; } /* ---------------------------------------------------------------------- Funzione 'Enemy' ---------------------------------------------------------------------- */ void Enemy(int pipeout) { struct position enemy; //int deltax; /* Spostamento orizzontale */ int deltay=1; /* Spostamento verticale */ enemy.x = MAXX; /* Coordinata X iniziale */ enemy.y = MAXY/2; /* Coordinata Y iniziale */ enemy.c ='
Комментарии:
1. Чтобы было ясно, вы говорите, что космический корабль игрока правильно реагирует на команды вверх / вниз, но не на команды стрельбы, верно?
Ответ №1:
Это выглядит ужасно подозрительно:
close(pipeout); /* chiusura del descrittore di lettura */ Proiettile(pipeout,apos.x,apos.y); /* invocazione funzione proiettile */
Разветвленный дочерний элемент закрывает файловый дескриптор pipeout
, но затем передает его функции Proiettile()
, которая пытается взаимодействовать с другими процессами путем записи в него. Мне непонятно, почему вы закрываете FD, но эта комбинация, очевидно, не будет работать для запущенного процесса Proiettile()
, чтобы что-либо сообщить.
Я отмечаю, что если бы вы правильно проверяли возвращаемые значения ваших системных вызовов, особенно ваших write()
вызовов, то ваша программа могла бы рассказать вам о самой проблеме. Кроме того, здесь есть и другие проблемы, связанные с (отсутствием) протокола, с помощью которого взаимодействуют ваши различные процессы, и риском торпедирования частичной записью и чтением, но это не то, о чем вы спрашивали.
Комментарии:
1. OMG Большое вам спасибо, я не знаю, как я этого не заметил :/ Что вы имеете в виду под отсутствием протокола?
2. @Zeld, похоже, по каналу передаются сообщения нескольких форматов. Как же тогда получателю узнать, что он получил? Как узнать даже о том, что он получил целое сообщение в первую очередь, а не больше или меньше? Если ваши данные не являются намного более однородными, чем кажутся, вам потребуется структурировать данные, передаваемые по каналу, в соответствии с протоколом, который передает эти данные, а возможно, и другие.
; /* Carattere identificativo */ /* Comunico le coordinate iniziali al processo padre */ write(pipeout,amp;enemy,sizeof(enemy)); while(1){ /* Se supero area Y schermo inverto il movimento */ if(enemy.y deltay lt; 1 || enemy.y deltay gt; MAXY){ deltay = -deltay; } /* Movimento Y */ enemy.y = deltay; /* Comunico le coordinate correnti al processo padre */ write(pipeout,amp;enemy,sizeof(enemy)); /* Inserisco una pausa per rallentare il movimento */ usleep(DELAY); } } /* ---------------------------------------------------------------------- Funzione 'Spaceship' - Movimento tramite i tasti cursore ---------------------------------------------------------------------- */ void Spaceship(int pipeout) { struct position apos; int p[2]; apos.x = 0; /* Coordinata X iniziale */ apos.y = MAXY/2; /* Coordinata Y iniziale */ apos.c='#'; /* Carattere identificativo astronave*/ int pidP; /* Comunico al processo padre le coordinate iniziali dell'astronave */ write(pipeout,amp;apos,sizeof(apos)); /* Lettura dei tasti cursore */ while(1) { char c; c = getch(); if (c==UP amp;amp; apos.y gt; 0){ apos.y-=1; } if(c==DW amp;amp; apos.y lt; MAXY - 1){ apos.y =1; } if(c==SHOOT) { pidP = fork(); if(pidP==0) { flash(); mvprintw(apos.y 1,apos.x,"-"); refresh(); /* ed eseguo quindi la relativa funzione di gestione */ close(pipeout); /* chiusura del descrittore di lettura */ Proiettile(pipeout,apos.x,apos.y); /* invocazione funzione proiettile */ } } /* Comunico al processo padre le coordinate dell'astronave */ write(pipeout,amp;apos,sizeof(apos)); } kill(pidP,1); } /* ---------------------------------------------------------------------- Funzione relativa al processo di visualizzazione e controllo ---------------------------------------------------------------------- */ void Area(int pipein) { struct position enemy, spaceship, dato_letto, proiettile; int collision=0; do { // Leggo dalla pipe / read(pipein,amp;dato_letto,sizeof(dato_letto)); switch((char) dato_letto.c){ case '
Комментарии:
1. Чтобы было ясно, вы говорите, что космический корабль игрока правильно реагирует на команды вверх / вниз, но не на команды стрельбы, верно?
Ответ №1:
Это выглядит ужасно подозрительно:
Разветвленный дочерний элемент закрывает файловый дескриптор pipeout
, но затем передает его функции Proiettile()
, которая пытается взаимодействовать с другими процессами путем записи в него. Мне непонятно, почему вы закрываете FD, но эта комбинация, очевидно, не будет работать для запущенного процесса Proiettile()
, чтобы что-либо сообщить.
Я отмечаю, что если бы вы правильно проверяли возвращаемые значения ваших системных вызовов, особенно ваших write()
вызовов, то ваша программа могла бы рассказать вам о самой проблеме. Кроме того, здесь есть и другие проблемы, связанные с (отсутствием) протокола, с помощью которого взаимодействуют ваши различные процессы, и риском торпедирования частичной записью и чтением, но это не то, о чем вы спрашивали.
Комментарии:
1. OMG Большое вам спасибо, я не знаю, как я этого не заметил :/ Что вы имеете в виду под отсутствием протокола?
2. @Zeld, похоже, по каналу передаются сообщения нескольких форматов. Как же тогда получателю узнать, что он получил? Как узнать даже о том, что он получил целое сообщение в первую очередь, а не больше или меньше? Если ваши данные не являются намного более однородными, чем кажутся, вам потребуется структурировать данные, передаваемые по каналу, в соответствии с протоколом, который передает эти данные, а возможно, и другие.
: // Enemy / // Cancello il precedente carattere visualizzato / mvaddch(enemy.y,enemy.x,' '); // Aggiorno le coordinate relative alla nuova posizione / enemy=dato_letto; break; case '#' : // Spaceship / // Cancello il precedente carattere visualizzato / mvaddch(spaceship.y,spaceship.x,' '); // Aggiorno le coordinate relative alla nuova posizione / spaceship=dato_letto; break; case '-' : // Proiettile/ // Cancello il precedente carattere visualizzato / mvaddch(proiettile.y,proiettile.x,' '); // Aggiorno le coordinate relative alla nuova posizione / proiettile=dato_letto; break; } //if(enemy.x != 1 || enemy.y !=0 ) mvaddch(dato_letto.y,dato_letto.x,dato_letto.c); refresh(); /* Il ciclo si ripete finchè le vite del contadino terminano */ } while(!collision); } void Proiettile(int pipeout,int x, int y) { struct position proiettile; int pidP=getpid(); int deltax=1; proiettile.x = x; /* Coordinata X iniziale */ proiettile.y = y; /* Coordinata Y iniziale */ proiettile.c='-'; write(pipeout,amp;proiettile,sizeof(proiettile)); while(1){ /* Se supero area X schermo inverte il movimento */ if(proiettile.x deltax gt; MAXX){ //CHIUDI PROCESSO kill(pidP,1); } /* Movimento X */ proiettile.x = deltax; /* Comunico le coordinate correnti al processo padre */ write(pipeout,amp;proiettile,sizeof(proiettile)); /* Inserisco una pausa per rallentare il movimento */ usleep(DELAY); } }
Комментарии:
1. Чтобы было ясно, вы говорите, что космический корабль игрока правильно реагирует на команды вверх / вниз, но не на команды стрельбы, верно?
Ответ №1:
Это выглядит ужасно подозрительно:
Разветвленный дочерний элемент закрывает файловый дескриптор pipeout
, но затем передает его функции Proiettile()
, которая пытается взаимодействовать с другими процессами путем записи в него. Мне непонятно, почему вы закрываете FD, но эта комбинация, очевидно, не будет работать для запущенного процесса Proiettile()
, чтобы что-либо сообщить.
Я отмечаю, что если бы вы правильно проверяли возвращаемые значения ваших системных вызовов, особенно ваших write()
вызовов, то ваша программа могла бы рассказать вам о самой проблеме. Кроме того, здесь есть и другие проблемы, связанные с (отсутствием) протокола, с помощью которого взаимодействуют ваши различные процессы, и риском торпедирования частичной записью и чтением, но это не то, о чем вы спрашивали.
Комментарии:
1. OMG Большое вам спасибо, я не знаю, как я этого не заметил :/ Что вы имеете в виду под отсутствием протокола?
2. @Zeld, похоже, по каналу передаются сообщения нескольких форматов. Как же тогда получателю узнать, что он получил? Как узнать даже о том, что он получил целое сообщение в первую очередь, а не больше или меньше? Если ваши данные не являются намного более однородными, чем кажутся, вам потребуется структурировать данные, передаваемые по каналу, в соответствии с протоколом, который передает эти данные, а возможно, и другие.