Администрирование локальных сетейРефераты >> Программирование и компьютеры >> Администрирование локальных сетей
tm_mday дата месяца 1 31
tm_wday день недели 0 6 (0 - Воскресенье)
tm_hour часы 0 23
tm_min минуты 0 59
tm_sec секунды 0 59
Номера месяца и дня недели начинаются с нуля, чтобы вы могли использовать их в качестве индексов:
char *months[] = { "Январь", "Февраль", ., "Декабрь" };
printf( "%s\n", months[ tm->tm_mon ] );
Часто бывает нужда передавать значения времени в одной строке
Вот пример программы которая преобразовывает в ремя в такой формат:
/* Mon Jun 12 14:31:26 2000 */
#include <stdio.h>
#include <time.h>
main() { /* команда date */
time_t t = time(NULL);
char *s = ctime(&t);
printf("%s", s);
}
UNIX-машины имеют встроенные таймеры (как правило несколько) с довольно высоким разрешением. Некоторые из них могут использоваться как "будильники" с обратным отсчетом времени: в таймер загружается некоторое значение; таймер ведет обратный отсчет, уменьшая загруженный счетчик; как только это время истекает - посылается сигнал процессу, загрузившему таймер.
Вот как, к примеру, выглядит функция задержки в микросекундах (миллионных долях секунды). Примечание: эту функцию не следует использовать вперемежку с функциями sleep и alarm.
#include <sys/types.h>
#include <signal.h>
#include <sys/time.h>
void do_nothing() {}
/* Задержка на usec миллионных долей секунды (микросекунд) */
void usleep(unsigned int usec) {
struct itimerval new, old;
/* struct itimerval содержит поля:
struct timeval it_interval;
struct timeval it_value;
Где struct timeval содержит поля:
long tv_sec; -- число целых секунд
long tv_usec; -- число микросекунд
*/
struct sigaction new_vec, old_vec;
if (usec == 0) return;
/* Поле tv_sec содержит число целых секунд.
Поле tv_usec содержит число микросекунд.
it_value - это время, через которое В ПЕРВЫЙ раз
таймер "прозвонит",
то есть пошлет нашему процессу
сигнал SIGALRM.
Время, равное нулю, немедленно остановит таймер.
it_interval - это интервал времени, который будет загружаться
в таймер после каждого "звонка"
(но не в первый раз).
Время, равное нулю, остановит таймер
после его первого "звонка".
*/
new.it_interval.tv_sec = 0;
new.it_interval.tv_usec = 0;
new.it_value.tv_sec = usec / 1000000;
new.it_value.tv_usec = usec % 1000000;
/* Сохраняем прежнюю реакцию на сигнал SIGALRM в old_vec,
заносим в качестве новой реакции do_nothing()
*/
new_vec.sa_handler = do_nothing;
sigemptyset(&new_vec.sa_mask);
new_vec.sa_flags = 0;
sigaction(SIGALRM, &new_vec, &old_vec);
/* Загрузка интервального таймера значением new, начало отсчета.
* Прежнее значение спасти в old.
* Вместо &old можно также NULL - не спасать.
*/
setitimer(ITIMER_REAL, &new, &old);
/* Ждать прихода сигнала SIGALRM */
sigpause(SIGALRM);
/* Восстановить реакцию на SIGALRM */
sigaction(SIGALRM, &old_vec, (struct sigaction *) 0);
sigrelse(SIGALRM);
/* Восстановить прежние параметры таймера */
setitimer(ITIMER_REAL, &old, (struct itimerval *) 0);
}
Пример оспользования интервалов
#include <stdio.h>
#include <unistd.h> /* _SC_CLK_TCK */
#include <signal.h> /* SIGALRM */
#include <sys/time.h> /* не используется */
#include <sys/times.h> /* struct tms */
struct tms tms_stop, tms_start;
clock_t real_stop, real_start;
clock_t HZ; /* число ticks в секунде */
/* Засечь время момента старта процесса */
void hello(void){
real_start = times(&tms_start);
}
/* Засечь время окончания процесса */
void bye(int n){
real_stop = times(&tms_stop);
#ifdef CRONO
/* Разность времен */
tms_stop.tms_utime -= tms_start.tms_utime;
tms_stop.tms_stime -= tms_start.tms_stime;
#endif
/* Распечатать времена */
printf("User time = %g seconds [%lu ticks]\n",
tms_stop.tms_utime / (double)HZ, tms_stop.tms_utime);
printf("System time = %g seconds [%lu ticks]\n",
tms_stop.tms_stime / (double)HZ, tms_stop.tms_stime);
printf("Children user time = %g seconds [%lu ticks]\n",
tms_stop.tms_cutime / (double)HZ, tms_stop.tms_cutime);
printf("Children system time = %g seconds [%lu ticks]\n",
tms_stop.tms_cstime / (double)HZ, tms_stop.tms_cstime);
printf("Real time = %g seconds [%lu ticks]\n",
(real_stop - real_start) / (double)HZ, real_stop - real_start);
exit(n);
}
/* По сигналу SIGALRM - завершить процесс */
void onalarm(int nsig){
printf("Выход #%d ================\n", getpid());
bye(0);
}
/* Порожденный процесс */
void dochild(int n){
hello();
printf("Старт #%d ================\n", getpid());
signal(SIGALRM, onalarm);
/* Заказать сигнал SIGALRM через 1 + n*3 секунд */
alarm(1 + n*3);
for(;;){} /* зациклиться в user mode */
}
#define NCHLD 4
int main(int ac, char *av[]){
int i;
/* Узнать число тиков в секунде */
HZ = sysconf(_SC_CLK_TCK);
setbuf(stdout, NULL);
hello();
for(i=0; i < NCHLD; i++)
if(fork() == 0)
dochild(i);
while(wait(NULL) > 0);
printf("Выход MAIN =================\n");
bye(0);
return 0;
}
Сигналы.
Процессы в UNIX используют много разных механизмов взаимодействия. Одним из них являются сигналы.
Сигналы - это асинхронные события. Что это значит? Сначала объясним, что такое синхронные события: я два раза в день подхожу к почтовому ящику и проверяю - нет ли в нем почты (событий). Во-первых, я произвожу опрос - "нет ли для меня события?", в программе это выглядело бы как вызов функции опроса и, может быть, ожидания события. Во-вторых, я знаю, что почта может ко мне прийти, поскольку я подписался на какие-то газеты. То есть я предварительно заказывал эти события.
Схема с синхронными событиями очень распространена. Кассир сидит у кассы и ожидает, пока к нему в окошечко не заглянет клиент. Поезд периодически проезжает мимо светофора и останавливается, если горит красный. Функция Си пассивно "спит" до тех пор, пока ее не вызовут; однако она всегда готова выполнить свою работу (обслужить клиента). Такое ожидающее заказа (события) действующее лицо называется сервер. После выполнения заказа сервер вновь переходит в состояние ожидания вызова. Итак, если событие ожидается в специальном месте и в определенные моменты времени (издается некий вызов для ОПРОСА) - это синхронные события. Канонический пример - функция gets, которая задержит выполнение программы, пока с клавиатуры не будет введена строка. Большинство ожиданий внутри системных вызовов - синхронны. Ядро ОС выступает для программ пользователей в роли сервера, выполняющего сисвызовы (хотя и не только в этой роли - ядро иногда предпринимает и активные действия: передача процессора другому процессу через определенное время (режим разделения времени), убивание процесса при ошибке, и.т.п.).