Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«QNX/UNIX: Анатомия ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌΠ°Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 16

Автор ОлСг Π¦ΠΈΠ»ΡŽΡ€ΠΈΠΊ

Особая ΠΎΠ±Π»Π°ΡΡ‚ΡŒ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ собствСнныС Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΌΠΎΠ³ΡƒΡ‚ Π½Π°ΠΉΡ‚ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈ Π³Π΄Π΅ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ (стСковыС) ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Ρ‹, β€” это асинхронноС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π° ΠΊΠΎΠ΄Π° Π² контСкстС ΠΏΠΎΡ‚ΠΎΠΊΠ°, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ сигнала.

Π•Ρ‰Π΅ ΠΎΠ΄Π½ΠΎ совсСм Π½Π΅ ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ собствСнных Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ° (ΠΌΡ‹ Π½Π΅ встрСчали Π² Π»ΠΈΡ‚Π΅Ρ€Π°Ρ‚ΡƒΡ€Π΅ ΡƒΠΏΠΎΠΌΠΈΠ½Π°Π½ΠΈΠΉ ΠΎ Π½Π΅ΠΌ), ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ особо ΠΎΡ€Π³Π°Π½ΠΈΡ‡Π½ΠΎ вписываСтся Π² использованиС ΠΈΠΌΠ΅Π½Π½ΠΎ Π‘++, β€” это Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ способ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° Π² Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ…. ΠŸΡ€ΠΈ этом Π½Π΅Π²Π°ΠΆΠ½ΠΎ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ - ΠΊΠ°ΠΊ присоСдинСнныС ΠΈΠ»ΠΈ ΠΊΠ°ΠΊ отсоСдинСнныС (ΠΌΡ‹ обсуТдали это Ρ€Π°Π½Π΅Π΅); Ρ‚Π°ΠΊΠΎΠ΅ использованиС Π² Π·Π°ΠΌΠ΅Ρ‚Π½ΠΎΠΉ ΠΌΠ΅Ρ€Π΅ Π½ΠΈΠ²Π΅Π»ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΡ… Ρ€Π°Π·Π½ΠΈΡ†Ρƒ. Π­Ρ‚Π° Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ° состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ:

β€’ Π•сли ΠΏΡ€ΠΈ создании ΠΊΠ»ΡŽΡ‡Π° Π½Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ дСструктор экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ° pthread_key_create(..., NULL), Ρ‚ΠΎ ΠΏΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π½Π°Π΄ экзСмпляром Π΅Π³ΠΎ Π΄Π°Π½Π½Ρ‹Ρ… Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ дСструктивныС дСйствия ΠΈ созданныС ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ экзСмпляры Π΄Π°Π½Π½Ρ‹Ρ… Π±ΡƒΠ΄ΡƒΡ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ послС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ².

β€’ Π•сли ΠΊ этим экзСмплярам Π΄Π°Π½Π½Ρ‹Ρ… созданы Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ доступа (Π° ΠΎΠ½ΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π² любом случаС созданы, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ области этих Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΌ ΠΈΡ‚ΠΎΠ³Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ), Ρ‚ΠΎ благодаря этому доступу ΠΏΠΎΡ€ΠΎΠΆΠ΄Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊΠΈ ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅, Β«ΠΎΡΡ‚Π°Π²ΡˆΠΈΠ΅ΡΡΒ» ΠΊΠ°ΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ².

Π’ ΠΊΠΎΠ΄Π΅ (Ρ‡Ρ‚ΠΎ Π³ΠΎΡ€Π°Π·Π΄ΠΎ нагляднСС) это ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ Ρ‚Π°ΠΊ (ΠΊΠΎΠ΄ с Π·Π°ΠΌΠ΅Ρ‚Π½Ρ‹ΠΌΠΈ упрощСниями взят ΠΈΠ· Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°):

// описаниС экзСмпляра Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°

struct throwndata {

 ...

};


