Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Помогите с лабой, плз)  (Прочитано 1397 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн sandric

  • Автор темы
  • Новичок
  • *
  • Сообщений: 13
    • Просмотр профиля
Помогите с лабой, плз)
« : 04 Июнь 2008, 12:45:03 »
Вот собственно лаба:
Задача - у главного процеса может быть неск. потомков(макс 5), и у их потомков тоже самое. Вот програ
/*
 * File:   main.cpp
 * Author: sandric
 *
 * Created on 17 травня 2008, 15:39
 */

  #include <iostream.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys/types.h>
  #include <sys/wait.h>
  #include <time.h>
  #include <signal.h>
  #include <sys/resource.h>


/*
 *
 */

int ctr = 0;

int col;

int col_p;

int main_pid;

int pid;

int mas_pid[5] = {0,0,0,0,0};

int mas_pid2[5] = {0,0,0,0,0};

using namespace std;

void usrHandler(int sig) {

    if (sig==SIGUSR1) ctr++;

  }

void usrHandler2(int sig) {

    if (sig==SIGUSR2){ 
        int pid;
        pid = fork();
       
        if(pid) cout<<endl<<"novyi 2...";
    }

}

int main(int argc, char** argv) {
   
    signal(SIGUSR1,usrHandler);
   
    signal(SIGUSR2,usrHandler2);
   
    main_pid = (int)getpid();
   
    cout<<"main_pid:"<<main_pid<<endl;
   
    cout<<"Введіть кількість процесів - потомків головного процеса(макс. 5): ";
   
    cin>>col;
   
    for(int i = 0; i!=col; i++){
   
    cout<<"\nВведіть число процесів - потомків для "<<i+1<<" потомку: ";
    cin>>mas_pid[i];
   
        }
   
    if(col >= 1){
        if(getpid() == main_pid){
            pid = mas_pid2[0] = fork();
            if(getpid() == main_pid){ cout<<endl<<main_pid<<" novyi 1:0:"<< mas_pid2[0]<<endl;}
        }
    }

               
    else {
          int x;
          cout<<endl<<"Неприпустиме значення. Натисніть клавішу 1...";
          cin>>x;
          return 0;
    }
   
    for(int i = 0; i<col-1; i++)
        if(pid > 0){
            mas_pid2[i+1] = (int)fork();
            if(getpid() == main_pid)
                cout<<endl<<main_pid<<" novyi 1:"<<i+1<<":"<<mas_pid2[i+1]<<endl;
    }

           
       if(getpid() == main_pid){
           
           for(int i = 0; i<col; i++){

           for(int j = 0; j != mas_pid[i]; j++){
               cout<<endl<<mas_pid2[i]<<endl;
               //kill(mas_pid2[i],SIGUSR2);
               
               if(getpid() != main_pid) break;
               
           }
           
           }
    }
   
    if(getpid() != main_pid) kill(main_pid,SIGUSR1);
   
    else{ sleep(1); cout<<endl<<"Загальна кількість процесів - потомків: "<<ctr;}
   
   
    return (EXIT_SUCCESS);
}

Всё пашет, если не отсылать сигнал ЮЗР2 на создание подпроц. подпроцессов)). Тогда выводит бред. Можна было ещё пайпом организовать, но на переделку времени нет, завтра сдача, + еще 4). Кто знает, почему не работает форк в обр. сигнала отпишитесь, плз. Сессия...
З.Ы. Извините за украинский, тока щас понял) В принцыпе там всё понятно.

Оффлайн S.Tokarev

  • Активист
  • *
  • Сообщений: 415
    • Просмотр профиля
Re: Помогите с лабой, плз)
« Ответ #1 : 04 Июнь 2008, 22:00:34 »
Алгогритм в корне не верен потому, что не гарантируется, что обработчик USR2 вызовется нужное количество раз. Следовательно, не гарантируется создание нужного количества внуков.
PS и уж тем более не факт что внуки успеют отрапортовать о своём создании посредством USR1.
PSPS Но самая большая проблема в том, что не понятно в какой момент child форкнется на внука, поскольку обработка сигнала штука асинхронная. Потому и бред выдаётся.

