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

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ для Linux. ΠŸΡ€ΠΎΡ„Π΅ΡΡΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 46

Автор ΠœΠ°Ρ€ΠΊ ΠœΠΈΡ‚Ρ‡Π΅Π»Π»

  mmap(NULL, alloc_size, PROT_WRITE, MAP_PRIVATE, fd, 0);

 close(fd);

 /* Π—Π°ΠΏΠΈΡΡŒ Π½Π° страницу для получСния Π΅Π΅ ΠΊΠΎΠΏΠΈΠΈ Π² частноС

    использованиС. */

 memory[0] = 0;

 /* Π—Π°ΠΏΡ€Π΅Ρ‚ Π½Π° запись Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ. */

 mprotect(memory, alloc_size, PROT_NONE);


 /* ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° записи Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ. */

 memory[0] = 1;


 /* Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ памяти. */

 printf("all done\n");

 munmap(memory, alloc_size);

 return 0;

}

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΏΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ схСмС.

1. Π—адаСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигнала SIGSEGV.

2. Π€Π°ΠΉΠ» /dev/zero отобраТаСтся Π² памяти, ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ выдСляСтся ΠΎΠ΄Π½Π° страница. Π’ эту страницу записываСтся ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, благодаря Ρ‡Π΅ΠΌΡƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ прСдоставляСтся частная копия страницы.

3. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π·Π°Ρ‰ΠΈΡ‰Π°Π΅Ρ‚ ΠΏΠ°ΠΌΡΡ‚ΡŒ, вызывая Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ mprotect() с Ρ„Π»Π°Π³ΠΎΠΌ PROT_NONE.

4. ΠšΠΎΠ³Π΄Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° впослСдствии обращаСтся ΠΊ памяти, Linux посылаСт Π΅ΠΉ сигнал SIGSEGV, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ обрабатываСтся Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ segv_handler(). ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигнала отмСняСт Π·Π°Ρ‰ΠΈΡ‚Ρƒ памяти, Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Ρ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ записи.

5. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° удаляСт ΠΎΠ±Π»Π°ΡΡ‚ΡŒ ΠΏΠ°ΠΌΡΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ munmap().

8.10. Ѐункция nanosleep(): высокоточная ΠΏΠ°ΡƒΠ·Π°

Ѐункция nanosleep() являСтся Π±ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΡ‡Π½ΠΎΠΉ вСрсиСй стандартной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sleep(), принимая ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° структуру Ρ‚ΠΈΠΏΠ° timespec, Π³Π΄Π΅ врСмя задаСтся с Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ Π΄ΠΎ наносСкунды, Π° Π½Π΅ сСкунды. ΠŸΡ€Π°Π²Π΄Π°, особСнности Ρ€Π°Π±ΠΎΡ‚Ρ‹ ОБ Linux Ρ‚Π°ΠΊΠΎΠ²Ρ‹, Ρ‡Ρ‚ΠΎ Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ оказываСтся Ρ€Π°Π²Π½ΠΎΠΉ 10 мс, Π½ΠΎ это всС Ρ€Π°Π²Π½ΠΎ Π²Ρ‹ΡˆΠ΅, Ρ‡Π΅ΠΌ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sleep(). Π€ΡƒΠ½ΠΊΡ†ΠΈΡŽ nanosleep() ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² прилоТСниях, Π³Π΄Π΅ трСбуСтся Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΌΠΈ ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Π°ΠΌΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ.

Π’ структурС timespec ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ Π΄Π²Π° поля:

β–  tv_sСс β€” Ρ†Π΅Π»ΠΎΠ΅ число сСкунд;

β–  tv_nsec β€” Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ число миллисСкунд (Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ мСньшС, Ρ‡Π΅ΠΌ 109).

Π Π°Π±ΠΎΡ‚Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ nanosleep(), ΠΊΠ°ΠΊ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sleep(), прСрываСтся ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ сигнала. ΠŸΡ€ΠΈ этом функция Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ -1, Π° Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ errno записываСтся ΠΊΠΎΠ΄ EINTR. Но Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ nanosleep() Π΅ΡΡ‚ΡŒ Π²Π°ΠΆΠ½ΠΎΠ΅ прСимущСство. Она ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ β€” Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° структуру timespec, Π² ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ (Ссли ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π΅ Ρ€Π°Π²Π΅Π½ NULL) заносится Π²Π΅Π»ΠΈΡ‡ΠΈΠ½Π° ΠΎΡΡ‚Π°Π²ΡˆΠ΅Π³ΠΎΡΡ ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Π° Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ (Ρ‚.Π΅. Ρ€Π°Π·Π½ΠΈΡ†Π° ΠΌΠ΅ΠΆΠ΄Ρƒ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΡ‹ΠΌ ΠΈ ΠΏΡ€ΠΎΡˆΠ΅Π΄ΡˆΠΈΠΌ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΊΠ°ΠΌΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ). Благодаря этому ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ Π²ΠΎΠ·ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ ΠΏΡ€Π΅Ρ€Π²Π°Π½Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ оТидания.