static pthread_once_t once = PTHREAD_ONCE_INIT;

static pthread_key_t key;

void createkey(void) { pthread_key_create(&key, NULL); }


// STL-ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ Π½Π° экзСмпляры Π΄Π°Π½Π½Ρ‹Ρ…

queue<throwndata*> result;


// функция ΠΏΠΎΡ‚ΠΎΠΊΠ°

void* GetBlock(void*) {

 pthread_once(&once, createkey);

 throwndata *td;

 if ((td = (throwndata*)pthread_getspecific(key)) == NULL) {

  td = new throwndata();

  pthread_setspecific(key, (void*)td);

  // Π²ΠΎΡ‚ ΠΎΠ½ - Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΉ ΠΏΡƒΡ‚ΡŒ доступа:

  result.push(td);

 }

 // Π΄Π°Π»Π΅Π΅ ΠΈΠ΄Π΅Ρ‚ плодотворная Ρ€Π°Π±ΠΎΡ‚Π° Π½Π°Π΄ Π±Π»ΠΎΠΊΠΎΠΌ Π΄Π°Π½Π½Ρ‹Ρ… *td

 // . . . . . . . . .

}


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

 // . . . . . .

 for (int i = 0; i < N; i++)

  pthread_create(NULL, NULL, GetBlock, NULL);

 // . . . . . . ΠΊ этому Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΈΡΡŒ;

 // Π½ΠΈ Π² ΠΊΠΎΠ΅ΠΌ случаС нСльзя ΠΏΠΎΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ result.size()

 // нСпосрСдствСнно Π² ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Ρ†ΠΈΠΊΠ»Π°!

 int n = result.size();

 for (int i = 0; i < n; i++) {

  throwndata *d = result.front();

  // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ° *d ...

  result pop();

  delete d;

 }

 return EXIT_SUCCESS;

}

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

Π’ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… ΠΊΠΎΠ΄Π° ΠΌΡ‹ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π»ΠΈ Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ pthread_create() Π² Π²ΠΈΠ΄Π΅ &GetBlock (адрСса Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ°), Π½ΠΎ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ ΡΠΎΠ·Π½Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ записали GetBlock. И Ρ‚ΠΎ ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠ΅ Π²Π΅Ρ€Π½ΠΎ, ΠΈΠ±ΠΎ компилятор достаточно ΡƒΠΌΠ΅Π½, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈ ΡƒΠΊΠ°Π·Π°Π½ΠΈΠΈ ΠΈΠΌΠ΅Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Π·ΡΡ‚ΡŒ Π΅Π΅ адрСс.

БобствСнныС Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² β€” это Π½Π°ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ Π³ΠΈΠ±ΠΊΠΈΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ‚Π°ΠΈΡ‚ΡŒ Π² сСбС ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅, Π΅Ρ‰Π΅ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Ρ‚Π΅Ρ…Π½ΠΈΠΊΠΈ примСнСния.

Π‘Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² Π² ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ срСдС

