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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> помогите с программой копирования файла, не сходятся md5sum у исходника и копии 
V
    Опции темы
duckich
Дата 7.12.2008, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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




M
MAKCim
Модератор: пользуйтесь тегом код!


При копировании файла с помощью сигналов возникает проблема. Почему при вызове функции md5sum суммы копии и исходного файла(копируемого) не совпадают. Помогите, пожалуйста.

Вот код программы:

Код

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#include <string.h>

int fr=-1, fw=-1;


int read_send(int pid,sigset_t* set)
{
    char symbol;
    int i,err,sgnl;
    for(;(err=read(fr,&symbol,1))==1;)
    {
        for(i=7;i>=0;i--)
        {
            if (((symbol>>i)&1) == '\0')
            {
                kill(pid,SIGUSR1);          //посылает сигнал SIGUSR1 пиду
            }
            else
            {
                kill(pid,SIGUSR2);         //посылает сигнал SIGUSR2 пиду
            }
            
            sigwait(set,&sgnl);
        }
    }
    if (err==-1) return -1;    
    
    close(fr);
    kill(pid,SIGTERM);
    _exit(0);
}

void termination(int signo)
{
    if ( fr != -1 ) close(fr);
    if ( fw != -1 ) close(fw);
    exit(0);
}

int receive_write(int pid,sigset_t* set)
{
    char symbol;
    int err,i,sgnl;

    while(waitpid(-1,NULL,WNOHANG)!=-1)
    {
        for(i=0;i<8;i++)
        {    
            err=0;
            symbol=symbol<<1;
            sigwait(set,&sgnl);
            if (sgnl == SIGUSR2)
                symbol+=1;
            else if (sgnl != SIGUSR1) 
            {
                symbol=symbol>>1;
                i--;
                err=1;        
            }
            kill(pid,SIGUSR1);
        }
        if (err==0)
            if (write(fw,&symbol,1) == -1) return -1;
    }    
    return 0;
}

int copy(char filename1[],char filename2[])                                        //функция copy, работающая от двух аргументов
{
    int n, prtime,pid,ppid;                                                    //описание переменных
    sigset_t set;                                                              //
    
    struct stat stbuf;                                                         //
    if ( stat(filename1,&stbuf) != 0 ) goto err;                               
                
    if (( fr = open(filename1,O_RDONLY) ) == -1 )                              //открываем файл для чтения
    {
        fprintf(stderr,"%s: ",filename1);                                  //возможная ошибка при этом
        goto err;                                                          //переход в блок обработки ошибок
    }
    if (( fw = open(filename2,O_CREAT|O_EXCL|O_WRONLY,stbuf.st_mode)) == -1 )  //создаём и открываем пустой файл для записи
    { 
        fprintf(stderr,"%s: ",filename2);                                  //возможная ошибка при этом
        goto err;                                                          //переход в блок обработки ошибок
    }
    
    sigemptyset(&set);                                                        //инициализирует набор сигналов, указанный в set, и "очищает" его от всех сигналов.
    sigaddset(&set,SIGUSR1);                                                  //добавдяет сигнал SIGUSR1 в набор set
    sigaddset(&set,SIGUSR2);                                                  //добавдяет сигнал SIGUSR2 в набор set
    sigprocmask(SIG_BLOCK,&set,NULL);                                         //Блокируем все сигналы
    
    ppid=getpid();
    
    if ((pid=fork()) == -1) goto err;                                     //создаём чилда и возможная ошибка при этом
    
    if (pid == 0)                                                            //если сын ничего не выполняет
    {
        close(fw);                                                       //закрываем записывающий "канал"
        if (read_send(ppid,&set) == -1)                                  //выполняем функцию чтения
        {
            fprintf(stderr,"%s: ",filename1);
            goto err;
        }
    }
    else
    {
        close(fr);
        if (receive_write(pid,&set) == -1)
        {
            fprintf(stderr,"%s: ",filename2);
            goto err;
        }
    }
    
    if (stat(filename2,&stbuf) != 0 ) goto err;
    
    close(fw);
    return 0;
err:
    fprintf(stderr,"error: %s \n",strerror(errno));
    if ( fr != -1 ) close(fr);
    if ( fw != -1 ) close(fw);
    exit(0);
}

int main(int argc, char **argv)                             //основная функция
{
    struct sigaction act;                               //определение обработчика сигнала
    memset(&act,0,sizeof(act));                         //обнуляет блоки динамической памяти
    act.sa_handler = termination;                       //задаём тип действия процесса:указатель на функцию обработки сигнала
    sigaction(SIGTERM,&act,NULL);

    if (argc!=3)                                       //считает количество операндов, нужно 1 название и 2 операнда
    {
        printf("\nne pravil'no nabrana komanda. Need: ./copy.c name_faila name_his_copy;\n\n");
    goto er0;
    }

    copy(argv[1],argv[2]);                             //копирует файл(запуск функции копирования)
        return 0;
    
er0:
    return -1;                                         //возвращаемый результат при ошибке
}

