Самьюэл Алекс
Шрифт:
В структуре
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);