РассмотрСв Β«Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΏΡ€ΠΈΠ±Π»ΠΈΠΆΠ΅Π½ΠΈΠΈΒ» Ρ‚Π΅Ρ…Π½ΠΈΠΊΡƒ собствСнных Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΌΡ‹ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ ΠΎΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ Π½Π° вопрос: Β«Π’ Ρ‡Π΅ΠΌ ΠΆΠ΅ Π³Π»Π°Π²Π½ΠΎΠ΅ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚Π°ΠΊΠΎΠΉ Π² ΠΎΠ±Ρ‰Π΅ΠΌ-Ρ‚ΠΎ достаточно Π³Ρ€ΠΎΠΌΠΎΠ·Π΄ΠΊΠΎΠΉ Ρ‚Π΅Ρ…Π½ΠΈΠΊΠΈ? И Π·Π°Ρ‡Π΅ΠΌ для Π΅Π΅ ввСдСния ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ Ρ€Π°ΡΡˆΠΈΡ€ΡΡ‚ΡŒ стандарты POSIX?Β» Π‘Π°ΠΌΠΎΠ΅ прямоС Π΅Π΅ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΏΠΎΠΌΠΈΠΌΠΎ Π΄Ρ€ΡƒΠ³ΠΈΡ… Β«ΠΏΠΎΠΏΡƒΡ‚Π½Ρ‹Ρ…Β» ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±Ρ‹Π»ΠΈ обсуТдСны Ρ€Π°Π½Π΅Π΅, β€” это ΠΎΠ±Ρ‰ΠΈΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ прСвращСния ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для ΠΎΠ΄Π½ΠΎΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠ³ΠΎ исполнСния Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡƒΡŽ (thread safe) Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΌ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠΈ. Π­Ρ‚ΠΎΡ‚ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ Π΅Π΄ΠΈΠ½ΡƒΡŽ (Π² смыслС Β«Π΅Π΄ΠΈΠ½ΠΎΠΎΠ±Ρ€Π°Π·Π½ΡƒΡŽΒ», Π° Π½Π΅ «СдинствСнно Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡƒΡŽΒ») Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΡŽ для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹Ρ… ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

ОБ QNX, Π·Π°ΠΈΠΌΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ инструмСнтарий GNU-Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ (gcc, make, …), прСдусматриваСт Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ построСния ΠΊΠ°ΠΊ статичСски связываСмых Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ (ΠΈΠΌΠ΅Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ² Π²ΠΈΠ΄Π° xxx.a), Ρ‚Π°ΠΊ ΠΈ раздСляСмых ΠΈΠ»ΠΈ динамичСски связываСмых (ΠΈΠΌΠ΅Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ² Π²ΠΈΠ΄Π° xxx.so). Π¦Π΅Π»Π΅ΡΠΎΠΎΠ±Ρ€Π°Π·Π½ΠΎΡΡ‚ΡŒ послСдних ΠΏΡ€ΠΈ построСнии Π°Π²Ρ‚ΠΎΠ½ΠΎΠΌΠ½Ρ‹Ρ… ΠΈ встраиваСмых систСм (Π½Π° Ρ‡Ρ‚ΠΎ Π³Π»Π°Π²Π½Ρ‹ΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΈ Π½Π°Ρ†Π΅Π»Π΅Π½Π° ОБ QNX) достаточно ΡΠΎΠΌΠ½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°. Однако высказанноС Π²Ρ‹ΡˆΠ΅ ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΎ построСнии Ρ€Π΅Π΅Π½Ρ‚Π΅Ρ€Π°Π±Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Ρ… Π΅Π΄ΠΈΠ½ΠΈΡ† относится Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹ΠΌ модулям (ΠΊΠ°ΠΊ статичСским, Ρ‚Π°ΠΊ ΠΈ динамичСским) Π² Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΠΎΠΌ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠΈ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π° Β«Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Β», Π½ΠΎ ΠΈ ΠΎΡ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΊΡƒΠ΄Π° Π±ΠΎΠ»Π΅Π΅ ΡˆΠΈΡ€ΠΎΠΊΠΈΠΉ спСктр Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² ΠΈ Π² Ρ‚ΠΎΠΉ ΠΆΠ΅ ΠΌΠ΅Ρ€Π΅ относится ΠΈ просто ΠΊ Π»ΡŽΠ±Ρ‹ΠΌ Π½Π°Π±ΠΎΡ€Π°ΠΌ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Π½Ρ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹Ρ… ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ (Π²ΠΈΠ΄Π° xxx.ΠΎ), Ρ€Π°Π·Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌΡ‹Ρ… Π² Ρ…ΠΎΠ΄Π΅ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠΎΠ΄ Ρ†Π΅Π»Π΅Π²ΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚.

