<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
<title>sb0y[AT]home</title>
<link>https://bagrintsev.me/</link>
<description>Уютный бложик девелопера.</description>
<language>ru</language>
<pubDate>Sun, 12 Apr 2026 23:11:22 +0300</pubDate>

<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>https://bagrintsev.me//</generator>
<managingEditor>sb0y@bagrincev.ru</managingEditor>
<webMaster>sb0y@bagrincev.ru</webMaster>

<item>
	<title>sleep() в C</title>
	<link>https://bagrintsev.me/blog/sleep-c/</link>
	<description>Многие знают, что sleep() обладает плохой точностью. Многие так же знают, что sleep(), как и любой блокирующий системный вызов нужно вызывать в цикле, так как он попросту может не выждать требуемое от него количество времени. Но в таком случае, после обработки сигнала, когда управляющий поток вернётся в место, где его прервали, sleep() будет вызван с теми же параметрами, что и первый раз.Возможно, Вы думаете, что можно положиться на то, что sleep() возвращает время, которое ему нужно "доспать" и просто итерировать цикл, до тех пор, пока возвращаемое значение не будет равно 0. Давайте обратимся к документации библиотеки libc.</description>
	<content:encoded><![CDATA[[Многие знают, что sleep() обладает плохой точностью. Многие так же знают, что sleep(), как и любой блокирующий системный вызов нужно вызывать в цикле, так как он попросту может не выждать требуемое от него количество времени.<br>
Но в таком случае, после обработки сигнала, когда управляющий поток вернётся в место, где его прервали, sleep() будет вызван с теми же параметрами, что и первый раз.<br><br>
Возможно, Вы думаете, что можно положиться на то, что sleep() возвращает время, которое ему нужно "доспать" и просто итерировать цикл, до тех пор, пока возвращаемое значение не будет равно 0. Давайте обратимся к <a target="_blank" href="http://www.gnu.org/software/libc/manual/html_mono/libc.html#Sleeping">документации библиотеки libc</a>.<br><br>

<blockquote>
Resist the temptation to implement a sleep for a fixed amount of time by using the return value of sleep, when nonzero, to call sleep again. This will work with a certain amount of accuracy as long as signals arrive infrequently. But each signal can cause the eventual wakeup time to be off by an additional second or so. Suppose a few signals happen to arrive in rapid succession by bad luck—there is no limit on how much this could shorten or lengthen the wait.
</blockquote>

Тоесть, разработчики стандартной библиотеки C настоятельно рекомендуют воздерживаться от такого кода:<br><br>

<code lang="cpp">
int n = 1;
while (n>0) {
 n = sleep(n);
}
</code>

Потому, что жизненный путь программы может пролегать через ситуации, когда процессу будет приходить любое количество сигналов, любых типов, в любой последовательности и в ходе прерывания слипа однажды, может совершенно спокойно пропасть или добавиться секунда или больше (или меньше). Особенно это касается сигнала <samp>SIGALRM</samp>. На некоторых системах, даже если Вы перехватили, заблокировали этот сигнал, sleep() может закончиться раньше. И это не полный список проблем.<br><br>

Все эти проблемы можно решить разными способами, но есть один вариант, который покрывает их всех вместе. Используйте <strong><a target="_blank" href="http://man7.org/linux/man-pages/man2/nanosleep.2.html">nanosleep()</a></strong>. Если механизм обработки сигналов прервёт выполнение этого вызова -- он вернёт <samp>-1</samp> и errno будет установлена в значение <samp>EINTR</samp>.
А факт того, что, она запишет оставшееся время ожидания в наносекундах в структуру <samp>timespec</samp>, указатель на которую можно передать вторым аргументом, позволит корректно продолжить "сон".<br><br>

<code lang="cpp">
#include <errno.h>
#include <time.h>

int sleep_ex( unsigned long sleep_time_sec )
{
        struct timespec tv;
        /* Construct the timespec from the number of whole seconds... */
        tv.tv_sec = sleep_time_sec;
        /* ... and the remainder in nanoseconds. */
        tv.tv_nsec = static_cast < long > ( ( sleep_time_sec - tv.tv_sec )  * 1000000000  );

        int rval = 0;

        // repeat nanosleep() call only if rval == -1 and errno set to EINTR
        do {
                /* Sleep for the time specified in tv. If interrupted by a
                 signal, place the remaining time left to sleep back into tv. */
                rval = nanosleep ( &tv, &tv );
        } while ( rval == -1 && errno == EINTR );

        return rval;
}
</code>]]></content:encoded>
	<pubDate>Sat, 05 Mar 2016 03:00:00 +0300</pubDate>
	
	<category><![CDATA[Программирование]]></category>	<comments>https://bagrintsev.me/blog/sleep-c</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/sleep-c</guid>
</item>
<item>
	<title>pthread_cancel() и C++</title>
	<link>https://bagrintsev.me/blog/pthread-cancel-in-cpp/</link>
	<description>С приходом в нашу жизнь реализации Linux тредов NPTL, стало доступно досрочное завершение тредов. Представьте себе ситуацию, когда у Вас есть треды с блокирующими системными вызовами или просто треды, использующие sleep() (что ещё хуже) и Вам вдруг понадобилось их завершить. В случае, если Вы программируете на С, скорей всего проблем не будет. Грабли начинают когда Вы решаете сделать тоже самое в C++.Конечно, с ходу можно посоветывать переписать код и использовать неблокирующие системные вызовы в бесконечном цикле, с условием итерирования. А sleep() заменить на nanosleep() с обработкой EINTR. Но всегда есть абстрактная ситуация в вакууме, когда есть рабочий код и Вам придётся разбираться почему он падает после Ваших изменений.Кроме того, принудительное завершение треда, может избавить Вас от необходимости контроля начавшейся итерации цикла, или даже, в теории отменить уже запущенный системный вызов, который использует переход в режим ядра (kernel mode).</description>
	<content:encoded><![CDATA[[С приходом в нашу жизнь реализации Linux тредов <abbr title="Native POSIX Thread Library">NPTL</abbr>, стало доступно досрочное завершение тредов. Представьте себе ситуацию, когда у Вас есть треды с блокирующими системными вызовами или просто треды, использующие sleep() (что ещё хуже) и Вам вдруг понадобилось их завершить. В случае, если Вы программируете на С, скорей всего проблем не будет. Грабли начинают когда Вы решаете сделать тоже самое в C++.
<br><br>
Что может случиться плохого? Такой подход соврешенно не совместим с <abbr title="Resource Acquisition Is Initialization (Получение ресурса есть инициализация)">RAII</abbr>.<br>
Рассмотрим пример, который <ins>гарантированно</ins> падает.<br><br>

<code lang="cpp">
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <exception>

class Object
{
public:
  ~Object() {
  std::cout << "Inside ~Object()" << std::endl;
  sleep ( 999 );
  }
};
 
void newThread()
{
  try {   
    Object regular_object_on_stack;
    std::cout << "Inside the new thread" << std::endl;
    // ... billion strings of code ...
    throw std::runtime_error ( "Random exception" );
  } catch ( const std::runtime_error& e ) {
   std::cout << "You will never see this exception: " << e.what() << std::endl;
  } 
}

int main()
{
   pthread_t thread;
   pthread_create ( &thread, nullptr, &newThread, nullptr );
   sleep ( 1 ); // time for new thread for correct init order
   std::cout << "Let's try to cancel our thread ..." << std::endl;
   pthread_cancel ( thread );
   pthread_join ( thread, nullptr );
   std::cout << "You have a good chance not to see this message" << std::endl;
   return 0;
}
</code>

Вот результат выполнения на Ubuntu 15.10:<br><br>

<code lang="bash">
Inside the new thread
Inside ~Object()
Let's try to cancel our thread ...
terminate called without an active exception
Aborted (core dumped)
</code>

Что же происходит в этом коде такого, что необходимо завершить выполнение? К счастью, в Ubuntu 15.10 хороший вывод ошибок и ясно, что виновен не пойманый exception. Но где?
При вызове любого системного вызова отмеченного как "<a target="_blank" href="http://man7.org/linux/man-pages/man7/pthreads.7.html">Cancellation point</a>".<br><br>

Давайте разберём ещё раз, с самого начала. Мы создаём объект класса Object, внутри треда, который спустя секунду, будет отдан на растерзание pthread_cancel(). Внуртри этого же треда, мы кидаем exception, что приводит к stack unwinding и вызову деструкторов объектов на стеке и функция sleep(), переходя в kernel mode и являесь при этом cancellation point, благодаря C++ -- кидает exception, во время раскрутки стека, что и приводит к гарантированному падению нашей программы.<br><br>

Не верите? :-) Попробуйте такой код:<br><br>

<code lang="cpp">
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <exception>

class Object
{
public:
  ~Object() {
   std::cout << "Inside ~Object()" << std::endl;
   try {
    sleep ( 999 );
   } catch ( ... ) {
    std::cout << "We got something strange here ..." << std::endl;
   }
 }
};
 
void newThread()
{
  try {   
   Object regular_object_on_stack;
   std::cout << "Inside the new thread" << std::endl;
   // ... billion strings of code ...
   throw std::runtime_error ( "Random exception" );
 } catch ( std::runtime_error& e ) {
   std::cout << "You will never see this exception: " << e.what() << std::endl;
 } 
}

int main()
{
  pthread_t thread;
  pthread_create ( &thread, nullptr, &newThread, nullptr );
  sleep ( 1 ); // time for new thread for correct init order
  std::cout << "Let's try to cancel our thread ..." << std::endl;
  pthread_cancel ( thread );
  pthread_join ( thread, nullptr );
  std::cout << "You have a good chance not to see this message" << std::endl;
  return 0;
}
</code>

В результате будет такой вывод:<br><br>

<code lang="bash">
Inside the new thread
Inside ~Object()
Let's try to cancel our thread ...
We got something strange here ...
FATAL: exception not rethrown
Aborted (core dumped)
</code>

Поражены? И это в деструкторе объекта! Как Вы понимаете, о <abbr title="Resource Acquisition Is Initialization (Получение ресурса есть инициализация)">RAII</abbr> с таким подходом можно забыть. Вы наверняка захотите использовать такие системные вызовы как fclose(), close(), dlclose() в деструкторе Вашего объекта. <a target="_blank" href="http://man7.org/linux/man-pages/man7/pthreads.7.html">Список</a> cancellation points достаточно обширен!<br><br>

Всё, что вы можете -- попытаться контролировать процесс вхожения в cancellation point, используя <a target="_blank" href="http://man7.org/linux/man-pages/man3/pthread_testcancel.3.html">pthread_testcancel()</a>, которая создаст cancellation point до входа в опасную область видимости. При этом, я сам не уверен, что эта тактика оправданна и вообще имеет право на жизнь.<br><br>

Интересно, что сам этот "exception" добавлеяет <strong>ИМЕННО</strong> C++ и его тип определён в хедере <strong>cxxabi.h</strong>, что значит, что его вполне реально поймать.<br><br>

<code lang="cpp">
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <exception>
#include <cxxabi.h>

void newThread()
{
  try {
    sleep ( 999 );
    std::cout << "Inside the new thread" << std::endl;
    // ... billion strings of code ...
    throw std::runtime_error ( "Random exception" );
  } catch ( abi::__forced_unwind& ) {
    std::cout << "abi::__forced_unwind is catched" << std::endl;
  } 
}

int main()
{
  pthread_t thread;
  pthread_create ( &thread, nullptr, &newThread, nullptr );
  sleep ( 1 ); // time for new thread for correct init order
  std::cout << "Let's try to cancel our thread ..." << std::endl;
  pthread_cancel ( thread );
  pthread_join ( thread, nullptr );
  std::cout << "You have a good chance not to see this message" << std::endl;
  return 0;
}
</code>

Вывод:<br><br>

<code lang="bash">
Let's try to cancel our thread ...
abi::__forced_unwind is catched
FATAL: exception not rethrown
Aborted (core dumped)
</code>

На самом деле, это не столько "exception", сколько механизм для stack unwinding, о чём можно сделать вывод из названия типа "__forced_unwind". Следовательно, раз мы можем его поймать, мы можем его и кинуть далее и даже обработать!<br><br>

<code lang="cpp">
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <exception>
#include <cxxabi.h>

void newThread()
{
  try {
    sleep ( 999 );
    std::cout << "Inside the new thread" << std::endl;
    // ... billion strings of code ...
    throw std::runtime_error ( "Random exception" );
  } catch ( abi::__forced_unwind& ) {
    std::cout << "rethrowing exception ..." << std::endl;
    throw;
  } catch ( ... ) {
    std::cout << "Catch any exception" << std::endl;
  }
}

int main()
{
  pthread_t thread;
  pthread_create ( &thread, nullptr, &newThread, nullptr );
  sleep ( 1 ); // time for new thread for correct init order
  std::cout << "Let's try to cancel our thread ..." << std::endl;
  pthread_cancel ( thread );
  pthread_join ( thread, nullptr );
  std::cout << "You have a good chance not to see this message" << std::endl;
  return 0;
}
</code>

<img src="/my/programming_world.jpg" class="img-responsive img-thumbnail">

Покрайней мере, программа уже не падает :-)<br><br>

<code lang="bash">
Let's try to cancel our thread ...
rethrowing exception ...
You have a good chance not to see this message
</code>

Что и требовалось доказать. Использование pthread_cancelation -- весьма сомнительная возможноcть <abbr title="Native POSIX Thread Library">NPTL</abbr>. Возможно, использование её в языке C оправданно, но в C++, в котором наличествует огромное количество уже готовых типов, которые используют различные системные вызовы, ничего не подозревая о новшествах реализации -- лучше воспользоваться функционалом предоставляемым libstdc++ ну или вообще, BOOST.

<h3>Статьи по теме</h3>
<ul>
<li>
<a target="_bank" href="https://en.wikipedia.org/wiki/Native_POSIX_Thread_Library">WIKI. NPTL.</a>
</li>
<li>
<a target="_bank" href="http://citforum.ru/programming/unix/threads/">Citforum. Потоки.</a>
</li>
<li>
<a target="_bank" href="http://man7.org/linux/man-pages/man7/pthreads.7.html">Man page. Pthreads.</a>
</li>
<li>
<a target="_bank" href="http://man7.org/linux/man-pages/man3/pthread_cancel.3.html">Man page. pthread_cancel.</a>
</li>
<li>
<a target="_bank" href="https://skaark.wordpress.com/2010/08/26/pthread_cancel-considered-harmful/">Skaark blog. pthread_cancel considered harmful
</a>
</li>
<li>
<a target="_bank" href="http://udrepper.livejournal.com/21541.html">Drepper. Cancellation and C++ Exceptions</a>
</li>
</ul>]]></content:encoded>
	<pubDate>Mon, 22 Feb 2016 03:00:00 +0300</pubDate>
	
	<category><![CDATA[Программирование]]></category>	<comments>https://bagrintsev.me/blog/pthread-cancel-in-cpp</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/pthread-cancel-in-cpp</guid>