Π’ листингС 8.8 ΠΏΠΎΠΊΠ°Π·Π°Π½Π° Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Π°Ρ рСализация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sleep(). Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ стандартного систСмного Π²Ρ‹Π·ΠΎΠ²Π° эта функция ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ Π΄Ρ€ΠΎΠ±Π½ΠΎΠ΅ число сСкунд ΠΈ Π²ΠΎΠ·ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ оТидания Π² случаС прСрывания ΠΏΠΎ сигналу.

Листинг 8.8. (better_sleep.c) Высокоточная рСализация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sleep()

#include <errno.h>

#include <time.h>


int better_sleep(double sleep_time) {

 struct timespec tv;

 /* Π—Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ структуры timespec Π½Π° основании ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ числа

    сСкунд. */

 tv.tv_sec = (time_t)sleep_time;

 /* Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π΅ΡƒΡ‡Ρ‚Π΅Π½Π½Ρ‹Ρ… Π²Ρ‹ΡˆΠ΅ наносСкунд. */

 tv.tv_nsec = (long)((sleep_time - tv.tv_sec) * 1e+9);


 while (1) {

  /* ΠŸΠ°ΡƒΠ·Π°, Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΡƒΠΊΠ°Π·Π°Π½Π° Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ tv.

     Π’ случаС прСрывания ΠΏΠΎ сигналу Π²Π΅Π»ΠΈΡ‡ΠΈΠ½Π° ΠΎΡΡ‚Π°Π²ΡˆΠ΅Π³ΠΎΡΡ

     ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΊΠ° Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ заносится ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ tv. */

  int rval = nanosleep(&tv, &tv);

  if (rval == 0)

   /* ΠΏΠ°ΡƒΠ·Π° ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π΅Π½Π°. */

   return 0;

  else if (errno == EINTR)

   /* ΠŸΡ€Π΅Ρ€Ρ‹Π²Π°Π½ΠΈΠ΅ ΠΏΠΎ сигналу. ΠŸΠΎΠ²Ρ‚ΠΎΡ€Π½Π°Ρ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ°. */

   continue;

  else

   /* Какая-Ρ‚ΠΎ другая ошибка. */

   return rval;

 }

 return 0;

}

8.11. Ѐункция readlink(): Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ символичСских ссылок

Ѐункция readlink() опрСдСляСт адрСсата символичСской ссылки. Она ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ‚Ρ€ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°: ΠΏΡƒΡ‚ΡŒ ΠΊ символичСской ссылкС, Π±ΡƒΡ„Π΅Ρ€ для записи адрСсата ΠΈ Π΄Π»ΠΈΠ½Π° Π±ΡƒΡ„Π΅Ρ€Π°. Как Π½ΠΈ странно, ΠΏΡƒΡ‚Π΅Π²ΠΎΠ΅ имя, ΠΏΠΎΠΌΠ΅Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π² Π±ΡƒΡ„Π΅Ρ€, Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌ символом. Но ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π΅ возвращаСтся Π΄Π»ΠΈΠ½Π° Π±ΡƒΡ„Π΅Ρ€Π°, Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ этот символ нСслоТно.

Если ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Π½Π΅ являСтся символичСской ссылкой, функция readlink() Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ -1, Π° Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ errno записываСтся константа EINVAL.

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°, прСдставлСнная Π² листингС 8.9, ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ адрСсата символичСской ссылки, Π·Π°Π΄Π°Π½Π½ΠΎΠΉ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строкС.

Листинг 8.9. (print-symlink.с) ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ адрСсата символичСской ссылки

#include Β«errno.h>

#include <stdio.h>

#include <unistd.h>


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

 char target_path[256];

 char* link_path = argv[1];


 /* ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° чтСния адрСсата символичСской ссылки. */

 int len =

  readlink(link_path, target_path, sizeof(target_path));


 if (len == -1) {

  /* Ѐункция Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ ошибкой. */

  if (errno == EINVAL)

   /* Π­Ρ‚ΠΎ Π½Π΅ символичСская ссылка. */

   fprintf(stderr, "%s is not a symbolic link\n", link_path);

  else

   /* ΠŸΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»Π° какая-Ρ‚ΠΎ другая ошибка. */

   perror("readlink");

  return 1;

 } else {

  /* Π—Π°Π²Π΅Ρ€ΡˆΠ°Π΅ΠΌ ΠΏΡƒΡ‚Π΅Π²ΠΎΠ΅ имя Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌ символом. */

  target_path[len] = '\0';

  /* Π’Ρ‹Π²ΠΎΠ΄ΠΈΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚. */

  printf("%s\n", target_path);

  return 0;

 }

}

НиТС ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ, ΠΊΠ°ΠΊ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΡΠΈΠΌΠ²ΠΎΠ»ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ссылку ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π΅Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ print-symlink:

% ln -s /usr/bin/wc my_link

% ./print-symlink my_link

/usr/bin/wc

8.12. Ѐункция sendfile(): быстрая ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π΄Π°Π½Π½Ρ‹Ρ…

Ѐункция sendfile() β€” это эффСктивный ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ копирования Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ дСскриптора Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ. ДСскрипторам ΠΌΠΎΠ³ΡƒΡ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ дисковыС Ρ„Π°ΠΉΠ»Ρ‹, сокСты ΠΈΠ»ΠΈ устройства.

