LinuxForum.Fans
Тема

Помогите разобраться с сигналами

Автор: NegativeCreep 10 сообщений 2127 просмотров
#106635

Имею такое задание:
Написать программу trykill которая на практике определяет множество сигналов,
- которыми могут обмениваться 2 процесса одного пользователя;
- которые могут быть посланы процессом пользователя A процессу пользователя B, при условии, что пользователи A и B являются членами одной группы;
- которые могут быть посланы процессом пользователя A процессу пользователя root.

Честно, не совсем представляю себе, как это решать. Нашел в интернете такую программу:

text
void sig_handler(int sig)
{
    printf("cathed signal %d\n",sig);
    exit(0);
}
int main(int argc,char **argv[])
{
    int i,errno,err;
    pid_t pid;
    // пока он спит, тестим его на восприимчивость сигналов
    for(i = 1;i < NSIG;i++)
    {
        if(i!=SIGSTOP&&i!= SIGKILL)
        {
            errno=0;
            err=signal(i, sig_handler);
            printf("sig %d, status %d, errno %d\n",i,err,errno);
        }
    }
    if((pid=fork())==0)
    {
        execl("./launch","./launch",0);
        sleep(30);
    }
}

В случае, когда надо послать сигнал другому пользователю:

text
void sig_handler(int sig)
{
    exit(0);
}
int main(int argc,char **argv[])
{
    int i,errno,err;
    pid_t pid;
    for(i = 1;i <NSIG;i++)
    {
        if(i!=SIGSTOP&&i!= SIGKILL)
        {
            err=kill(ЗДЕСЬ PID ПРОЦЕССА ДРУГОГО ПОЛЬЗОВАТЕЛЯ, i);
            printf("sig %d, status %d\n",i,err);
        }
    }
    if((pid=fork())==0)
    {
        execl("./launch","./launch",0);
        sleep(30);
    }
}

Как я понял, на печать выводятся сигналы, на которые отреагеровала функция sig_handler в виде цифр(по сути числа от 1 до 64). Мне же нужно, чтобы это были названия сигналов(типа SIGSTOP, SIGKILL). Первый вопрос - как сделать, чтобы выводились они.
Ну, это работает для процессов одного пользователя, а второй вопрос заключается в том, чтобы сделать это для двух.

-

#106659

Так, вроде получил желаемый результат)

Пожалуйста, подскажите тогда верно ли следующее:
Процесс пользователя А может посылать любые сигналы процессу пользователя В
Процесс пользователя А не может посылать процессу пользователя B никаких сигналов, даже если они члены одной группы
Ну и тем более процессу пользователя root

#106674
NegativeCreep написал:
Пожалуйста, подскажите тогда верно ли следующее:
1)Процесс пользователя А может посылать любые сигналы процессу пользователя В
2)Процесс пользователя А не может посылать процессу пользователя B никаких сигналов, даже если они члены одной группы
Ну и тем более процессу пользователя root

1) да
2) ничегонипонял. сформулируйте по человечески.

#106676

man wait

text
       #include <sys/wait.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <stdio.h>

int main(int argc, char *argv[]) { pid_t cpid, w; int status;

cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); }

if (cpid == 0) { /* Code executed by child */ printf("Child PID is %ld\n", (long) getpid()); if (argc == 1) pause(); /* Wait for signals */ _exit(atoi(argv[1]));

} else { /* Code executed by parent */ do { w = waitpid(cpid, &status, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); }

if (WIFEXITED(status)) { printf("exited, status=%d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("killed by signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("stopped by signal %d\n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("continued\n"); } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); exit(EXIT_SUCCESS); } }

PS: ну маны читать нынче не модно :(

#106678
drBatty написал:
[quote=NegativeCreep]Пожалуйста, подскажите тогда верно ли следующее:
1)Процесс пользователя А может посылать любые сигналы процессу пользователя В
2)Процесс пользователя А не может посылать процессу пользователя B никаких сигналов, даже если они члены одной группы
Ну и тем более процессу пользователя root

1) да
2) ничегонипонял. сформулируйте по человечески.[/quote]
Извиняюсь, торопился. В пером было "Процесс пользователя А может посылать любые сигналы процессу пользователя А".
Насчет второго - такой вывод сделал на основании того, что kill(pid,signal) возвращала -1(pid - пид любого процесса пользователя Б).

drBatty написал:
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int
main(int argc, char *argv[])
{
pid_t cpid, w;
int status;

cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}

if (cpid == 0) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));

} else { /* Code executed by parent */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}

if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}

PS: ну маны читать нынче не модно sad

За программу огромное спасибо, все понятно кроме того, где мы определяем переменную status. man wait изучал, использовать его не догадался(.
Как я понимаю, нужно запустить эту программу, а затем посылать ей сигналы с другой.

#106680

Вид исходного кода исправил.

#106685
NegativeCreep написал:

1)Извиняюсь, торопился. В пером было "Процесс пользователя А может посылать любые сигналы процессу пользователя А".
2)Насчет второго - такой вывод сделал на основании того, что kill(pid,signal) возвращала -1(pid - пид любого процесса пользователя Б).

