2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 01:38 


02/10/12
308
Системный вызов close. Раньше я думал, что для прикладной программы файл закрывается мгновенно, а далее система потихоньку освобождает системный буфер файлов, но выяснилось, что это не так. Минимальный пример. В качестве аргумента указать имя файла для копирования, он будет скопирован под именем "test". Файл у меня 374 кб.
код: [ скачать ] [ спрятать ]
Используется синтаксис C

//   gcc test.c -o test.cgi -Wall -Werror -O3
//   ./test.cgi

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>


//------------------- gettime_dt_msek ----------------------
// разность двух временных меток в миллисекундах
int gettime_dt_msek(struct timeval *tv1, struct timeval *tv2)
{
    return((tv2->tv_sec - tv1->tv_sec)*1000 +
           (tv2->tv_usec - tv1->tv_usec + 500)/1000);
}

//--------- time_metka --------
// печатает метку времени. tv0 -начало отсчета времени.
void time_metka(struct timeval *tv0, const char *metka)
{
    int t;
    struct timeval tv1;

    gettimeofday(&tv1, NULL);
    t = gettime_dt_msek(tv0, &tv1);
    printf("%s=%d.%03d sec\n", metka, t/1000, t%1000);
    return;
}

//------------ main --------------

int main(int argc, char **argv)
{
    struct timeval tv0[1];
    int fd1, fd2, k, n;
    char buf[8192];

    if(argc<2){ printf("Err-arg\n"); exit(0);}

    gettimeofday(tv0, NULL); // начало отсчета времени

    fd1=open(argv[1], O_RDONLY);
    if(fd1<0){ printf("fd1=open(%s)<0\n", argv[1]); exit(0);};

    //unlink("test");

    time_metka(tv0, "t1");

    fd2=open("test", O_CREAT|O_TRUNC|O_WRONLY, 00644);
    if(fd2<0){ printf("fd2=open()<0\n"); exit(0);};

    time_metka(tv0, "t2");
    while(1){
        k=read(fd1, buf, sizeof(buf));
        if(k<0){ printf("Error read\n"); exit(0);}
        if(k==0) break;
        n=write(fd2, buf, k);
        if(n != k){ printf("Error write\n"); exit(0);}
    }
    time_metka(tv0, "t3");
    close(fd1);
    time_metka(tv0, "t4");
    close(fd2);
    time_metka(tv0, "t5");

    exit(0);
}
/*
Тестовый файл для копирования 374 кб
Распечатка с закомментированным unlink.
Первый запуск, когда ещё нет выходного файла.
t1=0.000 sec
t2=0.000 sec
t3=1.182 sec
t4=1.182 sec
t5=1.182 sec

Следующие запуски.
t1=0.000 sec
t2=0.196 sec
t3=1.308 sec
t4=1.308 sec
t5=9.448 sec

Распечатка с раскомментированным unlink.
Первый запуск, когда ещё нет выходного файла.
t1=0.000 sec
t2=0.000 sec
t3=1.221 sec
t4=1.221 sec
t5=1.221 sec

Следующие запуски.
t1=0.208 sec
t2=0.209 sec
t3=1.395 sec
t4=1.395 sec
t5=1.395 sec
*/

 

В программе есть закомментированная строка unlink, она существенно влияет. Имею пять меток времени. При распечатке отсчет от нулевой метки (tv0).
Вопрос 1. Есть ли какое-нибудь объяснение этому явлению, почему так надолго подвисает close, если файл уже существует и открыт с флагом O_TRUNC, т. е. с опустошением? И зачем система его подвешивает?
Вопрос 2. Вызов close может быть прерван сигналом с ошибкой EINTR. Что при этом происходит? Немедленный возврат? А что с файлом, закрыт он или открыт? Или открыт наполовину? Не может же система так на половине всё бросить. Казалось бы, она должна тогда дозакрыть файл в фоновом режиме. Или же прикладная программа при получении EINTR может дальше пользоваться этим файлом как открытым, включая повторный вызов close?
Прошу ответить. Если можно, в общих чертах словами. Ссылки на английские тексты мне не прочитать.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 02:28 
Заслуженный участник


