Linux программирование в примерах
• После
положение сигналов в порожденном процессе остается тем же самым, за исключением сброса ожидающих сигналов и установленных интервалов таймера. Послеfork()положение несколько более сложно — в сущности, все, что может быть оставлено, остается; для всего остального восстанавливаются значения по умолчанию.exec()Упражнения
1. Реализуйте
с использованиемbsd_signal().sigaction()2. Если у вас не установлен GNU/Linux, запустите на своей системе
. Является ли ваша система традиционной или BSD?ch10-catchint3. Реализуйте функции System V Release 3
,sighold(),sigrelse(),sigignore()иsigpause(), использовавsigset()и другие подходящие функции из POSIX API.sigaction()4. Потренируйте свои навыки в жонглировании битами. В предположении, что сигнал 0 отсутствует и что имеется не более 31 сигналов, предусмотрите
дляtypedefи напишитеsigset_t,sigemptyset(),sigfillset(),sigaddset()иsigdelset().sigismember()5. Еще немного потренируйте свои навыки жонглирования битами. Повторите предыдущее упражнение, на этот раз предположив, что наибольшим сигналом является 42.
6. Теперь, когда вы сделали предыдущие два упражнения, найдите
и др. в своем заголовочном файлеsigemptyset(). (Может потребоваться поискать их; они могут быть в<signal.h>файлах, указанных в#include.) Являются ли они макросами или функциями?<signal.h>7. В разделе 10.7 «Сигналы для межпроцессного взаимодействия» мы упомянули, что код изделия должен работать с начальной маской сигналов процесса, добавляя и удаляя блокируемые сигналы в вызове
. Перепишите пример, используя для этого соответствующие вызовы.sigsuspend()8. Напишите свою собственную версию команды
. Интерфейс должен быть таким:killkill [-s <i>имя-сигнала</i>] <i>pid</i> ...Если сигнал не указан, программа должна посылать
.SIGTERM9. Как вы думаете, почему в современных оболочках, таких, как Bash и ksh93,
является встроенной командой?kill10. (Трудное) Реализуйте
, используяsleep(),alarm()иsignal(). Что случится, если обработчик сигнала дляpause()уже установлен?SIGALRM11. Поэкспериментируйте с
, изменяя интервал времени, на который засыпает каждый потомок, и организуя достаточное число вызововch10-reap.cдля сбора сведений о всех потомках.sigsuspend()12. Попробуйте заставить
испортить информацию вch10-reap2.c,kidsиnkids. Теперь добавьте вокруг критического раздела блокирование/разблокирование и посмотрите, есть ли разница.kidsleftГлава 11
Права доступа и ID пользователей и групп
Linux, вслед за Unix, является многопользовательской системой. В отличие от большинства операционных систем для персональных компьютеров, [114] в которых имеется лишь один пользователь и в которых, кто бы ни находился перед компьютером, он имеет полный контроль, Linux и Unix различают файлы и процессы по владельцам и группам, которым они принадлежат. В данной главе мы исследуем проверку прав доступа и рассмотрим API для получения и установки идентификаторов владельцев и групп.
11.1. Проверка прав доступа
Как мы видели в разделе 5.4.2 «Получение информации о файлах», файловая система хранит идентификаторы владельца и группы файла в виде числовых значений; это типы
иuid_tсоответственно. Для краткости мы используем для «идентификатора владельца (пользователя)» и «идентификатора группы» сокращения UID и GID соответственно.gid_tУ каждого процесса есть несколько связанных с ним идентификаторов пользователя и группы. Для проверки прав доступа в качестве упрощения используется один определенный UID и GID; когда UID процесса совпадает с UID файла, биты прав доступа пользователя файла диктуют, что может сделать процесс с файлом. Если они не совпадают, система проверяет GID процесса с GID файла; при совпадении используются права доступа группы; в противном случае, используются права доступа для «остальных».
Помимо файлов, UID определяет, как один процесс может повлиять на другой путем посылки сигналов. Сигналы описаны в главе 10 «Сигналы».
Наконец, особым случаем является суперпользователь,
.rootидентифицируется по UID, равным 0. Когда у процесса UID равен 0, ядро позволяет ему делать все, что он захочет: читать, записывать или удалять файлы, посылать сигналы произвольным процессам и т.д. (POSIX в этом отношении более непонятный, ссылаясь на процессы с «соответствующими привилегиями». Этот язык, в свою очередь, просочился в справочные страницы GNU/Linux и справочное руководство GLIBC online Info manual. Некоторые операционные системы действительно разделяют привилегии пользователей, и Linux также движется в этом направлении. Тем не менее, в настоящее время «соответствующие привилегии» означает просто процессы с UID, равным 0.)root11.1.1. Действительные и эффективные ID
Номера UID и GID подобны персональным удостоверениям личности. Иногда вам может понадобиться более одного удостоверяющего документа. Например, у вас могут быть водительские права или правительственное удостоверение личности [115]. Вдобавок, ваш университет или компания могли выдать вам свои удостоверения личности. То же самое относится и к процессам; они имеют при себе множество следующих номеров UID и GID:
Действительный ID пользователя
UID пользователя, породившего процесс.
Эффективный ID пользователя
UID, использующийся при большинстве проверок прав доступа. В большинстве случаев эффективный и действительный UID являются одним и тем же. Эффективный UID может отличаться от действительного при запуске, если установлен бит setuid файла исполняемой программы и файл не принадлежит пользователю, запускающему программу. (Вскоре будут дополнительные сведения.)
Сохраненный set-user ID
Первоначальный эффективный UID при запуске программы (после выполнения exec.) Имеет значение при проверке прав доступа, когда процессу нужно менять действительный и эффективный UID в ходе работы. Эта концепция пришла из System V.