Если задача не требует жонглирования сигналами, то без них надол делать.
Я бы сделал так
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
#include <sys/resource.h>

int makechildren(int num)
{
        int pid=getpid();
        for (int i=0;i<num;i++) {
                int child;
                switch (child=fork()) {
                        case 0:
                                cout<<"I'm "<<getpid()<<" just created by "<<pid<<" as its "<<(i+1)<<"/"<<num<<" child."<<endl;
                                return (i+1);
                        case -1:
                                cout<<"["<<pid<<"] failed to create "<<(i+1)<<"/"<<num<<" child."<<endl;
                                break;
                        default:
                                cout<<pid<<" just created "<<(i+1)<<"/"<<num<<" child with PID="<<child<<endl;
                }
        }
        return 0;
}

main ()
{
        int g=0;
        int children=0;
        int g_children[5]={0,0,0,0,0};
        int child;
        int n;
        int index,index2;
        while (1>children || 5<children) {
                cout<<endl<<"How many children the main process must have [1-5]:";
                cin>>children;
        }
        for (int i=0;i<children;i++) {
                g=0;
                while (1>g || 5<g) {
                        cout<<endl<<"How many children the child #"<<(i+1)<<" must have [1-5]:";
                        cin>>g;
                        g_children[i]=g;
                }
        }
        cout<<endl;
        index=index2=0;
        if (index=makechildren(children)) {
                index2=makechildren(g_children[index-1]);
        }
        cout<<"I'm "<<index<<":"<<index2<<" now exiting since nothing to do."<<endl;
}
« Последнее редактирование: 04 Июнь 2008, 22:20:38 от S.Tokarev »

Оффлайн sandric

  • Автор темы
  • Новичок
  • *
  • Сообщений: 13
    • Просмотр профиля
