The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
POSIX сигналы. Реализация программного прерывания по таймеру, !*! xBTx, 08-Июл-10, 19:18  [смотреть все]
Народ в общем такая проблема.
Есть таймер (200Гц) , выдающий сигналы SIGUSR1. Есть процесс состоящий из двух потоков - каждый
просто бесконечно инкрементирует и сбрасывает счетчик - тем самым создают полную загрузку процессора.
Необходимо реализовать немедленную реакцию на сигналы таймера (фактически вне зависимости от приоритетов и операций выполняемых потоками)
На первый взгляд самое просто повесить обработчик сигналов с помощью sigaction(). Что я и пытаюсь делать. Проверка "немедленной реакции " осуществляется банально - внутри обработчика инкрементирую счетчик по достижению числа кратного 200 инкрементирую 2ой счетчик и вывожу на экран. Таким образом выводимые значения должны просто соответствовать значению секундомера (в сек).Но в реальности происходит очень сильное отставание (секунд 15-20 за минуту). Вот реализация:

#include <cstdio>
#include <signal.h>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "../libraries/timer_200.h"//таймер 200Гц

using namespace std;

void * thread_func (void * arg)
{
int j=0;
    while (1)
    {
        j++;
        if (j>300) j=0;
    }
}

int init_thread ( int priority)
{
int i=0;
pthread_t pid;
pthread_attr_t attr;  

struct sched_param param;
  
    pthread_attr_init ( &(attr) );
    if (priority >= 0 )
    {
        pthread_attr_setinheritsched(&(attr), PTHREAD_EXPLICIT_SCHED);

    }

    pthread_create ( &(pid), &(attr), thread_func, NULL ); //Thread creation

    if (pid < 0)
    {
        printf ("\nCan't creat  thread !!!\n");
      
    }
    else
    {
        if (priority >=0)
        {

            param.sched_priority = priority;
            sched_setparam ( pid, ¶m );

        }
    }
}

static void sighandler(int sig, siginfo_t * , void * )
{
static int time=0;
static unsigned long int  counter=0;
    counter++;
    if (counter > 4000000) counter =1;
    if (counter % 200 == 0)
    {
        time++;
  
               cout<<"The handler works !!! Time="<<time<<endl;
    }
}

void init_handler()
{
    struct sigaction mysig;
    mysig.sa_sigaction = sighandler;
    mysig.sa_flags = SA_SIGINFO;
    sigaction(SIGUSR1, &mysig, NULL);
}
int main()
{
unsigned long int j =0;
int i=0;
    InitMainClk();//Timer init
    init_handler();
    init_thread(-1);

    //Разблокируем сигнал
    sigprocmask (SIG_UNBLOCK, &set, NULL);

    while (1)
    {
        i++;
        if (i % 200 == 0)
        {
            i=0;
            j++;
            if (j > 1000000) j=1;
        }

    }
return 0;
}

Соответственно в чем может быть проблема ? Кто не успевает? немедленно ли процесс реагирует на сигнал и если этот вариант плох - что можно сделать, чтобы реализовать немедленный вызов некоторой функции (обработки) с заданной частотой с прерыванием других потоков.

ВСЕМ ЗАРАНЕЕ СПАСИБО !

  • теряются сигналы , !*! Вова, 12:26 , 09-Июл-10 (1)

    >[оверквотинг удален]
    >static unsigned long int  counter=0;
    >    counter++;
    >    if (counter > 4000000) counter =1;
    >    if (counter % 200 == 0)
    >    {
    >        time++;
    >
    >            
    >   cout<<"The handler works !!! Time="<<time<<endl;
    >    }

    необходимо блокировать сигналы в обработчике, они теряются - http://www1.lib.ru/CTOTOR/book.txt_with-big-pictures.html

  • POSIX сигналы. Реализация программного прерывания по таймеру, !*! кошечка, 23:18 , 11-Июл-10 (2)
    >[оверквотинг удален]
    >    }
    >return 0;
    >}
    >
    >Соответственно в чем может быть проблема ? Кто не успевает? немедленно ли
    >процесс реагирует на сигнал и если этот вариант плох - что
    >можно сделать, чтобы реализовать немедленный вызов некоторой функции (обработки) с заданной
    >частотой с прерыванием других потоков.
    >
    >ВСЕМ ЗАРАНЕЕ СПАСИБО !

    собсно проблема в том что выполнение обработчика сигнала требует
    контекста процесса. так что выглядит все таким образом
    1) истекает таймер, ядро шлет процессу SIGUSR1
    2) _КОГДА ПРОЦЕСС ЗАСКЕДУЛИТСЯ__, управление получит обработчик сигнала

    соответственно момент 2 вовсе не обязан настать сразу после истечения таймера.
    похоже что вам нужно спустится в ядро

  • POSIX сигналы. Реализация программного прерывания по таймеру, !*! f00l, 09:56 , 12-Июл-10 (3)
    >Соответственно в чем может быть проблема ? Кто не успевает? немедленно ли
    >процесс реагирует на сигнал и если этот вариант плох - что
    >можно сделать, чтобы реализовать немедленный вызов некоторой функции (обработки) с заданной
    >частотой с прерыванием других потоков.
    >
    >ВСЕМ ЗАРАНЕЕ СПАСИБО !

    Если нужна высокая точность , то такими операторами как cout уже не пользуются и по не зависимому секундомеру не замеряют .

    Возможный алгоритм, используется функция clock() минимальная информация записывается в память и по прошествии нескольких минут выводится на экран , при выводи на экран есть понятие буферизация , то есть накопление и задержка в отображении .

    По умолчанию ядро работает на 100 Hz, то есть планировщик задач переключает процессы и передает им сигналы раз в 1/100 с , здесь требуется скорость в два раза выше .

    Либо изменять условия задачи, либо писать модуль ядра .





Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру