Автор Тема: Малко С Help  (Прочетена 1075 пъти)

Whisper

  • Напреднали
  • *****
  • Публикации: 128
  • Distribution: Ubuntu 8.10
  • Window Manager: Gnome
    • Профил
    • WWW
Малко С Help
« -: Dec 29, 2008, 10:57 »
Трябва да направя 5 процеса, като всеки процес трябва чрез канал да връща ID-то си на родителския.
Това което съм направил до сега ми връща Bad File Descriptor и незнам как да поправя тази грешка.Кода не е никак сложен :)

Код:
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>

int buf[5];

main()
{
int i,pid1,pid2,pid3,pid4,pid5,fd[2];
pid1=fork();
pipe(fd);
if(pid1==0)
{   
   pid2=fork();
   if(pid2==0)
     {
       pid3=fork();
          if(pid3==0)
           {
              pid4=fork();
                if(pid4==0)
                  {
                     pid5=fork();
                        if(pid5==0)
   {
int id5;
id5=getpid();
close(fd[0]);
write(fd[1],&id5,sizeof(id5));
close(fd[1]);
printf("proc5 ID sent \n");
                           }
                        else
                           {
                                wait();
                                close(fd[1]);
                                if(read(fd[0],&i,sizeof(i))==-1)
                                {
                                   perror("Read ID5");
                                }
                                buf[4]=i;
                                printf("proc5 ID %d\n",i);
                                close(fd[0]);
                                int id4=getpid();
                                write(fd[1],&id4,sizeof(id4));
                                close(fd[1]);
                                printf("proc4 ID sent\n");                           
                           }
                  }
        else
                  {
                    wait();
                    close(fd[1]);
                    if(read(fd[0],&i,sizeof(i))==-1)
                    {
                        perror("Read ID4");
                    }
                    buf[3]=i;
                    printf("proc4 ID %d\n",i);
                    close(fd[0]);
                    int id3=getpid();
                    write(fd[1],&id3,sizeof(id3));
                    close(fd[1]);
                    printf("proc3 ID sent\n");   
                  }
   }
          else
            {
               wait();
               close(fd[1]);
               if(read(fd[0],&i,sizeof(i))==-1)
               {
                  perror("Read ID3");
               }
               buf[2]=i;
               printf("proc3 ID %d\n",i);
               close(fd[0]);
               int id2=getpid();
               write(fd[1],&id2,sizeof(id2));
               close(fd[1]);
               printf("proc2 ID sent\n"); 
            }   
     }
    else
      {
         wait();
         close(fd[1]);
         if(read(fd[0],&i,sizeof(i))==-1)
         {
            perror("Read ID2");
         }
         buf[1]=i;
         printf("proc2 ID %d\n",i);
         close(fd[0]);
         int id1=getpid();
         write(fd[1],&id1,sizeof(id1));
         close(fd[1]);
         printf("proc1 ID sent\n");   
      }         
}
else
 {
   wait();
   close(fd[1]);
   if(read(fd[0],&i,sizeof(i))==-1)
   {
      perror("Read ID1");
   }
   buf[0]=i;
   close(fd[0]);
   for(i=0;i<5;i++)
       printf("%d\n",buf[i]);
   
 }
}
Активен

The Anticrist write up the honor roll

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Малко С Help
« Отговор #1 -: Dec 29, 2008, 11:20 »
Да, когато форкнеш нов процес, той унаследява файловите дескриптори на родителският процес. Обаче след това ако примерно отвориш нов или създадеш pipe в родителският процес, child-a не би трябвало да има идея за това.

Та пробва ли да размениш тези два реда:

pid1=fork();
pipe(fd);

----------------------------


FUCKING SHIT!!!

Сега хвърлих едно око на кода, какво си направил бе човек?!?

Няма да стане така.

Първо, няма да стане само с един pipe по този начин по който го правиш, трябва да създадеш 5 отделни pipes, всеки от тях преди съответните fork() функции. Защо това? Защото затваряш единия край където се пише и след това се опитваш да пишеш там, нормално е да се случи случка и нищо да не се изпише:


Код:
...
else
                           {
                                wait();
[b]                                close(fd[1]);[/b]
                                if(read(fd[0],&i,sizeof(i))==-1)
                                {
                                   perror("Read ID5");
                                }
                                buf[4]=i;
                                printf("proc5 ID %d\n",i);
                                close(fd[0]);
                                int id4=getpid();
[b]                            write(fd[1],&id4,sizeof(id4));[/b]
                                close(fd[1]);
                                printf("proc4 ID sent\n");                           
                           }


Но дори да разрешиш този проблем с писането във вече затворен дескриптор, пак ще има проблеми с цялата тарапана. Pipes ще сработят между процес-родител и child process, но не мисля, че ще сработят през серия от forks, с други думи не съм убеден, че можеш да правиш pipe();fork();fork(); и  процесът...ъъъъм *внук* да може да пише и чете във pipe-a създаден от *баба му*.


Другото което е, не можеш да пазиш тези неща в глобалната променлива buf. Това са процеси, а не нишки, процесите си имат собствени адресни пространства. Ако в рамките на един child промениш buf[], то в рамките на процеса-родител въобще няма да се отрази тази промяна. Което прави последният цикъл да изпишеш стойностите на buf[] безсмислен. За целта пробвай някакъв IPC механизъм, но не и по този начин.

