#define SI_ASYNCIO   (-4)

#define SI_MESGQ     (-5)

#define SI_NOTIFY    (-6)

#define SI_IRQ       (-7)

// QNX managers will never use this range.

#define SI_MINAVAIL  (-128)

#define SI_MAXAVAIL  (-64)

#define SI_NOINFO    127

#define SI_MAXSZ     126

Значение SI_QUEUE, равное -2, — это и есть то значение, которое мы видели в выводе тестовой задачи выше.

Соображения производительности

Ранее мы производили оценку затрат производительности процессора на переключение между контекстами для процессов и для потоков (тестовые задачи, которые мы по их структуре именовали как «симметричные»). Проделаем теперь то же самое, но синхронизацию процессов выполним посылкой и приемом сигнала (переключение контекстов будет происходить именно на операторе pause() — переходе к приему сигнала) (файл p6s.cc):

Затраты на переключение процессов посылкой сигналов

#include <stdlib.h>

#include <stdio.h>

#include <inttypes.h>

#include <iostream.h>

#include <unistd.h>

#include <sched.h>

#include <sys/neutrino.h>

// 'пустые' обработчики сигналов

static void nhand(int signo) {}

static void qhand(int signo, siginfo_t* info, void* context) {}

int main(int argc, char *argv[]) {

 unsigned long N = 1000;

 bool que = false;

 int opt, val;

 while ((opt = getopt(argc, argv, 'n:q')) != -1) {

  switch(opt) {

  case 'n':

   if (sscanf(optarg, '%i', &val) != 1)

    cout << 'parse command line error' << endl, exit(EXIT_FAILURE);

   if (val > 0) N = val;

   break;

  // ключ q определяет схему обработки сигнала

  case 'q':

   que = true;

   break;

  default:

   exit(EXIT_FAILURE);

  }

 }

 // установка сигнальных обработчиков

 sigset_t sig;

 sigemptyset(&sig);

 sigaddset(&sig, SIGUSR1);

 sigprocmask(SIG_UNBLOCK, &sig, NULL);

 struct sigaction act;

 act.sa_mask = sig;

 act.sa_sigaction = qhand;

 act.sa_handler = nhand;

 act.sa_flags = que ? SA_SIGINFO : 0;

 if (sigaction(SIGUSR1, &act, NULL) < 0)

  cout << 'set signal handler' << endl, exit(EXIT_FAILURE);

 pid_t pid = fork();

 if (pid == -1)

  cout << 'fork error' << endl, exit(EXIT_FAILURE);

 // кому отправлять сигнал?

 pid_t did = (pid == 0 ? getppid() : pid);

 unsigned long i = 0;

 uint64_t t = ClockCycles();

 while (true) {

  kill(did, SIGUSR1);

  if (++i == N) break;

  pause();

 }

 t = ClockCycles() - t;

 cout << getpid() << ' -> ' << did << ' : cycles - ' << t <<

  '; on signal - ' << (t / N) / 2 << endl;

exit(EXIT_SUCCESS);

}

Этим приложением мы можем тестировать и традиционную схему обработки сигналов (модель надежных сигналов), и схему обработки с очередью поступления сигналов (модель сигналов реального времени), когда при старте программы указан ключ -q. Посмотрим на результаты тестовых запусков:

# nice -n-19 p6s -n1000

2904115 -> 2912308 : cycles - 5792027; on signal - 2896

2912308 -> 2904115 : cycles - 5828952; on signal — 2914

# nice -n-19 p6s -n10000

2920499 -> 2928692 : cycles - 57522753, on signal - 2876

2928692 -> 2920499 : cycles - 57530378; on signal - 2876

# nice -n-19 p6s -n100000

2936883 -> 2945076 : cycles - 573730469; on signal - 2868

2945076 -> 2936883 : cycles - 573738122; on signal - 2868

# nice -n-19 p6s -n1000000

2953267 -> 2961460 : cycles - 5747418203, on signal - 2873

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату