Академический Документы
Профессиональный Документы
Культура Документы
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
166 167 167 167 p0 897 S 501 0:00 -bash
167 897 897 167 p0 897 R 501 0:00 ps -jx
Для того, чтобы всего этого достичь, в демоне нужно осуществить следующие действия:
1) произвести потомка:
if ((pid = fork()) < 0) return -1;
2) выйти из предка
if (pid != 0) { // предок
printf ("daemon started with pid=%d\n", pid);
exit (0);
}
3) в потомке
setsid();
chdir("/");
#include <sys/resource.h>
void main()
{
struct rlimit flim;
getrlimit(RLIMIT_NOFILE, &flim);
for (fd = 0; fd < flim.rlim_max; fd++)
close(fd);
}
г) задать бесконечный цикл (для нашего простейшего демона)
for (; ;) pause();
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 839 839 839 ? -1 S 501 34:32 ./parent -d
Как мы видим, наш процесс является лидером сессии (PID==SID), лидером группы
процессов (PID==PGID) и не имеет управляющего терминала (TTY==?), а его предком
является init (PPID==1), т.к. непосредственный предок прекратил выполнение.
1.2. Сигналы
Синтаксис
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);
Параметры
sig - сигнал, который нужно перехватить или игнорировать, задается аргументом
func - функция, которую следует вызвать при получении заданного сигнала, содержится в
аргументе. Эта функция должна принимать единственный аргумент типа – int (принятый
сигнал) и иметь тип void.
Результат
Функция сигнала возвращает функцию того же типа, которая является предыдущим
значением функции, заданной для обработки сигнала, или одно из двух специальных
значений:
SIG_IGN — игнорировать сигнал;
SIG_DFL — восстановить поведение по умолчанию.
#include<signal.h>
void main()
{
signal (SIGINT, func);
signal (SIGUSR1, func);
}
#include<bsd/signal.h>
void user_handler (int signum)
{
switch (signum) {
case SIGUSR1:
// обработка }}
CXXFLAGS = -I/usr/include
Если нам нужно организовать ожидание сигнала, то, как мы уже видели, можно
использовать функцию pause(). Если бы мы просто задали в нашем демоне бесконечный
цикл, это было бы слишком накладно с точки зрения процессорного времени.
kill 1250
пошлет ему же SIGTERM
kill -9 1250
пошлет ему же SIGKILL (если он не был убит предыдущим действием, SIGKILL используется
в крайних случаях, когда SIGTERM не помогает).
Например
killall -USR1 parent
Синтаксис
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
Параметры
sig - заданный сигнал
pid - код процесса (если -1, то всем)
Результат
В случае успеха она возвращает 0. Функция kill завершится аварийно, вернет -1 и
установит значение переменной errno, если задан неверный сигнал, (errno равна EINVAL),
у процесса нет полномочий (EPERM) или заданный процесс не существует (ESRCH).
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
Параметры
Вызов alarm намечает доставку сигнала SIGALRM через seconds секунд. В
действительности сигнал будильника будет доставлен чуть позже из-за обработки
задержек и учета неопределенностей. Значение 0 отменяет любой невыполненный
запрос на сигнал будильника. Вызов функции alarm до получения сигнала может вызвать
сброс графика доставки. У каждого процесса может быть только один невыполненный
сигнал будильника.
Результат
Функция alarm возвращает количество секунд, оставшихся до отправки любого
невыполненного вызова, alarm, или -1 в случае аварийного завершения.
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
pid_t pid;
printf("alarm application starting\n");
pid = fork();
switch(pid) {
case -1:
/* Аварийное завершение */
perror("fork failed");
exit(1);
case 0:
/* Дочерний процесс */
sleep(5);
kill(getppid(), SIGALRM);
exit(0);
}
Когда вы выполните программу, то увидите, что она делает паузу на пять секунд, в
течение которых ждет имитации будильника:
$ ./alarm
alarm application starting
waiting for alarm to go off
<5 second pause>
Ding!
Done $
Синтаксис
#include <unistd.h>
int pause(void);
Результат
Функция возвращает -1 (если следующий полученный сигнал не вызвал завершения
программы) с переменной errno, равной EINTR, в случае прерывания сигналом. Лучше
для ожидания сигналов применять функцию sigsuspend.
- ident - строка символов, которая будет выводиться каждый раз вместе с информацией
для того, чтобы легче было разобраться, кто что записал в журнал. В лабораторной
работе рекомендуется указывать в ident группу и вариант (т.к. в системный журнал будут
писать демоны разных групп и разобраться, где чей, будет не просто);
- option задает дополнительные параметры журнала, например LOG_PID означает, что
для каждой строки нужно указывать идентификатор процесса, который ее записал;
- facility означает т.н. источник информации (может быть LOG_KERN – от ядра, LOG_USER -
пользовательский процесс и т.д.). Мы будем использовать источник LOG_LOCAL0 (может
быть до LOG_LOCAL7 – это источник, определяемый пользователем) с тем, чтобы не
смешивать сообщения данной работы с другими сообщениями системы.
Синтаксис
Пример:
syslog (LOG_INFO, "daemon started with pid=%d", pid);
Вот какой вид имеет одна строка записи в журнале (при LOG_PID):
Oct 4 12:44:17 asu i38a1-daemon[2074]: daemon started with
pid=2074
После окончания работы с журналом его следует закрыть: closelog();