От wait() файда нямаш никаква, защото четенето от pipe-a е блокираща операция: докато не се подаде нещо от другия край, тя няма да завърши. Така че ти е гарантирано че ще си прочетеш стойността СЛЕД като процесът-дете ти я изпише. Особено при положение че четеш и пишеш там една 4-байтова стойност, да беше повече можеше да се появят проблеми предполагам и тогава да се налага да се изчаква детето да умре (пак лоша стратегия, но това е друга бира).

Както и да е, така ще сработи:

Код:
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>



int fd[2];
int fd1[2];
int fd2[2];
int fd3[2];
int fd4[2];




main()
{
int i,pid1,pid2,pid3,pid4,pid5;


pipe(fd);
pid1=fork();
if(pid1==0)
{
   pipe(fd4);
   pid2=fork();
   if(pid2==0)
     {
       pipe(fd3);
       pid3=fork();
          if(pid3==0)
           {
              pipe(fd2);
              pid4=fork();
                if(pid4==0)
                  {
                     pipe(fd1);
                     pid5=fork();
                        if(pid5==0)
                           {
                                int id5;
                                id5=getpid();
                                close(fd1[0]);
                                write(fd1[1],&id5,sizeof(id5));
                                close(fd1[1]);
                                printf("proc5 ID sent \n");
                           }
                        else
                           {
                                close(fd1[1]);
                                if(read(fd1[0],&i,sizeof(i))==-1)
                                {
                                   perror("Read ID5");
                                }
                                printf("proc5 ID %d\n",i);
                                close(fd[0]);
                                int id4=getpid();
                                write(fd2[1],&id4,sizeof(id4));
                                close(fd2[1]);
                                printf("proc4 ID sent\n");
                           }
                  }
                else
                  {
                    close(fd2[1]);
                    if(read(fd2[0],&i,sizeof(i))==-1)
                    {
                        perror("Read ID4");
                    }
                    printf("proc4 ID %d\n",i);
                    close(fd1[0]);
                    int id3=getpid();
                    write(fd3[1],&id3,sizeof(id3));
                    close(fd3[1]);
                    printf("proc3 ID sent\n");
                  }
           }
          else
            {
               close(fd3[1]);
               if(read(fd3[0],&i,sizeof(i))==-1)
               {
                  perror("Read ID3");
               }
               printf("proc3 ID %d\n",i);
               close(fd[0]);
               int id2=getpid();
               write(fd4[1],&id2,sizeof(id2));
               close(fd4[1]);
               printf("proc2 ID sent\n");
            }
     }
    else
      {
         close(fd4[1]);
         if(read(fd4[0],&i,sizeof(i))==-1)
         {
            perror("Read ID2");
         }
         printf("proc2 ID %d\n",i);
         close(fd4[0]);
         int id1=getpid();
         write(fd[1],&id1,sizeof(id1));
         close(fd[1]);
         printf("proc1 ID sent\n");
      }
}
else
 {
   close(fd[1]);
   if(read(fd[0],&i,sizeof(i))==-1)
   {
      perror("Read ID1");
   }
   printf("proc1 ID %d\n",i);

   close(fd[0]);
 }
}
« Последна редакция: Dec 29, 2008, 12:58 от gat3way »
Активен

"Knowledge is power" - France is Bacon

Whisper

  • Напреднали
  • *****
  • Публикации: 128
  • Distribution: Ubuntu 8.10
  • Window Manager: Gnome
    • Профил
    • WWW
Re: Малко С Help
« Отговор #2 -: Dec 29, 2008, 12:23 »
Пробвах, но ефектът е същия  ??? други идеи плс :)
Активен

The Anticrist write up the honor roll

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Малко С Help
« Отговор #3 -: Dec 29, 2008, 12:59 »
Ъх, требваше вместо да редактирам стария пост, да пусна нов, как и да е :)
Активен

"Knowledge is power" - France is Bacon

dobrev666

  • Напреднали
  • *****
  • Публикации: 119
  • Distribution: Slackware, Slackware64
    • Профил
    • WWW
Re: Малко С Help
« Отговор #4 -: Dec 29, 2008, 13:26 »
Taзи програма трябва да работи. Когато се използва pipe, не би трябвало да има проблем да се изпращат данни през 5 процеса. Аз съкратих програмата до този вариант:

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int fd[2];

int main()
{
        int i,pid1,pid2,pid3,pid4,pid5;
        pipe(fd);
        pid1=fork();
        if(pid1==0)
        {
                pid2=fork();
                if(pid2==0)
                {
                        pid3=fork();
                        if(pid3==0)
                        {
                                pid4=fork();
                                if(pid4==0)
                                {
                                        pid5=fork();
                                        if(pid5==0)
                                        {
                                                int id5;
                                                id5=getpid();
                                                close(fd[0]);
                                                write(fd[1],&id5,sizeof(id5));
                                                close(fd[1]);
                                                printf("proc5 ID sent \n");
                                        }
                                }
                        }
                }
        }
        else
        {
                close(fd[1]);
                if(read(fd[0],&i,sizeof(i))==-1)
                {
                        perror("Read ID1");
                }
                printf("proc1 ID %d\n",i);
                close(fd[0]);
        }
}

Резултата след компилиране и стартиране е това:
proc5 ID sent
proc1 ID 3628

Активен