Если ΠΌΡ‹ обратимся ΠΊ тСхничСской Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ API QNX (аналогичная ΠΊΠ°Ρ€Ρ‚ΠΈΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΈ Π² API любого UNIX), Ρ‚ΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ нСбольшая Ρ‡Π°ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΎΡ‚ΠΌΠ΅Ρ‡Π΅Π½Π° ΠΊΠ°ΠΊ thread safe. К «нСбСзопасным» отнСсСны Ρ‚Π°ΠΊΠΈΠ΅ общСизвСстныС Π²Ρ‹Π·ΠΎΠ²Ρ‹, ΠΊΠ°ΠΊ select(), rand() ΠΈ readln(), Π° ΠΌΠ½ΠΎΠ³ΠΈΠΌ «нСбСзопасным» Π² ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ срСдС Π²Ρ‹Π·ΠΎΠ²Π°ΠΌ ΡΠΎΠΏΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ ΠΈΡ… бСзопасныС Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚Ρ‹ с суффиксом *_r Π² написании ΠΈΠΌΠ΅Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ MsgSend() β€” MsgSend_r().

Π’ Ρ‡Π΅ΠΌ ΠΆΠ΅ состоит Π½Π΅Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ Π² ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ срСдС? Π’ Π½Π΅Ρ€Π΅Π΅Π½Ρ‚Π΅Ρ€Π°Π±Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²Π»Π΅Π½Π½Ρ‹Ρ… для выполнСния Π² ΠΎΠ΄Π½ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, Π² ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ связанной с ΠΏΠΎΡ‚Ρ€Π΅Π±Π½ΠΎΡΡ‚ΡŒΡŽ Π² статичСских Π΄Π°Π½Π½Ρ‹Ρ…, хранящих Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ. Рассмотрим ΠΊΠ»Π°ΡΡΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ rand(), Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌΡƒΡŽ Π² самых Ρ€Π°Π·Π½ΠΎΠΎΠ±Ρ€Π°Π·Π½Ρ‹Ρ… ОБ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊ (ΠΏΡ€ΠΈ Β«ΡƒΠ΄Π°Ρ‡Π½ΠΎΠΌΒ» Π²Ρ‹Π±ΠΎΡ€Π΅ констант А, Π’, Π‘):

int rand(void) {

 static int x = rand_init();

 return x = (A*x + B)%C;

}

Вакая рСализация, ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ коррСктная Π² ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠΉ (ΠΎΠ΄Π½ΠΎΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ) ΠΌΠΎΠ΄Π΅Π»ΠΈ, становится нСбСзопасной Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ: Π°) вычислСниС x ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ событиСм диспСтчСризации, ΠΈ Π½Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΎ, Ρ‡Ρ‚ΠΎ вновь ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ²ΡˆΠΈΠΉ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊ Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ обратится ΠΊ rand() ΠΈ исказит Ρ…ΠΎΠ΄ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ вычислСния; Π±) ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Β«Ρ…ΠΎΡ‚Π΅Π» Π±Ρ‹Β» ΠΈΠΌΠ΅Ρ‚ΡŒ свою Π°Π²Ρ‚ΠΎΠ½ΠΎΠΌΠ½ΡƒΡŽ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ вычислСний x, Π½Π΅ Π·Π°Π²ΠΈΡΡΡ‰ΡƒΡŽ ΠΎΡ‚ повСдСния ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². Π–Π΅Π»Π°Π΅ΠΌΡ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ достигнут, Ссли ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ свой Π°Π²Ρ‚ΠΎΠ½ΠΎΠΌΠ½Ρ‹ΠΉ экзСмпляр ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ x, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ двумя путями:

1. Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ объявлСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

int rand_r(int *x) {

 return x = (А * (*x) + Π’) % Π‘;

};