09/05/12
25179
Что-то воспроизвести не получается. Как не старался, все равно (и без test, и с ним) примерно так:
Код:
t1=0.002 sec
t2=0.002 sec
t3=0.007 sec
t4=0.007 sec
t5=0.007 sec
Копировался файл размером 2.6Мб. Пробовал с gcc 4.8.5 и 6.2.1.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 03:25 


02/10/12
308
У меня ноутбук большой, портфельного формата, DELL, ему лет десять, данные привел с него. Сейчас попробовал на другом компьютере, он в Дата-центре, мне там дали аккаунт, там большой разброс, но всё же эффект ярко выражен. Привожу минимальный и максимальный случаи, файл 1.1 Мб, программа в том виде, как в моем сообщении, т. е. с закомментированным unlink:
Код:
t1=0.000
t2=0.000
t3=0.002
t4=0.002
t5=0.028

t1=0.000
t2=0.000
t3=0.002
t4=0.002
t5=0.492

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

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 04:31 


02/10/12
308
Приведу еще данные со второго компьютера (в Дата-центре) для больших файлов, они малый разброс имеют:
Код:
Файл 380 Мб
t1=0.000
t2=0.052
t3=0.351
t4=0.351
t5=3.000

Файл 1.4 Гб
t1=0.000
t2=0.182
t3=1.314
t4=1.314
t5=14.304

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 08:42 


27/08/14
207
Как-то странно:
Код:
Файл 256 Мб
t1=0.000 sec
t2=2.720 sec
t3=3.412 sec
t4=3.412 sec
t5=4.495 sec

t1=0.000 sec
t2=0.068 sec
t3=0.581 sec
t4=0.581 sec
t5=0.614 sec

t1=0.000 sec
t2=1.932 sec
t3=2.466 sec
t4=2.466 sec
t5=4.835 sec

t1=0.000 sec
t2=0.076 sec
t3=0.574 sec
t4=0.575 sec
t5=1.881 sec
Это 4 последовательных запуска. Эффект похоже есть, но он у меня начинает проявляется для достаточно больших файлов (для 64 Мб такого нет).

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 09:48 
Заслуженный участник


04/03/09
910
oleg_2 в сообщении #1193978 писал(а):
Вопрос 2. Вызов close может быть прерван сигналом с ошибкой EINTR. Что при этом происходит?

Стандарт говорит, что может быть что угодно, но конкретно в линуксовой реализации файл будет корректно закрыт.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 11:32 
Заслуженный участник


09/05/12
25179
oleg_2 в сообщении #1193992 писал(а):
А Вы несколько раз запускали программу? Подвисание только тогда, когда уже существует ранее скопированный файл.
Да, несколько раз. От размера файла эффект тоже никак не зависит (самый большой использовавшийся - немного больше гигабайта), последние три отсчета всегда совпадают.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение20.02.2017, 18:42 
Заслуженный участник


26/05/14
981
Чтение http://man7.org/linux/man-pages/man2/close.2.html показывает, что если вывод в файл буферизируется, то close не возвращает управление пока данные не будут записаны (по этой причине результат close всегда надо проверять на ошибки). Там же указано, что если к файлу применялся unlink, то файл удаляется. Полагаю, что в этом случае система не ждёт окончания записи буферов.
То что время записи не зависит от размера файла - нормально. Оно зависит от размера буфера.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение21.02.2017, 01:57 


02/10/12
308
Понятно. Спасибо.
slavav в сообщении #1194142 писал(а):
Чтение http://man7.org/linux/man-pages/man2/close.2.html показывает,
Я читаю русские переводы манов на www.opennet.ru, там примерно то же самое написано. Я не ожидал, что ни у кого не воспроизведётся эффект, только у Progger-а, да и то слабо выраженный.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение21.02.2017, 06:44 


11/12/14
893
slavav в сообщении #1194142 писал(а):
Чтение http://man7.org/linux/man-pages/man2/close.2.html показывает, что если вывод в файл буферизируется, то close не возвращает управление пока данные не будут записаны (по этой причине результат close всегда надо проверять на ошибки). Там же указано, что если к файлу применялся unlink, то файл удаляется. Полагаю, что в этом случае система не ждёт окончания записи буферов.
То что время записи не зависит от размера файла - нормально. Оно зависит от размера буфера.


