Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: Arvigeus в Apr 18, 2011, 11:05



Титла: [решен] fork() проблеми
Публикувано от: Arvigeus в Apr 18, 2011, 11:05
Здравейте! Опитвам се да съставя програма, която създава два процеса: единият чете, другият извежда. Проблемът е, че  увисва още при започване. Ето го кодът, ако някой може да ми каже какъв е проблема:
Код
GeSHi (C):
  1. #include <unistd.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. struct point {
  6.  int ID;
  7.  char* text;
  8.  int lock;
  9.  int readed;
  10. }*p;
  11.  
  12. extern getmem(int memory);
  13. extern testandset(int *lock);
  14.  
  15. char *messages[] = {
  16.  "Segmantation Fault",
  17.  "Unhandled Exception",
  18.  "Stack Overflow",
  19.  "Core Dump",
  20.  "General Protection Fault",
  21.  "Page Fault",
  22.  "Storage Violation",
  23.  "Bounds Check Fault",
  24.  "Null Pointer Exception",
  25.  "Divide Fault",
  26.  "NMI Interrupt",
  27.  "Overflow Trap",
  28.  "Invalid Opcode Fault",
  29.  "Runtime Error",
  30.  "Unspecified Fatal Error",
  31.  "Nuff said",
  32.  "Invalid Task State Segment Fault",
  33.  "Not Present Fault",
  34.  "Access Violation",
  35.  "Invalid Option",
  36.  "" /* The last message will never got read, so put it empty string is used */
  37. };
  38.  
  39. int main(void) {
  40.  int pid, id=-1;
  41.  
  42.  p = (struct point *)getmem(666);
  43.  p->readed = 1;
  44.  p->lock = 0;
  45.  p->ID = 0;
  46.  
  47.  switch(fork()) {
  48.    case -1: /* Error */
  49.      printf("Fork error! Exiting...\n");
  50.      return 1;
  51.      break;
  52.    case 0: /* Child -  Reading Messages */
  53.      while(messages[id+1]!=NULL) {
  54.      while (testandset(&(p->lock))) {}
  55.      if(p->ID!=id) {
  56.        printf("%s\n", p->text);
  57.        if(id==-1) sleep(3);
  58.        else sleep(1);
  59.        id = p->ID;
  60.      }
  61.      p->readed = 1;
  62.      p->lock = 0;
  63.      }
  64.      printf("\n\tEnd of child process\n");
  65.      break;
  66.  default: /* Parrent - Generate Messages */
  67.    while(messages[p->ID]!=NULL) {
  68.      while(p->readed==0) {}
  69.      while (testandset(&(p->lock))) {}
  70.      p->text = messages[p->ID];
  71.      p->ID++;
  72.      p->readed = 0;
  73.      p->lock = 0;
  74.    }
  75.    wait();
  76.    printf("\n End of parent process\n");
  77.  }
  78.  return 0;
  79. }
???


Титла: Re: fork() проблеми
Публикувано от: bop_bop_mara в Apr 18, 2011, 11:15
Аз ли греша, или това "бащата пише, детето чете" става през структурата? Ако е така, прочети отново какво се случва при fork(), а след това се заеми и с четене за shared memory (или IPC като цяло) :).

Също така, за по-добър стил, проверявай дали резултата, който върне fork() не е -1 (т.е. грешка), недей да разделяш случаите просто на 0 и не-0 :)


Титла: Re: fork() проблеми
Публикувано от: mpakmop в Apr 18, 2011, 11:37
А защо test_and_set() винаги връща 0? Така програмата никога няма да влезе в while циклите по-долу.


Титла: Re: fork() проблеми
Публикувано от: bop_bop_mara в Apr 18, 2011, 11:48
А защо test_and_set() винаги връща 0? Така програмата никога няма да влезе в while циклите по-долу.
Не е това фаталното в случая, а и употребата не е за условие за влизане в цикъл, а while(test_and_set()) {} - т.е. за ключалките.

Edit: Но, да, и механизмът за заключване "куца".


Титла: Re: fork() проблеми
Публикувано от: bvbfan в Apr 18, 2011, 12:59
Цитат на: Arvigeus
      while(p->ID<20) {
        while(test_and_set()) {}
        if(p->ID!=id) {
          printf( "Message %d:\t%s\n", p->ID, p->text);
          id = p->ID;
        }
        p->readed = 1;
        p->lock = 1;
      }

Безкраен цикъл, може би p->ID++ ?
Освен това, char text[50]; strcpy(p->text, messages[0]);  ??? много тъпо, когато ползваш статични текстове, както в случая, не използвай буфери, камо ли strcpy, поне sprintf( p->text, "%.49s", message[0]); може просто
struct point {
  int ID;
  const char *text;
  int lock;
  int readed;
}*p;
 
static const char *messages[] = { ... }; p->text = message[0];


Титла: Re: fork() проблеми
Публикувано от: Arvigeus в Apr 18, 2011, 22:38
Благодаря за съветите! Просто от ужасно много време не съм ползвал C и всеки път ми е малко странно.
Коригирах си горният пост. Това с test_and_set() явно се е объркало при копирането, защото иначе си беше "правилния" вариант.
Засега програмата  пак не работи (стига си до същата точка)...


Титла: Re: fork() проблеми
Публикувано от: bop_bop_mara в Apr 18, 2011, 23:36
Благодаря за съветите! Просто от ужасно много време не съм ползвал C и всеки път ми е малко странно.
Коригирах си горният пост. Това с test_and_set() явно се е объркало при копирането, защото иначе си беше "правилния" вариант.
Засега програмата  пак не работи (стига си до същата точка)...
OK, ще ти го кажа направо, когато процес създаде процес-дете, адресното пространство се копира, а не се споделя (няма как да е иначе, замисли се какъв хаос би настъпил). Няма как да ти работи замисъла на програмата с този код. Прочети какво прави fork(), прочети какво е IPC и си избери някой механизъм (например shared memory).


Титла: Re: fork() проблеми
Публикувано от: sdr в Apr 19, 2011, 14:01
pthread.h му е майката за това което се опитваш да направиш. Нишките за разлика от процесите поделят общо адресно пространство. Ако се каниш да си отделяш IO-то от "бизнес логиката" по-добре ползвай разните му select/poll диревати :)


Титла: Re: [решен] fork() проблеми
Публикувано от: Arvigeus в Apr 20, 2011, 19:02
Проблемът е решен. За съжеление поради ограниченото ми време използвах библиотека, предоставена ми от училище, която май не спазва много-много стандартите. Редактирал съм кода, във "работеща" версия, само дето няма да може да ви се компилира без тази библиотека. Ако някой все пак прояви някакъв интерес, може да ми пише. Но задачата наистина е тривиална, така че...