Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Linux][C]Работа с процессами, Что я не так делаю? 
:(
    Опции темы
Relrin
Дата 26.3.2012, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 20.2.2012

Репутация: нет
Всего: нет



Поставили на днях задачу написать следующую программу под Linux (Ubuntu): Написать программу нахождения массива N последовательных значений функции y[i]=sin(2*PI*k/N) ( i=0,1,2…N-1 ) с использованием ряда Тейлора. Пользователь задаёт значения  k и количество N членов ряда Тейлора, n - количество максимально возможных созданных дочерних процессов. Для расчета  каждого члена ряда Тейлора запускается отдельный процесс. Каждый процесс выводит на экран  и в файл свой pid и рассчитанное значение ряда. Головной процесс считывает из файла значения  всех рассчитанных членов ряда Тейлора, суммирует их  и полученное значение y[i] записывает в файл. Проверить работу программы для N=256 k=5; N=1024  k=10. Использовать для процессов только функции fork() и wait().

Если не ограничивать в количестве максимального количества процессов, то рассчеты производятся верно. После попытки ограничить количество процессов, все приводит к тому, что пересчеты идут неверные, причем некоторые значения по несколько раз, плюс ко всему не закрываются процессы, что ставит в ступор программу, и она ничего не делает. Подскажите, что и как исправить, а то уже битый час бьюсь...  smile 

Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define PI 3.14159265358979323846
extern int errno;

//удаление подстроки из строки
void DeletePartPath(char *str, char *fnd, char *buf)
{
    //Ищем поисковый контекст (fnd) в строке
    char *p=strstr(str, fnd);
    //Если fnd не найден, то копируем всю строку и завершаем функцию.
    if(p==NULL)
    {strcpy(buf, str); return;}
    //Если нашли, то вырежем часть строки
    char *fnd1=fnd;
    while(str<p)
    {*buf=*str; buf++; str++; *buf='\0';}
    //Скопировали строку до встречи fnd.
    while(*fnd1)
    {str++; fnd1++;} //Пропустили fnd.
    //Скопировали все, что идет после fnd.
    strcpy(buf, str);
    return;
}

//возведение дробного числа в степень
float PowFloat(float value,int in)
{
    int i;
    float result=1;
    for(i=1;i<=abs(in);i++)
      result*=value;
    return result;
}

//возведение -1 в степень
int PowMinusOne(int in)
{
    //если остаток от деления =0 => степень четная, и возвращаем 1
    if((in%2)==0) return 1;
      //иначе степень - нечетная, а результат равен -1
      else return -1;
}

//Рассчет ряда Тейлора с помощью процессов
int TailorFunction(char err[], int K, int N, int n)
{
    FILE *input,*output; //входной и выходной файлы
    char InPath[]="/tmp/math.txt";   //путь входного файла
    char OuPath[]="/tmp/result.txt"; //путь выходного файла

    ///Подсчет членов ряда Тейлора с помощью процессов
    int i;
    float *arr;     //указатель на динамический массив

    //выделяем память для массива
    arr=(float*)calloc(N,sizeof(float));
    //обнуляем все элементы динамического массива
    for(i=0;i<N;i++) arr[i]=0;
    //создаем файл для входных данных
    if((input=fopen(InPath,"w+"))==NULL)
    {
        DeletePartPath(err,"./",err);
        //проверка на ошибку, если она возникла
        switch(errno)
        {
            case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;}
            case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;}
            case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;}
            case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;}
            case EISDIR:{fprintf(stderr,"%s Error: It is directory!\n",err);break;}
            default: {fprintf(stderr,"%s Error: Cannot open or create file!\n",err);break;}
        }
        return 1;
    }
    /*
    | ВЫЧИСЛЕНИЕ РЯДА ТЕЙЛОРА
    | от фукнции sin(2*PI*K/N), где
    | i={0,1,2,..,N-1}
    | K - № гармоники
    | N - делитель для члена ряда (и кол-во всевозможных значений)
    | n - кол-во процессов
    */

    int j=0;
    long int factorial=1;   //факториал
    int cnt=1;              //счетчики
    int sign;               //знак
    float degree;           //значение X^i
    int pid,son;           //PID процесса и его статус
    for(i=0;i<=N-1;i++)
    {
                //создаем процесс
                if (j!=n)
                {
                    pid=fork();
                    j++;

                    //если это дочерний процесс
                    if(pid==0)
                    {
                        //подсчет элемента ряда
                        degree=PowFloat((2*PI*K/N),2*i+1);//вычисляем X^(2j+1)
                        sign=PowMinusOne(i+2);            //меняем знак на противоположный
                        arr[i]=sign*degree/factorial;     //элемент ряда
                        cnt=cnt+2;                        //факториал следующего эл-та
                        factorial=factorial*(cnt-1)*cnt;  //вычислим факториал для следующего эл-а
                        //выводим значение подсчетов и ID процесса
                        fprintf(stdout,"PID=%d and arr[%d]=%.25f\n",getpid(),i+1,arr[i]);
                        //фомируем выходную строку из числа
                        char buffer[30];                  //строка на 30 символов
                        *buffer='\0';                     //очищаем строку buffer
                        sprintf(buffer,"%.25f\n",arr[i]); //перевод дробного числа в строку
                        //запись значения в текстовый файл
                        if((fputs(buffer,input))==-1)
                        {
                          //удаляем часть пути
                          DeletePartPath(err,"./",err);
                          //проверка на ошибку, если она возникла
                          switch(errno)
                          {
                              case ENOTTY:{fprintf(stderr,"%s Error: Uknown operation I/O control!\n",err);break;}
                              case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;}
                              case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;}
                              default: {fprintf(stderr,"%s Error: Cannot write file!\n",err);break;}
                          }
                          return 1;
                        }
                    }
                }
                //ожидаем завершение процесса
                if (j==n)
                {
                    //Ожидаем завершения всех дочерних процессов
                    while(wait(NULL)==-1);
                    //обнуляем, и по новой повторяем
                    j=0;
                }
    }
    //освобождаем память от динамического массива
    free(arr);

    ///Подсчет суммы элементов ряда Тейлора
    //перевод окна входного файла на его начало
    rewind(input);
    //создаем файл
    if((output=fopen(OuPath,"w"))==NULL)
    {
        DeletePartPath(err,"./",err);
        //проверка на ошибку, если она возникла
        switch(errno)
        {
            case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;}
            case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;}
            case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;}
            case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;}
            case EISDIR:{fprintf(stderr,"%s Error: It is directory!\n",err);break;}
            default: {fprintf(stderr,"%s Error: Cannot open or create file!\n",err);break;}
        }
        return 1;
    }
    //подсчет суммы ряда
    char buffer[50],tmp[50];
    float sum,value;       //сумма элементов ряда тейлора; элемент в виде числа

    while(!feof(input))
    {
        *buffer='\0';                //очищаем строку buffer
        fgets(buffer,50,input);      //считываем строку
        sscanf(buffer,"%f",&value);  //переводим строку в дробное число
        sum+=value;                  //считаем сумму
    }

    //фомируем выходную строку
    *buffer='\0';              //очищаем строку buffer
    *tmp='\0';                 //очищаем строку tmp
    sprintf(tmp,"%.25f",sum);  //перевод числа в строку
    strcat(buffer,tmp);        //строка вида "summ=%f"
    //подаем команду на запись
    if((fputs(buffer,output))==-1)
    {
        DeletePartPath(err,"./",err);
        //проверка на ошибку, если она возникла
        switch(errno)
        {
            case ENOTTY:{fprintf(stderr,"%s Error: Uknown operation I/O control!\n",err);break;}
            case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;}
            case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;}
            default: {fprintf(stderr,"%s Error: Cannot write file!\n",err);break;}
        }
        return 1;
    }

    //пробуем закрыть входной файл
    if(fclose(input)==-1)
    {
        //удаляем часть пути
        DeletePartPath(err,"./",err);
        //проверка на ошибку, если она возникла
        switch(errno)
        {
            case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;}
            case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;}
            case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;}
            case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;}
            default: {fprintf(stderr,"%s Error: Cannot close file!\n",err);break;}
        }
        return 1;
    }

    //пробуем закрыть выходной файл
    if(fclose(output)==-1)
    {
        DeletePartPath(err,"./",err);
        //проверка на ошибку, если она возникла
        switch(errno)
        {
            case EACCES:{fprintf(stderr,"%s Error: Access is denied!\n",err);break;}
            case EBADF :{fprintf(stderr,"%s Error: Invalid file descriptor!\n",err);break;}
            case EBUSY :{fprintf(stderr,"%s Error: Resourse is busy!\n",err);break;}
            case EMFILE:{fprintf(stderr,"%s Error: Too many open files!\n",err);break;}
            default: {fprintf(stderr,"%s Error: Cannot close file!\n",err);break;}
        }
        return 1;
    }

    return 0;
}

int main(int argc,char *argv[])
{
    int K,N,n;
    //проверка на количество аргументов
    if(argc<4)
    {
        fprintf(stderr,"Error:Too few arguments!\n");
        return 1;
    }
    K=atoi(argv[1]);
    N=atoi(argv[2]);
    n=atoi(argv[3]);
    //если все указано верно, то  высчитываем ряд Тейлора
    TailorFunction(argv[0],K,N,n);
    return 0;
}


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0429 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.