LINUX.ORG.RU

выделение памяти в модуле ядра


0

0

Подскажите пожалуйста, правильно ли выделяется и освобождается память в модуле ядра с целью
последующеготображения через mmap?
После нескольких циклов выделения/освобождения свободная память в системе заканчивается и
не выделяется необходимое количество блоков.
Ядро 2.4.18. Спасибо. Привожу псевдокод выделения/освобождения памяти.
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
	//Allcoate m_blkNum blcok of memory m_blkSize
	for( ii=0; ii<m_blkNum; ii++ )
	{
		m_arrBlock[ii].sysAdr = pci_alloc_consistent( m_pci, 
							      m_blkSize, 
							      &m_arrBlock[ii].phyAdr );
		
		
		if( pcbuf->m_arrBlock[ii].sysAdr == NULL ) 
		{
			printk("<0> Allocc(()) failed allocate memory for block=%d,\
						 ptr=0x%X\n", ii, (int)pBlk[ii] );
			
			return -ENOMEM;
		}
		
		//try to lock all physical pages in the current block
		lock_pages( m_arrBlock[ii].sysAdr, m_blkSize );
		
	}
	
	//free allocated memory blocks
	for( ii=0; ii<m_blkNum; ii++ )
	{
		if(m_arrBlock[ii].sysAdr != NULL)
		{
			//unlock all physical pages in the current block
			unlock_pages( m_arrBlock[ii].sysAdr, m_blkSize );
				
			pci_free_consistent( m_pci, m_blkSize, 
					     m_arrBlock[ii].sysAdr, 
					     virt_to_bus(m_arrBlock[ii].sysAdr));
		}
	}	
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
static int lock_pages( void *va, u32 size )
{
	int j=0; 
	
	struct page *start_page_addr = virt_to_page( va );
		
	spin_lock(&init_mm.page_table_lock);
	for (j=0; j < (size >> PAGE_CACHE_SHIFT); j++) {
		SetPageReserved((start_page_addr+j));
		//printk("<0> start_page_addr[%i] = 0x%X\n", j, (int)(start_page_addr+j) );
	}
	spin_unlock(&init_mm.page_table_lock);	
	//set lock status;
		
	return 0;	
} 

//--------------------------------------------------------------------

static int unlock_pages( void *va, u32 size )
{
	int j=0; 
	
	struct page *start_page_addr = virt_to_page( va );
	
	spin_lock(&init_mm.page_table_lock);		
	for (j=0; j < (size >> PAGE_CACHE_SHIFT); j++) {
		ClearPageReserved((start_page_addr+j));
		//printk("<0> start_page_addr[%i] = 0x%X\n", j, (int)(start_page_addr+j) );
	}
	spin_unlock(&init_mm.page_table_lock);
	//clear lock status

	return 0;	
}	

//--------------------------------------------------------------------

Re: выделение памяти в модуле ядра

про память ничего сказать не могу, а вот по оптимизации можно предложить:

заменить 
   if( pcbuf->m_arrBlock[ii].sysAdr == NULL ) 
на
   if(unlikely(pcbuf->m_arrBlock[ii].sysAdr == NULL)),

а
   if(m_arrBlock[ii].sysAdr != NULL)
можно на
   if(likely(m_arrBlock[ii].sysAdr != NULL))
или тоже unlikely.

:)

RomanU ()

Re: выделение памяти в модуле ядра

не очень понял вопрос.

mmap делается? или память теряется просто после
allocate/deallocate? вроде не должно быть на
первый взгляд.

spin_lock(&init_mm.page_table_lock) абсолютно
не нужен. память принадлежит вам, никто ее видеть
не может, можете играться с PG_reserved без всяких
блокировок.

idle ★★★★★ ()
Ответ на: Re: выделение памяти в модуле ядра от idle

Re: выделение памяти в модуле ядра

idle: >mmap делается?

mmap делается без проблем. Я предполагаю, что память теряется после allocate/deallocate. Но как проверить это не знаю? Еще может на правильную мысль наведет тот факт, что памяти выделяется не так много. На машине с 256 Мб (RAM) выделяется только 98 Мб. Причем от размера блока m_blkSize объем не завист.

Спасибо за помощь. Кстати а что делают unlikely/likely можете пояснить, или где посмотреть? Я впервые о них слышу.

karak ()
Ответ на: Re: выделение памяти в модуле ядра от karak

Re: выделение памяти в модуле ядра

> Кстати а что делают unlikely/likely можете пояснить, или где
> посмотреть? Я впервые о них слышу.

Впервые - это очень интересно:) потому как они на каждом углу в ядре.
Когда я стал смотреть исходники, я постоянно на них натыкался,
в результате чего и стал искать, что же это такое.

Находятся в include/linux/compiler.h

#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

Это расширения gcc, которые позволяют предсказать компилятору
ветку перехода.

Есть небольшое пояснение тут:

http://thep.physik.uni-mainz.de/pipermail/ginac-devel/2001-September/000329.html


но что-то сейчас недоступен этот линк.
Ну, в любом случае, info gcc на предмет __builtin_expect :)

RomanU ()
Ответ на: Re: выделение памяти в модуле ядра от karak

Re: выделение памяти в модуле ядра

> mmap делается без проблем.

тогда я думаю (хотя я очень невнимательно читал приведенный код)
что проблема где-то там. скажем, неправильное манипулирование
page->_count. вы можете это легко проверить, впрочем. вызывайте
allocate/deallocate (без реального использования) и смотрите,
течет ли память.

поищите на этом форуме по PageReserved, подобные проблемы уже
обсуждались.

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