Эмм, так то да, но только за одной поправкой - там написано прямо противоположное:
Цитата:
A successful close does not guarantee that the data has been
successfully saved to disk, as the kernel uses the buffer cache to
defer writes. Typically, filesystems do not flush buffers when a
file is closed. If you need to be sure that the data is physically
stored on the underlying disk, use fsync(2).

"Типичным" сценарием обозначено мгновенное закрытие по close с последующих сбросом буферов уже в недрах операционки.
Но в принципе возможность остаётся, т.к. не сказано что другое поведение запрещено.

P.S.

Гипотеза возникла - может быть у топиккастера выпадает так что файловые системы или находятся в состоянии близком к переполнению свободного места или какой нибудь режим дисковых квот включен и операционка реально решает, что не может заведомо знать что сбросит на диск всё успешно, в общем некий анализ группы риска, и ждёт поэтому в close, а не отдаёт его сразу.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение21.02.2017, 12:25 
Заслуженный участник


04/03/09
910
Наверное, сразу надо было спросить, а какая файловая система-то?
aa_dav в сообщении #1194259 писал(а):
Но в принципе возможность остаётся, т.к. не сказано что другое поведение запрещено.

Не запрещено-то не запрещено, но в коде системного вызова close есть вот такое:
Используется синтаксис C
if (filp->f_op->flush)
    retval = filp->f_op->flush(filp, id);

Это на первый взгляд единственное место, где можно серьезно зависнуть, вот только функция flush не реализована для большинства ФС, за некоторыми исключениями.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение21.02.2017, 14:18 


02/10/12
308
На моём ноутбуке сначала была Виндовс, а потом на него поставили Линукс. С полной очисткой диска, с удалением всех файлов. В окне "файлы" написано, что свободно 64 Гб. Другой компьютер - это арендованный в Дата-центре сервер, с ним я работаю через PuTTY (выносная консоль). При входе сообщение "The programs included with the Debian GNU/Linux system are free software;". Какие там настройки я не знаю. Какая файловая система тоже не знаю, ни тут, ни там. Там для меня файловую систему и настройки менять не будут. Тут мне самому не поменять, да может быть это и не надо. И почему-то сильно влияет unlink.
Может быть, по-другому поставить вопрос. При оценке быстродействия программы допустимо ли применить unlink, не будет ли это подтасовкой? С одной стороны, он ничем другим не обоснован, кроме как желанием получить лучшие результаты тестов. А с другой стороны, оценивается программа, а не система, которая, видимо, по-разному у всех работает.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение21.02.2017, 15:36 
Аватара пользователя


14/11/12
1367
Россия, Нижний Новгород
Воспроизводится на сетевой файловой системе (с резервным копированием). Просто на локальном жёстком диске (без резервного копирования) не воспроизводится.

Сетевая файловая система (с резервным копированием):
Код:
t1=0.000 sec
t2=0.012 sec
t3=0.023 sec
t4=0.023 sec
t5=0.118 sec

Просто локальный диск (разместил файлы в директории /tmp):
Код:
t1=0.000 sec
t2=0.003 sec
t3=0.020 sec
t4=0.020 sec
t5=0.020 sec

В датацентрах используются распределённые файловые системы с резервным копированием.

oleg_2, попробуйте разместить файл в директории /tmp.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение21.02.2017, 16:11 


02/10/12
308
На сервере файловая система ext4. На моём ноутбуке даже в "/tmp/test" результат прежний:
Код:
t1=0.000 sec
t2=0.194 sec
t3=1.343 sec
t4=1.343 sec
t5=9.562 sec


-- 21.02.2017, 17:19 --

Я так понимаю, что в /tmp файл хранится прямо в памяти, а не на диске.

 Профиль  
                  
 
 Re: СИ. Программа подвисает на close(fd). И сигнал.
Сообщение21.02.2017, 16:30 
Заслуженный участник


09/05/12
25179
oleg_2 в сообщении #1194373 писал(а):
Я так понимаю, что в /tmp файл хранится прямо в памяти, а не на диске.
Не обязательно.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group