LINUX.ORG.RU

Линукс и реальное время или почему fflush не работает как надо


0

0

В очередной раз пишу не надеясь получить ответа на вопрос, но для очестки совести. Рассказывали, что ОС реального времени - эта та, время реакции которой прогнозируемо. Отлично. Тогда скока же времени нужно линуксу, чтобы записать на жёсткий диск 1 мегабайт ? Не спешите с ответами. Сначала давайте-ка напишем программку, которая раз в 50 миллисекунд валит в файл на диск информацию порциями по 1000000 байт. В программе посчитаем, скока нужно линуксу времени для этого. А получается вот что : в большинстве случаев времени для этого линуксу надо довольно мало, но периодиски мы имеем что линуксу для записи 1 мегабайта на диск надо 300-2000 миллисекунд ! И всё бы было объяснимо и понятно, кеширование там и всё такое, если бы не одна деталька : после записи информации мы используем функцию fflush, которая обязана содержимое буферов сбросить на диск. Что же это за взбрыкивания такие, а, дорогие товарищи ? Какова их природа, объясните пжлста, если можете. Текст програмы приведу ниже.


# include <sys/timeb.h>
# include <stdio.h>
# include <time.h>
# include <sys/time.h>


__inline__ unsigned long long int rdtsc()
{
	unsigned long long int x;
	__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
	return x;
}

unsigned long long GetCurrentTime(void)
{
	static struct timeb tt;
	unsigned long long result;
	
	static struct timeval ttt;
	struct timezone tz;
	unsigned long long int r;
	
	ftime(&tt);
	
	int rv;
	
	rv = gettimeofday(&ttt, &tz);
	
	
	r = rdtsc();
	
	result=(unsigned long long)((unsigned long long)ttt.tv_sec/*time(&unused)*/ * (unsigned long long)1000000)+(unsigned long long)ttt.tv_usec;
	
	return result;
}

/* миллисекунд */
void usleep_my (unsigned int ms)
{
	struct timespec req;
	
	
	if (!ms) return;
	
	req.tv_sec=ms/1000;
	req.tv_nsec=(ms-req.tv_sec*1000)*1000000;
	
	nanosleep(&req, NULL);
}

int main (void)
{
# define SIZEOFBUFFER 1000000
	char buffer [SIZEOFBUFFER];
	unsigned long long t1, t2;	
	
	FILE * fil;
	
	
	fil = fopen("test.null", "a");
	
	while (1)
	{
		usleep_my(50);
		
		t1 = GetCurrentTime();
		
		fwrite (buffer, SIZEOFBUFFER, 1,  fil);
		fflush (fil);
		
		t2 = GetCurrentTime();
		
		printf ("%2.1f \n", (double)(t2-t1));
		
		t1 = t2;
	}
}

lenin
() автор топика
Ответ на: комментарий от lenin

Наблюдать за программой минутку-две.

lenin
() автор топика
Ответ на: комментарий от alexru

Какой патч посоветуете ? Можно ли отключить кеширование данных ? Нужно чтобы сразу сбрасывались, как в чистой ДОС.

lenin
() автор топика
Ответ на: комментарий от lenin

А если добавть sync(); , то всё ок:)

anonymous
()
Ответ на: комментарий от lenin

Иди-ка ты почитай man fflush для начала, прежде чем в очередной раз всякую фигню сюда писать.

fflush НЕ СБРАСЫВАЕТ буфера на диск, задача fflush в том, чтобы выполнить системный вызов write для буфера потока (FILE *), находящегося в пространстве пользователя.

anonymous
()
Ответ на: комментарий от lenin

Чтобы сбрасывалось сразу на диск нужно добавить при его монтировании опцию sync.

alexru ★★★★
()

>ассказывали, что ОС реального времени - эта та, время реакции которой ?

каким боком относиться linux к ОС жесткого реального времени?

fghj ★★★★★
()
Ответ на: комментарий от fghj

ты всё испортил: теперь Россия не выполнит свои обязательства по экспорту сероводорода :)

Pi ★★★★★
()
Ответ на: комментарий от lenin

> Можно ли отключить кеширование данных ? Нужно чтобы сразу сбрасывались, как в чистой ДОС.

Блин, троллюга недобитая... Прочти man 2 open ВНИМАТЕЛЬНО на предмет опции O_SYNC. В сщчетании с fflush это даст запрошеный тобой эффект.

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

И еще - если тебе нужен именно FILE * для fprintf, fputs и так далее на синхронных операциях, используй open + fdopen + setvbuf.

no-dashi ★★★★★
()

man fsync
man fdatasync
сначала fflush, потом fdatasync, только после этого долетят изменения до диска.

Casus ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.