ΠžΠ±Ρ‹Ρ‡Π½ΠΎ Ρ†ΠΈΠΊΠ» копирования рСализуСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° выдСляСт Π±ΡƒΡ„Π΅Ρ€ фиксированного Ρ€Π°Π·ΠΌΠ΅Ρ€Π°, ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Π΅Ρ‚ Π² Π½Π΅Π³ΠΎ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ· исходного дСскриптора, Π·Π°Ρ‚Π΅ΠΌ записываСт содСрТимоС Π±ΡƒΡ„Π΅Ρ€Π° Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ дСскриптор ΠΈ повторяСт ΠΎΠΏΠΈΡΠ°Π½Π½ΡƒΡŽ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ скопированы всС Π΄Π°Π½Π½Ρ‹Π΅. Вакая схСма нСэффСктивна ΠΊΠ°ΠΊ с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Ρ‚Π°ΠΊ ΠΈ с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Π·Π°Ρ‚Ρ€Π°Ρ‚ памяти, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ выдСляСтся Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π±ΡƒΡ„Π΅Ρ€ ΠΈ Π½Π°Π΄ Π΅Π³ΠΎ содСрТимым Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ копирования.

Ѐункция sendfile() устраняСт ΠΏΠΎΡ‚Ρ€Π΅Π±Π½ΠΎΡΡ‚ΡŒ Π² создании ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ Π±ΡƒΡ„Π΅Ρ€Π°. Π•ΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ дСскриптор для записи, дСскриптор для чтСния, ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ смСщСния ΠΈ число ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌΡ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…. ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ смСщСния опрСдСляСт ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°, с ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ начинаСтся ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ (0 β€” это Π½Π°Ρ‡Π°Π»ΠΎ Ρ„Π°ΠΉΠ»Π°). ПослС окончания копирования пСрСмСнная Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ смСщСниС ΠΊΠΎΠ½Ρ†Π° Π±Π»ΠΎΠΊΠ°. Ѐункция sendfile() объявлСна Π² Ρ„Π°ΠΉΠ»Π΅ <sys/sendfile.h>.

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°, показанная Π² листингС 8.10, прСдставляСт собой ΠΏΡ€ΠΎΡΡ‚ΡƒΡŽ, Π½ΠΎ ΠΎΡ‡Π΅Π½ΡŒ ΡΡ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΡƒΡŽ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ копирования. Она ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строкС Π΄Π²Π° ΠΈΠΌΠ΅Π½ΠΈ Ρ„Π°ΠΉΠ»Π° ΠΈ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ содСрТимоС ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ. Π Π°Π·ΠΌΠ΅Ρ€ исходного Ρ„Π°ΠΉΠ»Π° опрСдСляСтся с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fstat().

Листинг 8.10. (сору.с) ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ„Π°ΠΉΠ»Π° с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sendfile()

#include <fcntl.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/sendfile.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <unistd.h>


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

 int read_fd;

 int write_fd;

 struct stat stat_buf;

 off_t offset = 0;


 /* ΠžΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°. */

 read_fd = open(argv[1], O_RDONLY);

 /* ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°. */

 fstat(read_fd, &stat_buf);

 /* ΠžΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° для записи. */

 write_fd =

  open(argv[2], O_WRONLY | O_CREAT, stat_buf.st_mode);

 /* ΠŸΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ. */

 sendfile(write_fd, read_fd, &offset, stat_buf.st_size);

 /* Π—Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ Ρ„Π°ΠΉΠ»ΠΎΠ². */

 close(read_fd);

 close(write_fd);


 return 0;

}

Ѐункция sendfile() часто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для ΠΏΠΎΠ²Ρ‹ΡˆΠ΅Π½ΠΈΡ эффСктивности копирования. Она ΡˆΠΈΡ€ΠΎΠΊΠΎ примСняСтся Web-сСрвСрами ΠΈ сСтСвыми Π΄Π΅ΠΌΠΎΠ½Π°ΠΌΠΈ, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΌΠΈ Ρ„Π°ΠΉΠ»Ρ‹ ΠΏΠΎ сСти клиСнтским ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°ΠΌ. Запрос ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ поступаСт Ρ‡Π΅Ρ€Π΅Π· сокСт. БСрвСрная ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ дисковый Ρ„Π°ΠΉΠ», ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅Ρ‚ ΠΈΠ· Π½Π΅Π³ΠΎ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ записываСт ΠΈΡ… Π² сокСт. Благодаря Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sendfile() эта опСрация сущСствСнно ускоряСтся.

8.13. Ѐункция setitimer(): Π·Π°Π΄Π°Π½ΠΈΠ΅ ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»ΡŒΠ½Ρ‹Ρ… Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠ²

Ѐункция setitimer() являСтся ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ΠΌ систСмного Π²Ρ‹Π·ΠΎΠ²Π° alarm(). Она ΠΏΠ»Π°Π½ΠΈΡ€ΡƒΠ΅Ρ‚ доставку сигнала ΠΏΠΎ истСчСнии Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΊΠ° Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.