</item>
<item>
	<title>Создать загрузучную USB-флешку из Linux среды</title>
	<link>https://bagrintsev.me/blog/windows-boot-usb-stick-linux/</link>
	<description>Для Linux существует несколько проектов, позволяющих создавать загрузочные USB носители из ISO образа с Windows. Это и кроссплатформенный UNetbootin и WinUSB, который судя по всему больше не поддерживается автором.Однако, я скачивал Windows 10 с торрентов и записанные флешки на отрез отказывались грузиться :-(Дело то ли в специфике русского Windows, скаченного в торрентов, то ли в ошибках, которые хором повторяют эти программы. К счастью, у нас есть Grub, который грузит всё и всегда.В этой статье я постараюсь кратко изложить, что нужно сделать, чтобы Ваш ISO образ попал на USB носитель и при этом с него можно было бы грузиться.</description>
	<content:encoded><![CDATA[[Для Linux существует несколько проектов, позволяющих создавать загрузочные USB носители из ISO образа с Windows. Это и кроссплатформенный <a target="_blank" href="https://unetbootin.github.io/" target="_blank">UNetBootin</a> и <a target="_blank" href="http://en.congelli.eu/prog_info_winusb.html">WinUSB</a>, который судя по всему больше не поддерживается автором.<br />Однако, я скачивал Windows 10 с торрентов и записанные флешки на отрез отказывались грузиться :-(<br />Дело то ли в специфике русского Windows, скаченного в торрентов, то ли в ошибках, которые хором повторяют эти программы. К счастью, у нас есть Grub, который грузит всё и всегда.<br />В этой статье я постараюсь кратко изложить, что нужно сделать, чтобы Ваш ISO образ попал на USB носитель и при этом с него можно было бы грузиться.<br /><br />Для начала -- смотрите содержимое команды <strong>fdisk -l<br /><br /></strong>
<code lang=bash>
sudo fdisk -l

...

Disk /dev/sdc: 7,3 GiB, 7813988352 bytes, 15261696 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe3c1b8f6

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdc1  *    16128 15261695 15245568  7,3G  c W95 FAT32 (LBA)
</code>
Моя флешка -- <strong>/dev/sdc1</strong>. Не перепутайте!<br />Первое, что сделаем -- отформатируем флешку. Для этого отмонтируем её и создадим разметку FAT32 универсальной командой. <br><br>

<code lang="bash">
sudo umount /dev/sdc1
sudo mkfs.vfat /dev/sdc1
</code>

Ok. Теперь примонтируем наш ISO через loop, чтобы получить доступ к файлам образа. Скорей всего, это так же хорошо будет работать и через любой архиватор, например Ark.
<br><br>
<code lang="bash">
mkdir iso # создадим папку, в которую отобразятся файлы образа
sudo mount -o loop Windows\ 10\ Pro\ x64\ MoverSoft\ 09.2015.iso iso
mount: /dev/loop0 is write-protected, mounting read-only
ls iso/
autorun.inf  autounattend.xml  boot  bootmgr  bootmgr.efi  efi  setup.exe  sources  support
</code>
Ну а теперь примонтируйте обратно флешку. Можно кликнуть на неё в менеджере файлов или просто вытащить из компьютера и вставить обратно.<br>
А далее, просто скопируйте файлы из образа на вашу флешку.
<br><br>
<code lang="bash">
sudo cp -Rf iso/* /media/sb0y/93E0-7F17 # так Ubuntu примонтировала мой USB stick
</code>

После завершения довольно продолжительной операции копирования, настало время сделать главное -- установить и настроить Grub.<br>
Делается это командой:
<br><br>
<code lang="bash">
sudo grub-install --target=i386-pc --boot-directory="/media/sb0y/93E0-7F17/boot" /dev/sdc # обратите внимание, что я не указываю номер раздела
Installing for i386-pc platform.
Installation finished. No error reported.
</code>

Некоторым древним материнским платам, необходим флаг boot на разделе, чтобы начать с него процедуру загрузки. Проставить его можно командой:
<br><br>
<code lang="bash">
sudo parted /dev/sdc set 1 boot on # опять же, обратите внимание, что номер раздела я не пишу
</code>

И последнее, что нужно будет сделать -- сконфигурировать Grub на загрузку ntloader.<br>
Создайте в каталоге <strong>/media/sb0y/93E0-7F17/boot/grub/grub.cfg</strong>, в нём напишете:
<br><br>
<code lang="bash">
set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
menuentry 'Install Windows 10, 8, 7' {
     ntldr /bootmgr
}
</code>
<br>
Вот и всё. Проверено на Windows 7, 8, 10.]]></content:encoded>
	<pubDate>Sun, 17 Jan 2016 03:00:00 +0300</pubDate>
	
	<category><![CDATA[How-to]]></category>	<comments>https://bagrintsev.me/blog/windows-boot-usb-stick-linux</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/windows-boot-usb-stick-linux</guid>
</item>
<item>
	<title>Файл менеджер для директорий в Gigolo на Kubuntu 14.04</title>
	<link>https://bagrintsev.me/blog/gigolo-default-manager-kubuntu-14-04/</link>
	<description>Ранее писал о том, как объяснить Gigolo как работать с различными типами файлов. Это сильно помогало, в случае, если эта полезная программа работала в чужеродной среде, отличной от XFCE4 или Gnome. Последнее обновление Kubuntu принесло новой пищи для размышлений. Описанный способ не работает, gfvs-open теперь не слушается текстового файла defaults.list. Однако, решение нашлось.</description>
	<content:encoded><![CDATA[[<p>Ранее <a href="/blog/gigolo-file-associations" target="_blank">писал</a> о том, как объяснить Gigolo как работать с различными типами файлов. Это сильно помогало, в случае, если эта полезная программа работала в чужеродной среде, отличной от XFCE4 или Gnome. Последнее обновление Kubuntu принесло новой пищи для размышлений. Описанный способ не работает, gfvs-open теперь не слушается текстового файла defaults.list. Однако, решение нашлось. <!--more-->Починили утилиту gvfs-mime. Теперь легитимный обработчик MIME типов можно узнать по команде:</p>

<code lang="bash">gvfs-mime --query inode/directory Приложение по умолчанию для «inode/directory»: kde4-gwenview.desktop Зарегистрированные приложения: kde4-gwenview.desktop kde4-dolphin.desktop Рекомендуемые приложения: kde4-gwenview.desktop kde4-dolphin.desktop </code> 

<p>Ну а теперь, скажем, что мы конкретно хотим:</p>

<code lang="bash">gvfs-mime --set inode/directory kde4-dolphin.desktop Set kde4-dolphin.desktop as the default for inode/directory
</code>]]></content:encoded>
	<pubDate>Sat, 19 Apr 2014 04:00:00 +0400</pubDate>
	
	<category><![CDATA[How-to]]></category>	<comments>https://bagrintsev.me/blog/gigolo-default-manager-kubuntu-14-04</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/gigolo-default-manager-kubuntu-14-04</guid>
</item>
<item>
	<title>Идеальные CFLAGS в Gentoo</title>
	<link>https://bagrintsev.me/blog/ideal-cflags-in-gentoo/</link>
	<description>С 4й версии GCC умеет подбирать оптимальные параметры автоматически, для этого нужно всего лишь указать в CFLAGS ключ -march=native. Однако, бывают случаи, когда -march=native использовать нельзя, например, если у вас distcc (proof) Вот здесь начинается особая, уличная магия. Первое, что нужно сделать - узнать свою модель процессора. Сделать это можно при помощи команды:</description>
	<content:encoded><![CDATA[[<p>С 4й версии GCC умеет подбирать оптимальные параметры автоматически, для этого нужно всего лишь указать в CFLAGS ключ -march=native. Однако, бывают случаи, когда -march=native использовать нельзя, например, если у вас distcc (<a href="http://www.gentoo.org/doc/en/distcc.xml" target="_blank">proof</a>) Вот здесь начинается особая, уличная магия. Первое, что нужно сделать - узнать свою модель процессора. Сделать это можно при помощи команды:</p>

<!--more-->

<code lang="bash">
grep -m1 -A3 "vendor_id" /proc/cpuinfo
</code>

<p>Получите примерно такое:</p>

<code lang="bash">
vendor_id       : GenuineIntel
cpu family      : 6
model           : 30
model name      : Intel(R) Xeon(R) CPU           X3450  @ 2.67GHz
</code>

<p>Простое решение - позаимствовать из архивов Gentoo Wiki набор протестированных флагов (<a href="http://wiki.gentoo.org/wiki/Safe_CFLAGS" target="_blank">раз</a>, <a href="http://www.gentoo-wiki.info/Safe_Cflags" target="_blank">два</a>, <a href="http://gentoo-en.vfose.ru/wiki/Safe_Cflags/Intel" target="_blank">три</a>). Однако такие документации уже довольно стары, а то и вовсе не поддерживаются. Так что вы имеете достаточно большую вероятность просто не найти свой процессор в этих простынях. Поэтому последний и сложный вариант - составить свой собственный, точный набор флагов, используя те же инструменты, что и GCC для -march=native.</p>

<code lang="bash">
# выполнять от root`а
gcc -c -Q -march=native --help=target
</code>

<p>Это команда выведет список флагов, который поддерживает ваш процессор. Используйте осторожно, ибо не всякая программа будет компилироваться с ними. Например от <strong>mstackrealign</strong> у меня намертво отваливалась сборка порта bzip2. Так же будет полезно рассказать GCC сколько памяти у процессора в L-кешах. В этом нам поможет утилита <strong>lscpu</strong>:</p>

<code lang="bash">
sb0y@fabian / $ lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    2
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 30
Stepping:              5
CPU MHz:               2660.000
BogoMIPS:              5320.11
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              8192K
NUMA node0 CPU(s):     0-7
</code>

<p>Теперь можно добавить в CFLAGS: <strong>--param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=8192</strong>. Вот и всё. После установки новых флагов, лучше выполнить emerge system, чтобы быть уверенным, что ничего не сломалось.</p>]]></content:encoded>
	<pubDate>Mon, 01 Jul 2013 04:00:00 +0400</pubDate>
	
	<category><![CDATA[How-to]]></category>	<comments>https://bagrintsev.me/blog/ideal-cflags-in-gentoo</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/ideal-cflags-in-gentoo</guid>
</item>
<item>
	<title>Qt5: скопировать после сборки файлы в build directory</title>
	<link>https://bagrintsev.me/blog/qt5-copy-files-to-build-directory/</link>
	<description>Qt5 создаёт build directory рядом с source directory.Если Ваш проект считывает какие-либо файлы после запуска программы - их нужно положить в соответствующие директории.Qmake позволяет сделать это кроссплатформенно, создав цели для make install.Итак, в файле проекта *.pro добавьте такие строки:</description>
	<content:encoded><![CDATA[[<p>Qt5 создаёт build directory рядом с source directory.
Если Ваш проект считывает какие-либо файлы после запуска программы - их нужно положить в соответствующие директории.
Qmake позволяет сделать это кроссплатформенно, создав цели для make install.</p>

<p>Итак, в файле проекта <strong>*.pro</strong> добавьте такие строки:</p>
<!--more-->
<code lang="make">
install_it.path = $$OUT_PWD
install_it.files += $$PWD/html

INSTALLS += install_it
</code>

<p>Этот код инициализирует массив <strong>install_it</strong>, который заполняется переменной директории сборки (<strong>$$OUT_PWD</strong>) и переменной с директорией исходных кодов Вашего проекта (<strong>$$PWD</strong>).</p>
<p>В итоге скопируется директория <strong>html</strong>, лежащая в директории с исходными кодами.</p>

<p>Про остальные переменные, коими обладает qmake, можно почитать <strong><a href="http://doc.qt.digia.com/4.6/qmake-variable-reference.html" target="_blank">здесь</a></strong>.</p>

<p>Далее нужно попросить QtCreator запускать make install после сборки проекта.</p>
<ul>
<li>Найдите на главной панели слева вкладку "Projects".</li> 
<li>В появившемся окне найдите раздел "Build Steps".</li>
<li>В нём надо нажать на кнопку "Add Build Step".</li>
<li>В выпавшем списке выбирайте пункт "Make".</li>
<li>В поле "Make arguments" напишите <strong>install</strong>.</li> 
</ul>

<a href="/content/postImages/qt5-copy-necessary-files-to-build-directory/1372180518.png"><img src="/content/postImages/qt5-copy-necessary-files-to-build-directory/1372180518_small.jpeg" /></a>

<p>Вот собственно и всё!</p>]]></content:encoded>
	<pubDate>Tue, 25 Jun 2013 04:00:00 +0400</pubDate>
	
	<category><![CDATA[How-to]]></category>	<comments>https://bagrintsev.me/blog/qt5-copy-files-to-build-directory</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/qt5-copy-files-to-build-directory</guid>
</item>
<item>
	<title>Ведущий ноль для чисел в JavaScript</title>
	<link>https://bagrintsev.me/blog/leading-zero-for-a-number-in-javascript/</link>
	<description>Недавно понадобилось повторить работу С-функции printf() с параметром "%02d" на JavaScript.Получилась такая функция:</description>
	<content:encoded><![CDATA[[<p>Недавно понадобилось повторить работу С-функции printf() с параметром "%02d" на JavaScript.
Получилась такая функция:</p>
<!--more-->
<code lang="javascript">
function zeroField (val, numSize)
{
 var outZero = "";
 var zeroCount = numSize - String(val).length;
 for (var x=0; x < zeroCount; ++x) outZero += "0";
 return outZero+val;
}
</code>

<p>Конечно, можно поработать со степенями. Но скорость будет уже не та.</p>
<code lang="javascript">
function zeroField (val, numSize)
{
 var tmp = String (val);
 for (var x=numSize; x; --x)
 {
   if ( val < Math.pow (x, 10) ) 
   {
     tmp = "0" + tmp; 
   }
 }

  return tmp;
}
</code>
<p>
Ну и напоследок, для тех, у кого есть возможность подключать в проекте сторонние библиотеки: <a href="http://www.diveintojavascript.com/projects/javascript-sprintf" target="_blank">реализация printf() на Javascript</a>.
</p>]]></content:encoded>
	<pubDate>Thu, 23 May 2013 04:00:00 +0400</pubDate>
	
	<category><![CDATA[Программирование]]></category>	<comments>https://bagrintsev.me/blog/leading-zero-for-a-number-in-javascript</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/leading-zero-for-a-number-in-javascript</guid>
</item>
<item>
	<title>Пересборка всех модулей Xorg на Gentoo</title>
	<link>https://bagrintsev.me/blog/xorg-modules-rebuild-on-gentoo/</link>
	<description>Вот уже второй раз, после значительных обновлений моей домашней рабочей машины с Calculate, в иксах не работают мышь и клавиатура. В Xorg.log при этом пишется следующее:</description>
	<content:encoded><![CDATA[[<p>Вот уже второй раз, после значительных обновлений моей домашней рабочей машины с <a href="http://www.calculate-linux.ru/" target="_blank">Calculate</a>, в иксах не работают мышь и клавиатура. В Xorg.log при этом пишется следующее:</p>
<!--more-->
<code lang="bash">
[643641.785] (II) LoadModule: "evdev"
[643641.785] (II) Loading /usr/lib64/xorg/modules/input/evdev_drv.so
[643641.785] (II) Module evdev: vendor="X.Org Foundation"
[643641.785]    compiled for 1.13.1, module version = 2.7.3
[643641.785]    Module class: X.Org XInput Driver
[643641.785]    ABI class: X.Org XInput driver, version 18.0
[643641.785] (EE) module ABI major version (18) doesn't match the server's version (19)
[643641.785] (II) UnloadModule: "evdev"
[643641.785] (II) Unloading evdev
[643641.785] (EE) Failed to load module "evdev" (module requirement mismatch, 0)
[643641.785] (EE) No input driver matching `evdev'
</code>

<p>Причём, не спасает штатная команда</p>
<code lang="bash">
emerge @x11-module-rebuild
</code>

<p>На одном из форумов Gentoo, нашёл действенный способ, который получает список Xorg модулей из qlist, таким образом пересобираются <strong>ВСЕ</strong> модули. Записал, чтобы не искать:</p>
<code lang="bash">
emerge -1 $(qlist -IC x11-drivers)
</code>]]></content:encoded>
	<pubDate>Sun, 07 Apr 2013 04:00:00 +0400</pubDate>
	
	<category><![CDATA[How-to]]></category>	<comments>https://bagrintsev.me/blog/xorg-modules-rebuild-on-gentoo</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/xorg-modules-rebuild-on-gentoo</guid>
</item>
<item>
	<title>Настройка Eclipse для работы с cmake проектами</title>
	<link>https://bagrintsev.me/blog/setting-eclipse-for-working-with-cmake-projects/</link>
	<description>В отличии от NetBeans, где достаточно всего лишь создать проект из существующего Makefile, Eclipse требует некоторой настройки. В этой статье я подробно разберу настройку отладчика и компилятора.Предположим, что у вас есть такой, вполне обычный CMakeLists.txt.</description>
	<content:encoded><![CDATA[[<p>В отличии от NetBeans, где достаточно всего лишь создать проект из существующего Makefile, Eclipse требует некоторой настройки. 
В этой статье я подробно разберу настройку отладчика и компилятора.</p>

<p>Предположим, что у вас есть такой, вполне обычный CMakeLists.txt.</p>
<!--more-->
<code autoFormat="false" lang="cmake">
project(weathercollector)

cmake_minimum_required(VERSION 2.8)

include (CMakeUserFindMySQL)

include_directories ("${PROJECT_BINARY_DIR}")
include_directories ("${MYSQL_INCLUDE_DIR}") 
include_directories ("${PROJECT_SOURCE_DIR}/re2")
include_directories ("${PROJECT_SOURCE_DIR}/rudeconfig/src")
include_directories ("${PROJECT_SOURCE_DIR}/headers")
link_directories ("${PROJECT_SOURCE_DIR}/re2/obj")
link_directories ("${PROJECT_SOURCE_DIR}/rudeconfig/.libs")

file (COPY ${PROJECT_SOURCE_DIR}/settings.conf DESTINATION ${PROJECT_BINARY_DIR})
file (COPY ${PROJECT_SOURCE_DIR}/weathercollector.rc DESTINATION ${PROJECT_BINARY_DIR})

find_package (Threads)

FILE(GLOB_RECURSE SRCS "${PROJECT_SOURCE_DIR}/src/*.cpp")
ADD_EXECUTABLE(weathercollector ${SRCS})

target_link_libraries (weathercollector ${MYSQL_LIBRARIES})
target_link_libraries (weathercollector re2)
target_link_libraries (weathercollector stdc  )
target_link_libraries (weathercollector m)
target_link_libraries (weathercollector rudeconfig)
target_link_libraries (weathercollector ${CMAKE_THREAD_LIBS_INIT})
</code>

<p>Теперь давайте создадим проект Eclipse. Нажимайте File > New > Project. В появившимся мастере выбирайте C++ Project. Далее как обычно: вводите название, выбирайте Toolchain.</p>

<a target="_blank" href="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358863479.png"><img src="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358863479_small.jpeg" /></a>

<p>Теперь откройте окно Make Target, проследуя Window > Show View > Make Target. Оно появится справа от главного окна. Выберете в этом окне корневую директорию для CMake, именно она станет его рабочей директорией.</p>

<a target="_blank" href="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358865055.png"><img src="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358865055_small.jpeg" /></a>

<p>Теперь:</p>
<ul> 
<li>кликайте правой кнопкой мыши по выбранной папке и в контекстном меню нажимайте "New...".</li> 
<li>В появившемся диалоге, уберите две галочки "Same as the target name" и "Use builder settings".</li>
</ul>

<p>Затем заполните форму:</p>

<ul>
<li>Target Name: Cmake Release</li>
<li>Make Target: (оставить пустым)</li>
<li>Build command:
<code autoFormat="false" lang="bash">
cmake -E chdir Release/ cmake -G "Unix Makefiles" ../ -DCMAKE_BUILD_TYPE:STRING=Release
</code></li>
<li>Жмём Ок.</li>
</ul>

<a target="_blank" href="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358865888.png"><img src="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358865888_small.jpeg" /></a>

<p>Тоже самое нужно сделать для цели Debug. Target Name, естественно будет Cmake Debug, а Build command:</p>

<code lang="bash" autoFormat="false">
cmake -E chdir Debug/ cmake -G "Unix Makefiles" ../ -DCMAKE_BUILD_TYPE:STRING=Debug
</code>

<p>Как вы уже наверняка поняли, в директории проекта необходимо создать директории, в которых будут собираться цели:</p>

<code lang="bash">
mkdir Release Debug
</code>

<p>Теперь кликните правой кнопкой мыши по созданной цели и нажмите Build Target. Eclipse зайдёт в рабочую директорию и выполнит там команду "cmake ../". Естественно это действие нужно будет повторять после каждой правки CMakeLists.txt</p>

<p>Теперь необходимо настроить, собственно сам Builder.</p>

<ul>
<li>В левом меню найдите свой проект</li>
<li>Вызовите контекстное меню правым щелчком мыши и нажмите Properties</li>
<li>В появившемся окне выберите слева в списке, пункт "C/C++ Build"</li>
<li>В верхнем выпадающем меню, выберете конфигурацию "Release" (если такой нет, создайте в этом же окошке)</li>
<li>Снимите галочки "Use default build command" и "Generate make files automatically"</li>
</ul>

<p>В активизировавшемся поле ввода "Build command", укажите:</p>

<code autoFormat="false" lang="cmake">
make -C ${ConfigName}
</code>

</li>
<li>
В поле "Build directory" напишите: <strong>${PROJECT_LOC}</strong>
</li>
</ul>
<a target="_blank" href="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358869509.png"><img src="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358869509_small.jpeg" /></a>

<p>Переходим на вкладку Behaviour. Там всё должно быть вот так:</p>

<a target="_blank" href="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358866886.png"><img src="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358866886_small.jpeg" /></a>

<p>Тоже самое следует повторить и для конфигурации Debug, с той лишь разницей, что в поле "Build command" я обычно указываю опцию VERBOSE=1, чтобы получать подробный лог компиляции. Поле у меня при этом выглядит вот так:</p>

<code autoFormat="false" lang="cmake">
make -C ${ConfigName} VERBOSE=1
</code>

<p>Стоит заметить, что после каждого изменения файла CMakeLists.txt необходимо обновить цель. Для этого нужно щёлкнуть на ней правой кнопкой мыши и в контекстном меню нажать "Rebuild Last Target".</p>

<h2>Компиляция и дебагинг</h2>

<p>Как выяснилось, просто иметь цели компиляции не достаточно. Нужно ещё настроить соответствующие кнопки на верхней панели. Начнём с самого интересного - c Debug`а.</p>

<ul>
<li>Найдите на верхней панели иконку с маленьким зеленоватым жучком и нажмите на стрелку вниз рядом с ним.</li>
<li>В выпадающем меню выберете "Debug Configurations"</li>
<li>В появившемся окне, в списке слева выберете пункт "C/C++ Application" и кликните по нему правой кнопкой мыши.</li>
<li>Далее "New" и это создаст вам новый профиль отладки для текущего приложения в проекте.</li>
</ul>

<a target="_blank" href="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358871228.png"><img src="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358871228_small.jpeg" /></a>

<p>Далее нажимайте кнопку "Browse", рядом с полем Project и выбирайте проект, с которым будете работать.
После этого нажимает "Search Project" и там вы должны увидеть исполняемый файл, который получается после компиляции. Выбирайте его.</p>

<p>Стоит отметить, что бывали случаи, когда путь на выходной бинарник, в поле C/C++ Application по умолчанию указывал куда-то в CMakeFiles. Забирать его от туда не очень удобно, поэтому не стесняйтесь указывать что-то вроде "Debug/weathercollector" :-)</p>

<p>Теперь опять находим в левом фрейме Project Explorer свой проект, кликаем по нему правой кнопкой мыши, в выпавшем меню находим пункт "Debug as" и выбираем только что созданный профиль дебагинга.</p>

<p>В верхнем меню, нажмите кнопку с иконкой молоточка, в выпадающем меню которого можно найти созданные ранее профили Debug и Release.</p>

<p>Всё, теперь можно нажимать на иконку с зелёным жучком и пользоваться всеми прелестями отладчика Eclipse.</p>

<a target="_blank" href="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358871475.png"><img src="/content/postImages/setting-eclipse-for-working-with-cmake-projects/1358871475_small.jpeg" /></a>

<p>Следуя тому же принципу, нужно создать и назначить профили для кнопок Run и Build.</p>]]></content:encoded>
	<pubDate>Tue, 22 Jan 2013 04:00:00 +0400</pubDate>
	
	<category><![CDATA[How-to]]></category>	<comments>https://bagrintsev.me/blog/setting-eclipse-for-working-with-cmake-projects</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/setting-eclipse-for-working-with-cmake-projects</guid>
</item>
<item>
	<title>Gigolo: ассоциации файлов</title>
	<link>https://bagrintsev.me/blog/gigolo-file-associations/</link>
	<description>Gigolo - это графический и консольный интерфейс для подключения к локальным и удалённым файловым системам, использующий GIO/GVfs. С его помощью вы можете быстро и просто подсоединить или смонтировать практически любую файловую систему, если её поддержка есть в вашей системе. Для частого использования предусмотрены закладки.Бывает так, что из коробки Gigolo отказывается открывать смонтированные директории. Лечится это правкой файла defaults.list.</description>
	<content:encoded><![CDATA[[<p>Gigolo - это графический и консольный интерфейс для подключения к локальным и удалённым файловым системам, использующий GIO/GVfs. С его помощью вы можете быстро и просто подсоединить или смонтировать практически любую файловую систему, если её поддержка есть в вашей системе. Для частого использования предусмотрены закладки.</p>

<p>Бывает так, что из коробки Gigolo отказывается открывать смонтированные директории. Лечится это правкой файла <strong>defaults.list</strong>.</p>
<!--more-->
<code lang="bash">
$ locate defaults.list
/home/sb0y/.local/share/applications/defaults.list
/usr/portage/gnome-base/gnome-session/files/defaults.list
</code>

<p>В принципе по содержимому файла уже понятно что и к чему. На всякий случай привожу свой файл полностью.</p>

<code lang="bash">
application/illustrator=gimp.desktop
application/pdf=evince.desktop;gimp.desktop
application/rss xml=chromium-chromium.desktop;mozilla-firefox.desktop
application/rtf=writer.desktop
application/vnd.mozilla.xul xml=chromium-chromium.desktop;mozilla-firefox.desktop
application/vnd.oasis.opendocument.spreadsheet=calc.desktop
application/vnd.oasis.opendocument.text=writer.desktop
application/x-font-ttx=chromium-chromium.desktop;mozilla-firefox.desktop
application/x-ufraw=chromium-chromium.desktop;mozilla-firefox.desktop
application/xhtml xml=chromium-chromium.desktop;mozilla-firefox.desktop
application/xml-external-parsed-entity=chromium-chromium.desktop;mozilla-firefox.desktop
application/xml=chromium-chromium.desktop;mozilla-firefox.desktop
application/xsd=chromium-chromium.desktop;mozilla-firefox.desktop
application/xslt xml=chromium-chromium.desktop;mozilla-firefox.desktop
audio/mp4=audacious2-gtkui.desktop
audio/mpeg=audacious2-gtkui.desktop
audio/x-flac=audacious2-gtkui.desktop
audio/x-ms-wma=audacious2-gtkui.desktop
audio/x-wav=audacious2-gtkui.desktop
image/bmp=gqview.desktop;gimp.desktop
image/gif=gqview.desktop;gimp.desktop
image/jpeg=gqview.desktop;gimp.desktop
image/jpg=gqview.desktop;gimp.desktop
image/png=gqview.desktop;gimp.desktop
image/svg xml-compressed=gimp.desktop;gqview.desktop
image/svg xml=gqview.desktop;gimp.desktop
image/tiff=gqview.desktop;gimp.desktop
image/vnd.microsoft.icon=gqview.desktop;gimp.desktop
image/vnd.wap.wbmp=gqview.desktop;gimp.desktop
image/x-gray=gqview.desktop;gimp.desktop
image/x-pcx=gqview.desktop;gimp.desktop
image/x-png=gqview.desktop;gimp.desktop
image/x-portable-anymap=gqview.desktop;gimp.desktop
image/x-portable-bitmap=gqview.desktop;gimp.desktop
image/x-portable-graymap=gqview.desktop;gimp.desktop
image/x-portable-pixmap=gqview.desktop;gimp.desktop
image/x-tga=gqview.desktop;gimp.desktop
image/x-xbitmap=gqview.desktop;gimp.desktop
image/x-xpixmap=gqview.desktop;gimp.desktop
text/html=chromium-chromium.desktop;mozilla-firefox.desktop
text/plain=mousepad.desktop
video/x-msvideo=gnome-mplayer.desktop

# strings below was added for fix

x-directory/gnome-default-handler=Thunar.desktop
inode/directory=Thunar.desktop
x-directory/normal=Thunar.desktop
</code>

<p>В моём конфиге почему-то не оказалось строк</p>

<code lang="bash">
x-directory/gnome-default-handler=Thunar.desktop
inode/directory=Thunar.desktop
x-directory/normal=Thunar.desktop
</code>

<p>Из-за этого Gigolo открывал директории не через Thunar или Nautilus, а как ни странно через аудио плеер Audacious :)</p>

<p>При написании использовалась <a href="http://www.uvena.de/gigolo/help.html" target="_blank">Gigolo Help</a>.</p>

<p><strong>UPDATE</strong></p>
<p>Так же можно в графическом интерфейсе Gigolo открыть Edit -> Preferences и в вкладке General, в качестве File manager ввести, например Thunar.<p>]]></content:encoded>
	<pubDate>Sat, 05 Jan 2013 04:00:00 +0400</pubDate>
	
	<category><![CDATA[How-to]]></category>	<comments>https://bagrintsev.me/blog/gigolo-file-associations</comments>
	<guid isPermaLink="false">https://bagrintsev.me/blog/gigolo-file-associations</guid>
</item>

</channel></rss>