Re: Помогите с лабой, плз)
« Ответ #2 : 04 Июнь 2008, 23:41:13 »
Спасибо за ответ. Жаль только, что тема лабораторной "сигналы в ОС Юникс")  :-[

Оффлайн sandric

  • Автор темы
  • Новичок
  • *
  • Сообщений: 13
    • Просмотр профиля
Re: Помогите с лабой, плз)
« Ответ #3 : 05 Июнь 2008, 13:10:23 »
Ничо у меня не получается(. Вот 3-я лаба: использование очереди сообщений - типа клиент сначала собирает у всех потомков их пиды, а потом, када ужо все считал - отправляет назад всем. Работает все, вот только как-то хаотично выводит сообщения - оно что, вообще не синхронизировано?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <unistd.h>
#include <dirent.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/*
 *
 */

using namespace std;

typedef struct mymsgbuf
{
  long mtype;
  int num;
  int num_mas[20];
} mess_t;

pid_t pid;

int col;

int ctr = 0;

int main_pid;

string s_pid;
       
ostringstream strStream;

void usrHandler(int sig) {

    if (sig==SIGUSR1) ctr++;

  }


int main(int argc, char** argv) {
   
    int mas[20];
   
    signal(SIGUSR1,usrHandler);

   
    int qid;
    key_t msgkey;
    mess_t buf;
   
    int length;
   
    length = sizeof(mess_t) - sizeof(long);

    msgkey = ftok(".",'m');

    qid = msgget(msgkey, IPC_CREAT | 0660);
   
    main_pid = getpid();
   
    cout<<"Введіть кількість місць у автобусі: ";
   
    cin>>col;
   
    if(col >= 1)
        pid = fork();
   
   
    for(int i = 0; i<col-1; i++)
   
        if(pid) pid = fork();
   
   
    if(!pid){
     
        buf.mtype = 1;
       
        buf.num = (int)getpid();
       
        cout<<"\nКлієнт відправив повідомлення: "<<buf.num;
       
        msgsnd(qid, &buf, length, 0);
       
        kill(main_pid, SIGUSR1);


            if(msgrcv(qid, &buf, length, 2, 0) > 0){
               
                cout<<"\nКлієнт прийняв повідомлення:\n";
                for(int i = 0; i<col; i++)
                    cout<<endl<<buf.num_mas[i];
               
            }
         
    }
   
    if(pid){
        sleep(0.5);
        int i = 0;
       
        while(ctr<col){sleep(0.001);}
       
        while(i<col){
            if(msgrcv(qid, &buf, length,1, 0)>0){
            cout<<"\nСервер прийняв повідомлення: "<<buf.num;
            mas[i] = buf.num;
            i++;
            }
        }
       
        for(int i = 0; i<col; i++)
            buf.num_mas[i] = mas[i];
       
        for(int i = 0; i<col; i++){
       
        buf.mtype = 2;
       
        if(msgsnd(qid, &buf, length, 0) != -1)
       
            cout<<"\nСервер відправив повідомлення...";}
       
        sleep(1);
       
        msgctl(qid, IPC_RMID, 0);
       
    }

    return (EXIT_SUCCESS);
}


А вот, что выводит:
Введіть кількість місць у автобусі: 5






Сервер прийняв повідомлення: 6934
Сервер прийняв повідомлення: 6935
Сервер прийняв повідомлення: 6936
Сервер прийняв повідомлення: 6937
Клієнт відправив повідомлення: 6934
Клієнт прийняв повідомлення:
Сервер прийняв повідомлення: 6938

6934
6935
6936
6937
6938Клієнт відправив повідомлення: 6935
Клієнт прийняв повідомлення:

6934
6935
6936
6937
6938Сервер відправив повідомлення...
Клієнт відправив повідомлення: 6936
Клієнт прийняв повідомлення:

6934
6935
6936
6937
6938Сервер відправив повідомлення...
Сервер відправив повідомлення...
Сервер відправив повідомлення...
Клієнт відправив повідомлення: 6937
Клієнт прийняв повідомлення:

6934
6935
6936
6937
6938Клієнт відправив повідомлення: 6938
Клієнт прийняв повідомлення:

6934
6935
6936
6937
6938Сервер відправив повідомлення...[Press Enter to close window]

Что за бред?

Оффлайн S.Tokarev

  • Активист
  • *
  • Сообщений: 415
    • Просмотр профиля
Re: Помогите с лабой, плз)
« Ответ #4 : 05 Июнь 2008, 14:10:06 »
Это особенности буферизации cout или терминала.
Поставь "\n" в конец каждого cout и убери из начала.
« Последнее редактирование: 05 Июнь 2008, 14:12:49 от S.Tokarev »

Thread

  • Гость
Re: Помогите с лабой, плз)
« Ответ #5 : 05 Июнь 2008, 17:05:16 »
После каждого вывода нужно cout'у скармливать ::std::flush (заголовочный файл <ostream>).

Оффлайн sandric

  • Автор темы
  • Новичок
  • *
  • Сообщений: 13
    • Просмотр профиля
Re: Помогите с лабой, плз)
« Ответ #6 : 05 Июнь 2008, 20:48:40 »
Спс за сиаут, пошло) А как на счёт 1 лабы? Ни кто не знает, почему бачинит? :(

Оффлайн S.Tokarev

  • Активист
  • *
  • Сообщений: 415
    • Просмотр профиля
Re: Помогите с лабой, плз)
« Ответ #7 : 05 Июнь 2008, 23:55:54 »
Очень плохой стиль программирования. Кто вас там учит?
for(int i = 0; i<col-1; i++)
        if(pid > 0){
            mas_pid2[i+1] = (int)fork();
            if(getpid() == main_pid)
                cout<<endl<<main_pid<<" novyi 1:"<<i+1<<":"<<mas_pid2[i+1]<<endl;
        }
Этот код создаёт не col-1 процесс а больше. Если не ошибаюсь (col-1)*(col-2)/2  процессов.

По существу же собака зарыта ещё и в непонимании функции sleep()
man 3 sleep
Мастер не засыпает на секунду. Первый же сигнал его будит. Потому счётчик не полноценный.
Но даже если
sleep(1) заменить на while(sleep(1)) всё-равно процесс не сможет сказать сколько сигналов он получил пока сидел в ядре.

 

Страница сгенерирована за 0.138 секунд. Запросов: 24.