1) куда спешить-то?
2) да. насколько я знаю, только процесс с UID == 0 может посылать сообщения другим процессам. Это связанно с безопасностью (например на сервере одни пользователи не имеют права вырубать программы других. Ибо анархия == wendowz.) Только администратор может управлять процессами пользователей. Я знаю, это не очень удобно - приходится делать например сигнальные файлы для обмена информацией.

NegativeCreep написал:
где мы определяем переменную status

в самом начале. потом адрес этой переменной передаётся внутрь waitpid(), которая и пишет туда текущий статус.

NegativeCreep написал:
Как я понимаю, нужно запустить эту программу, а затем посылать ей сигналы с другой.

ага. А программа, которая посылает сигналы называется kill. По умолчанию она посылает сигнал TERM, который завершает программу, но можно послать и любой другой сигнал любой программе.

Имеется исключение: сигнал KILL передаётся не программе, а ядру, которое завершает заданный процесс. например:
[console]doc@dt:~$ sleep 1h &
[1] 2368
doc@dt:~$ kill -KILL 2368
doc@dt:~$ kill -KILL 2368
bash: kill: (2368) - Нет такого процесса
[1]+ Убито sleep 1h
doc@dt:~$
[/console]
тут я запустил программу sleep, с параметром "1 час". А потом грохнул её, послав сигнал KILL (это девятка).

NegativeCreep написал:
Вид исходного кода исправил.

спасибо.

#106687
NegativeCreep написал:
Мне же нужно, чтобы это были названия сигналов(типа SIGSTOP, SIGKILL).

добавьте в вашу программу

text
#include <signal.h>

это приведёт к добавлению такого файла (далее для моей системы, в вашей файл может быть другим и с другим именем!)
doc@dt:~$ cat !$

text
cat /usr/include/bits/signum.h
/* Signal number definitions.  Linux version.
   Copyright (C) 1995,1996,1997,1998,1999,2003 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */

#ifdef _SIGNAL_H

/* Fake signal functions. */ #define SIG_ERR ((__sighandler_t) -1) /* Error return. */ #define SIG_DFL ((__sighandler_t) 0) /* Default action. */ #define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */

#ifdef __USE_UNIX98 # define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ #endif

/* Signals. */ #define SIGHUP 1 /* Hangup (POSIX). */ #define SIGINT 2 /* Interrupt (ANSI). */ #define SIGQUIT 3 /* Quit (POSIX). */ #define SIGILL 4 /* Illegal instruction (ANSI). */ #define SIGTRAP 5 /* Trace trap (POSIX). */ #define SIGABRT 6 /* Abort (ANSI). */ #define SIGIOT 6 /* IOT trap (4.2 BSD). */ #define SIGBUS 7 /* BUS error (4.2 BSD). */ #define SIGFPE 8 /* Floating-point exception (ANSI). */ #define SIGKILL 9 /* Kill, unblockable (POSIX). */ #define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ #define SIGSEGV 11 /* Segmentation violation (ANSI). */ #define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ #define SIGPIPE 13 /* Broken pipe (POSIX). */ #define SIGALRM 14 /* Alarm clock (POSIX). */ #define SIGTERM 15 /* Termination (ANSI). */ #define SIGSTKFLT 16 /* Stack fault. */ #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ #define SIGCHLD 17 /* Child status has changed (POSIX). */ #define SIGCONT 18 /* Continue (POSIX). */ #define SIGSTOP 19 /* Stop, unblockable (POSIX). */ #define SIGTSTP 20 /* Keyboard stop (POSIX). */ #define SIGTTIN 21 /* Background read from tty (POSIX). */ #define SIGTTOU 22 /* Background write to tty (POSIX). */ #define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ #define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ #define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ #define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ #define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ #define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ #define SIGPOLL SIGIO /* Pollable event occurred (System V). */ #define SIGIO 29 /* I/O now possible (4.2 BSD). */ #define SIGPWR 30 /* Power failure restart (System V). */ #define SIGSYS 31 /* Bad system call. */ #define SIGUNUSED 31

#define _NSIG 65 /* Biggest signal number + 1 (including real-time signals). */

#define SIGRTMIN (__libc_current_sigrtmin ()) #define SIGRTMAX (__libc_current_sigrtmax ())

/* These are the hard limits of the kernel. These values should not be used directly at user level. */ #define __SIGRTMIN 32 #define __SIGRTMAX (_NSIG - 1)

#endif /* <signal.h> included. */

#106688
NegativeCreep написал:
if(i!=SIGSTOP&&i!= SIGKILL)

довольно глупо, ибо насколько я знаю, SIGKILL никогда не доходит до программы.

#106814

Спасибо за терпение и за помощь)
Почти все понял, остался один маленький вопрос)
Сигналы через kill надо вручную посылать, потому что некоторые будут убивать процесс, и надо его запускать заного (с новым pid). Это верно?

Войдите или зарегистрируйтесь, чтобы ответить.