ΠŸΡ€ΠΈ этом ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° «клонирования» ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ x Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΈΠ· ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² (Π΄Π° ΠΈ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ Π΅Π΅ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ) Π½Π΅ снимаСтся, ΠΎΠ½Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрСносится Π½Π° ΠΏΠ»Π΅Ρ‡ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, Ρ‡Ρ‚ΠΎ, ΠΎΠ΄Π½Π°ΠΊΠΎ, достаточно просто Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ ΠΏΡ€ΠΈ создании ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π·Π° счСт Π΅Π΅ стСка Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…:

void* thrfunc(void*) {

 int x = rand_init();

 ... = rand_r(&x);

};

ИмСнно Ρ‚Π°ΠΊΠΎΠ²Π° Ρ„ΠΎΡ€ΠΌΠ° ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ эквивалСнта Π² API QNX β€” rand_r().

2. Π’ этом Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π΅ ΠΌΡ‹ сохраняСм ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ описания Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π±Π΅Π· ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π·Π° счСт использования Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… экзСмпляров собствСнных Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°. (Π’Π΅ΡΡŒ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΉ Π½ΠΈΠΆΠ΅ ΠΊΠΎΠ΄ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅ компиляции; всС ΠΈΠΌΠ΅Π½Π°, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ rand(), Π½Π΅Π²ΠΈΠ΄ΠΈΠΌΡ‹ ΠΈ нСдоступны ΠΈΠ· Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ‹Π·ΠΎΠ²Π°, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ΄Ρ‡Π΅Ρ€ΠΊΠ½ΡƒΡ‚ΠΎ явным использованиСм ΠΊΠ²Π°Π»ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° static.)

static pthread_key_t key;

static pthread_once_t once = PTHREAD_ONCE_INIT;

static void destr(void* db) { delete x; }

static void once_creator(void) { pthread_key_create(&key, destr); }


int rand(void) {

 pthread_once(&once, once_creator);

 int *x = pthread_getspecific(key);

 if (x == NULL) {

  pthread_setspecific(key, x = new int);

  *x = rand_init();

 }

 return x = (A * (*x) + B) % C;

}

Π’ этом Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π΅, Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ, вСсь ΠΊΠΎΠ΄ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅Π³ΠΎ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π° ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π΅ ΠΊ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ остаСтся Ρ‚Π΅ΠΊΡΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½Ρ‹ΠΌ:

void* thrfunc(void*) {

 // ...

 while (true) {

  ... = rand(x);

 }

}

ΠŸΠ΅Ρ€Π΅Π²ΠΎΠ΄ всСго ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π½Π° использованиС ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ срСды состоит Π² Π·Π°ΠΌΠ΅Π½Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΉ Π΅Π΄ΠΈΠ½ΠΈΡ†Ρ‹ (ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°, Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ), содСрТащСй Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ rand(), ΠΈ Π½ΠΎΠ²ΠΎΠΉ сборкС прилоТСния с этой ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΉ Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅ΠΉ.

ΠŸΡ€ΠΈ Ρ‚Π°ΠΊΠΎΠΌ способС ΠΈΠ·ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ ΠΏΠΎΠ΄ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΡƒΡŽ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ ΠΈ стандартныС общСизвСстныС Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ API, написанныС Π² своСм ΠΏΠ΅Ρ€Π²ΠΎΠ·Π΄Π°Π½Π½ΠΎΠΌ Π²ΠΈΠ΄Π΅ 25 Π»Π΅Ρ‚ назад… (ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅, Ρ‚Π°ΠΊ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ это Π΄Π΅Π»Π°Ρ‚ΡŒ стандарт POSIX, вводящий Π² ΠΎΠ±ΠΈΡ…ΠΎΠ΄ собствСнныС Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²).

ДиспСтчСризация ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²

ΠšΠ°ΠΆΠ΄ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ, ΡƒΡ‡Π°ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΌΡƒ Π² процСссС диспСтчСризации, соотвСтствуСт экзСмпляр структуры, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΉ Π² Ρ„Π°ΠΉΠ»Π΅ <sys/target_nto.h>, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ находятся всС Ρ„ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ для ОБ QNX опрСдСлСния: