2010-07-13 2 views
1

Мне нужно написать регистрацию api, которая выполняет фактическое ведение журнала в отдельном потоке.захватить стек вызовов и выполнить его в другом потоке

У меня есть приложение, которое хочет зарегистрировать некоторую информацию. Он вызывает мой API, и api захватывает все аргументы и т. Д., А затем передает их отдельному потоку для регистрации.

Регистратор api принимает вариативные аргументы, и поэтому мои первоначальные мысли заключались в том, чтобы захватить весь стек вызовов и как-то передать его потоку, который будет вести журнал.

Я рад, что я могу захватить стек вызовов. Однако я не уверен, как передать этот стек вызовов другому методу.

Я использую g ++ на linux, и ему также может потребоваться работать с CC CC CC на Solaris.

Любые идеи.

ответ

2

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

Я предполагаю, что вы используете отдельный поток журналов, чтобы повысить эффективность протокола ведения журнала. Вполне вероятно, что в этом случае более эффективно использовать API журналов для извлечения вариативных параметров, преобразовать их в более простое представление (например, строку, подлежащую протоколированию) и очередь.

Обратите внимание также, что хороший API протоколирования не должен блокироваться, поэтому я бы посоветовал незафиксированную очередь между API протоколирования и потоком ведения журнала.

+0

Спасибо, Фредерик. Это и есть причина, лежащая в основе резака с резьбой. Я хочу, чтобы медленная работа диска io ушла в другой поток. Я попытался скопировать стек, но, конечно, это все равно означает, что все объекты, которые регистрируются, должны быть достаточно длинными, чтобы их можно было заносить в журнал. Я думаю, вы идете построить строку ведения журнала в точке вызова, а затем передать ее в журнал - это лучший подход. – ScaryAardvark

0

Проблема в том, что вы не знаете, как передать ее другому потоку, проще всего иметь очередь (std :: deque, возможно) вызовов с мететексом, защищающим его. Когда ваше приложение сгенерировало стоп-колл, оно блокировало бы мьютекс, нажимало бы стоп-код, а затем разблокировал мьютекс. Протоколирующий поток периодически блокирует мьютекс, проверяет размер очереди и, если он не пуст, снимает стоп-сигнал и обрабатывает его.

Есть способы повысить эффективность там (например, переменные состояния, используя отдельный счетчик, поэтому вам не нужно блокировать перед проверкой размера или даже с использованием неблокирующих структур данных), но я бы рекомендовал не беспокоиться о тех, пока они не появятся в профилировании.

0

Альтернативный подход может быть:

  1. Определите макрос, который печатает имя функции и некоторую дополнительную информацию, как имя файла, номер строки и т.д., используя стандартные предопределенные макросы. Вы даже можете передать некоторую дополнительную информацию журнала, которую в противном случае вы использовали бы printf. Это вызовет функцию отправки данных в другой поток. Эта нить может ждать сокет/труба. Запишите данные в это, и вы сможете читать с него с помощью системных вызовов (write/read/pipe).
  2. Теперь вставьте этот макрос в начале каждой функции/API. Вы можете получить callflow (стек вызовов)
  3. Ваш поток ведения журнала может затем использовать информацию из этого макроса для записи в файл, отображения на консоли и т. Д.

    определяют PRINT_LOG (Х) function_to_pass_data_to_thread (X, FILE, ЛИНИЯ);

    API1() 
    { 
        PRINT_LOG("Entered API1"); 
        //Your API here 
    

    }

PS: К сожалению о дрянной редактирования. Кажется, я не понимаю, что сегодня проблема с редактором. Нужно записать ошибку SO, я думаю .;)

Смежные вопросы