Unix-вилка, которая разветвляется только на одного ребенка - PullRequest
3 голосов
/ 07 октября 2011

Очевидно домашнее задание, однако я не прошу, чтобы кто-нибудь сделал это для меня, а просто хочу направление. До сих пор я уже писал это как дерево процессов форка (что было непросто выяснить)

   /* Includes */
#include <unistd.h>     /* Symbolic Constants */
#include <stdio.h>      /* Input/Output */
#include <stdlib.h>     /* General Utilities */
#include<errno.h>

int main()
{   
    pid_t leftchild;
    pid_t rightchild;
    pid_t pid;
    int level=0;
    int max;


    printf("Enter in max level for process tree: ");
    scanf(" %d", &max);




    pid=getpid();
        fprintf(stderr,"I am the parent process with and id of: %ld\n", (long)getpid());
    for(; level<max; level++){

        leftchild=fork();
          if (leftchild == -1)
           {   

              fprintf(stderr, "can't fork, error %d\n", errno);
              exit(EXIT_FAILURE);
           }

        if(leftchild==0){
            fprintf(stderr,"Level is %d, i am %ld , my parent is %ld\n",level, (long)getpid(), (long)getppid());
            continue;
        }



        else{
            rightchild=fork();

            if(rightchild==0){
                fprintf(stderr,"Level is %d, i am %ld , my parent is %ld\n",level, (long)getpid(), (long)getppid());

                continue;
            }
        }
    wait(NULL);
    wait(NULL);
    break;

    }   

}

эта программа создает это дерево

    i
    /\
  i    i 
 /\    /\
i  i  i  i

Мне нужно создать другое дерево ветвлений, в котором есть такое дерево:

     i
    / \
  i     i
        /\
       i  i
          /\  
         i  i
            /\
            i  i

Какую модификацию я должен рассмотреть, чтобы внести в мою программу?

Я попытался создать еще один форк внутри оператора правой руки, и это не сработало. Я даже пытался все расколоть, но это с треском провалилось. Я просто не вижу решения логически. какие-либо советы или предложения?

Я пробовал рекурсию:

     /* Includes */
#include <unistd.h>     /* Symbolic Constants */
#include <stdio.h>      /* Input/Output */
#include <stdlib.h>     /* General Utilities */
#include<errno.h>
pid_t leftchild;
pid_t rightchild;
pid_t pid;
int level=0;
int max;



void recurse(){
if(level<2){
    leftchild= fork();
        if (leftchild == -1)
           {   

              fprintf(stderr, "can't fork, error %d\n", errno);
              exit(EXIT_FAILURE);
           }

        if(leftchild==0){
            fprintf(stderr,"Level is %d, i am %ld , my parent is %ld\n",level, (long)getpid(), (long)getppid());

        }   

    rightchild=fork();
        if (rightchild == -1)
           {   

              fprintf(stderr, "can't fork, error %d\n", errno);
              exit(EXIT_FAILURE);
           }

        if(rightchild==0){
            fprintf(stderr,"Level is %d, i am %ld , my parent is %ld\n",level, (long)getpid(), (long)getppid());

        }
        level++;
        recurse();
        }

    }




int main()
{   



    printf("Enter in max level for process tree: ");
    scanf(" %d", &max);


    pid=getpid();
        fprintf(stderr,"I am the parent process with and id of: %ld\n", (long)getpid());

    recurse();



}

Это на самом деле не вернет pid для чего-либо, по какой-то конкретной причине, почему?

Ответы [ 2 ]

2 голосов
/ 07 октября 2011

Ваш левый ребенок не должен продолжать цикл;он должен выйти из цикла или выйти.У него нет дочерних элементов, но это просто означает, что вызов wait() будет возвращаться с ошибкой каждый раз.

Ваш правый ребенок должен продолжить цикл, чтобы продолжить процесс до последнего уровня.

Родительский процесс на каждом уровне должен выйти из цикла после запуска второго (правого) потомка и дождаться смерти его потомков.


Пример

Кажется, это работаетдля меня;это простая адаптация ответа на SO 7624325 , ваш предыдущий связанный вопрос, хотя я вырезал его из приведенного выше примера кода.

Пример вывода

I am the parent process with and id of: 13277
Level is 0, I am Left  child 13278, my parent is 13277
Exiting: 13278
Level is 0, I am Right child 13279, my parent is 13277
Level is 1, I am Left  child 13280, my parent is 13279
Level is 1, I am Right child 13281, my parent is 13279
Exiting: 13280
Level is 2, I am Right child 13283, my parent is 13281
Level is 2, I am Left  child 13282, my parent is 13281
Exiting: 13282
Level is 3, I am Left  child 13284, my parent is 13283
Level is 3, I am Right child 13285, my parent is 13283
Exiting: 13284
Level is 4, I am Left  child 13286, my parent is 13285
Exiting: 13286
Level is 4, I am Right child 13287, my parent is 13285
Level is 5, I am Left  child 13288, my parent is 13287
Exiting: 13288
Level is 5, I am Right child 13289, my parent is 13287
Level is 6, I am Right child 13291, my parent is 13289
Level is 6, I am Left  child 13290, my parent is 13289
Exiting: 13290
Exiting: 13291
Exiting: 13289
Exiting: 13287
Exiting: 13285
Exiting: 13283
Exiting: 13281
Exiting: 13279
Exiting: 13277

Пример кода

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

static void run_process(const char *child, int level)
{
    fprintf(stderr, "Level is %d, I am %-5s child %ld, my parent is %ld\n",
            level, child, (long)getpid(), (long)getppid());
}

int main(void)
{   
    int max = 7;

    fprintf(stderr, "I am the parent process with and id of: %ld\n", (long)getpid());

    for (int level = 0; level < max; level++)
    {
        pid_t leftchild;
        pid_t rightchild;
        if ((leftchild = fork()) < 0)
        {   
            fprintf(stderr, "can't fork, error %d\n", errno);
            exit(EXIT_FAILURE);
        }
        else if (leftchild == 0)
        {
            run_process("Left", level);
            break;
        }
        else if ((rightchild = fork()) < 0)
        {   
            fprintf(stderr, "can't fork, error %d\n", errno);
            exit(EXIT_FAILURE);
        }
        else if (rightchild == 0)
        {
            run_process("Right", level);
            continue;
        }
        else
            break;
    }

    wait(NULL);
    wait(NULL);
    fprintf(stderr, "Exiting: %ld\n", (long)getpid());

    return(0);
}
1 голос
/ 07 октября 2011

Почему вы не используете рекурсию вместо цикла for?Создайте вилку для левой стороны и назовите себя для правой.

...