Перейти к содержимому
Калькуляторы

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

В модуле ядра линукс нужно крутить 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).

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В модуле ядра линукс нужно крутить 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 слишком быстро?

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В модуле ядра линукс нужно крутить 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);

или я не прав?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

...

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

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

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

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

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

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

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

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В Linux 2.6 есть API для per-cpu счетчиков, если есть возможность - используйте их. http://lwn.net/Articles/22911/

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

Изменено пользователем bitbucket

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.