Jump to content
Калькуляторы

вопрос к гуру ядра линукс

В модуле ядра линукс нужно крутить 8 счетчиков типа uint_32

Какой тип взаимной блокировки лучше использовать

spin_lock_bh(&a->lock)
a->counter1++;
.....
a->counter8++;
spin_unlock_bh(&a->lock)

или же как в атомарных операциях

unsigned long flags;
local_irq_save(flags)
a->counter1++;
.....
a->counter8++;
local_irq_restore(flags)

 

 

счетчики крутятся в match функции match модуля для iptables(простая считалка пакетов типа ip_account).

Жду ответов. Спасибо.

Share this post


Link to post
Share on other sites
В модуле ядра линукс нужно крутить 8 счетчиков типа uint_32

счетчики крутятся в match функции match модуля для iptables(простая считалка пакетов типа ip_account).

Жду ответов. Спасибо.

Для счетчиков не важен порядок выполнения, а важна атомарность. Для атомарных целочисленных операций есть такое:

#include <asm/atomic.h>

atomic_t x1 = ATOMIC_INIT(0);
int x;

atomic_inc(&x1);
x = atomic_read(&x1);

 

Однако, не переполнятся ли uint_32 слишком быстро?

Edited by photon

Share this post


Link to post
Share on other sites
В модуле ядра линукс нужно крутить 8 счетчиков типа uint_32

счетчики крутятся в match функции match модуля для iptables(простая считалка пакетов типа ip_account).

Жду ответов. Спасибо.

Для счетчиков не важен порядок выполнения, а важна атомарность. Для атомарных целочисленных операций есть такое:

#include <asm/atomic.h>

atomic_t x1 = ATOMIC_INIT(0);
int x;

atomic_inc(&x1);
x = atomic_read(&x1);

 

Однако, не переполнятся ли uint_32 слишком быстро?

не переполнятся. Они раз в 30 секунд будут сниматься.

Про атомарность думал. Но в том же asm/atomic.h вот что за код:

static inline int atomic_add_return(int i, atomic_t *v)
{
        unsigned long flags;
        int temp;

        local_irq_save(flags);
        temp = v->counter;
        temp += i;
        v->counter = temp;
        local_irq_restore(flags);

        return temp;
}

static inline void atomic_inc(atomic_t *v)
{
        atomic_add_return(1, v);
}

То есть поидее оптимальней будет сделать:

unsigned long flags;
local_irq_save(flags);
counter1++;
................
counterN++;
local_irq_restore(flags);

или я не прав?

Share this post


Link to post
Share on other sites

Делайте как хотите. В любом случае, лучше пользоваться готовым API, чем изобретать свои велосипеды.

Share this post


Link to post
Share on other sites
Делайте как хотите. В любом случае, лучше пользоваться готовым API, чем изобретать свои велосипеды.

Ясно. Спасибо. Буду пробовать :)

 

Share this post


Link to post
Share on other sites
В модуле ядра линукс нужно крутить 8 счетчиков типа uint_32

Какой тип взаимной блокировки лучше использовать

...

счетчики крутятся в match функции match модуля для iptables(простая считалка пакетов типа ip_account).

Если у вас не SMP система - блокировка не нужна вообще, ибо операция 'inc dword ptr ...' выполняется атомарно.

Если все же SMP, то тут два варианта:

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

свой комплект, а результат получать суммированием по всем N комплектам счетчиков. В этом случае блокировок не будет вообще.

Для абсолютно точного получения результата проще всего создать новый комплект нулевых счетчиков, и поменять его местами

с текущим, причем операцию земены сделать атомарной через 'lock mov ...'. Соответственно полученый 'старый' комплект счетчиков

обрабатывать, и нулить.

2. Если п1 не подходит (или не intel) - делайте mutex lock.

 

Частая блокировка прерываний сильно ухудшает производительность.

Share this post


Link to post
Share on other sites

А по хорошему нужно всего лишь прочитать это

 

http://www.kernel.org/pub/linux/kernel/peo...king/index.html

 

и не пытаться изобретать велосипед. Там рассмотрены все возможные варианты синхронизации.

 

P.S.: Не обращайте внимания на дату документа. Он все еще очень актуален.

 

делайте mutex lock
В softirq? Где нельзя спать? Ничего хорошего не получится. :(

Share this post


Link to post
Share on other sites
В softirq? Где нельзя спать? Ничего хорошего не получится. :(
Я имел в виду не фунционал ядра, а тип семафора. Правильней даже spinlock, но без cli/sti. Конечно, в softirq любой sched() приведет к bug(scheduling_in_interrupt). Простой семафор для SMP делается через lock cmpxchg, тем более, что время, на которое делается блоировка не существенно.

 

Но правильно придумать алгоритм, что бы вообще избежать лочек.

Edited by bitbucket

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this