PM MAIL   Вверх
MAKCim
Дата 7.12.2008, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



duckich, 
проблема в том, что порядок выбора pending-сигнала в sigwait может не совпадать с порядком их генерации
используй sigqueue/sigwaitinfo

Код

union sigval sigval;
for(i=7;i>=0;i--)
{
    sigval.sigval_int = i;
    if (((symbol >> i) & 1) == 0)
    {
        sigqueue(pid,SIGUSR1,sigval);          //посылает сигнал SIGUSR1 пиду
    }
    else
    {
        sigqueue(pid,SIGUSR2,sigval);         //посылает сигнал SIGUSR2 пиду
    }
            
    sigwait(set,&sgnl);
}
 

Код

siginfo_t siginfo;
union sigval sigval;
symbol = 0;
for(i=0;i<8;i++)
{    
    err=0;
    sigwaitinfo(set,&sgnl,&siginfo);
    if (sgnl == SIGUSR2)
        symbol |= 1 << siginfo->si_value;
    sigval = (union sigval)siginfo->si_value; 
    sigqueue(pid,SIGUSR1,sigval);
}



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
duckich
Дата 7.12.2008, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо за то что вы мне помогаете.
В вашем коде есть некоторые неточности, но это не суть как важно.

Заменив часть моего кода на :

Код

int read_send(int pid,sigset_t* set)
{
    char symbol;
    int i,err,sgnl;
    for(;(err=read(fr,&symbol,1))==1;)
    {
        union sigval sigval;
        for(i=7;i>=0;i--)
        {
            sigval.sival_int = i;
             if (((symbol >> i) & 1) == 0)
             {
                 sigqueue(pid,SIGUSR1,sigval);          //посылает сигнал SIGUSR1 пиду
             }
             else
             {
                 sigqueue(pid,SIGUSR2,sigval);         //посылает сигнал SIGUSR2 пиду
             }
            sigwait(set,&sgnl);
        }
    }
    if (err==-1) return -1;    
    
    close(fr);
    kill(pid,SIGTERM);
    _exit(0);
}

и

Код

int receive_write(int pid,sigset_t* set)
{
    char symbol;
    int err,i,sgnl;

    while(waitpid(-1,NULL,WNOHANG)!=-1)
    {
        siginfo_t siginfo;
        union sigval sigval;
        symbol = 0;
        for(i=0;i<8;i++)
        {
            err=0;
            sigwaitinfo(set,&siginfo);                       //sigwait(set,&sgnl);
            if (sgnl == SIGUSR2)
            symbol |= 1 << siginfo.si_value;
            sigval = (union sigval)siginfo.si_value; 
             sigqueue(pid,SIGUSR1,sigval);
        }
        if (err==0)
        if (write(fw,&symbol,1) == -1) return -1;
    }    
    return 0;
}


Я столкнулся с ешё одной проблемой он не воспринимает "->"
Я его уже и заменял на точку, но ошибок становится только больше. Я просто не совсем хорошо знаком с siginfo и маны мне не помогают.
Посоветуйте что мне делать, пожалуйста.

PM MAIL   Вверх
duckich
Дата 7.12.2008, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



НУ ХОТЬ КТО-НИБУДЬ МОЖЕТ ПОМОЧЬ МНЕ С ЭТИМ ВОПРОСОМ, ПРОСТО СРОКИ СДАЧИ ПОДЖИМАЮТ?

Насчёт той ошибки (->) если я заменяю её на точку то возникает не много ошибок, а одна проблемы с ">>".

Эта программа уже написана почти полностью за исключением отладки и прошу тех кому не лень скомпилируйте её в gcc и если получится исправьте ошибку, пожалуйста. Просто я над чем-то туплю и уже ничего путного сделать не могу!

Это сообщение отредактировал(а) duckich - 7.12.2008, 18:28
PM MAIL   Вверх
MAKCim
Дата 7.12.2008, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



duckich, 
я не понял, в чем конкретно и где проблема с ->?


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
duckich
Дата 7.12.2008, 22:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Да.
Программа не воспринимает ->  в коде
Код

 symbol |= 1 << siginfo->si_value;
            sigval = (union sigval)siginfo.si->value; 


Когда я заменяю её на точку то возникает другая ошибка: проблема с <<

Проблемный код
Код


 symbol |= 1 << siginfo.si_value;
            sigval = (union sigval)siginfo.si_value; 



И если не трудно можно в кратце объяснить про siginfo и её поля.
ТЕ чем не устроил компилятору мой старый код.
И что такое union?

Это сообщение отредактировал(а) duckich - 7.12.2008, 22:44
PM MAIL   Вверх
MAKCim
Дата 7.12.2008, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



duckich, 
Код

siginfo->si_value.sigval_int



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
duckich
Дата 7.12.2008, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Cпасибо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

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

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


 




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


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

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