|
Программирование >> Структура ядра и системные вызовы
функции рореп и pclose определены в P0SIX.2, но не в POSIX.l. Их использование демонстрируется ниже на примере программе test popen. С: ♦include <stdio.h> ♦include <unistd.h> int main (int argc, char* argv[]) { char buf(256], *mode= (argc>2) ? w : r ; FILE *fptr; if (argOl && (fptr = popen (argv[ 1 ],mode)) ) ( switch (*mode) ( case r: while (fgets(buf,256,fptr)) fputs(buf,stdout); break; case W: fprintf (fptr, %s\n ,argv[2] ) ; return pclose(fptr); return 5; Синтаксис вызова этой тест-программы выглядит так: % a.out <shell cmd> [ <данные, предназначенные для записи в shell cmd> ] Если вызов осуществляется только с одной командой shell (то есть с одним аргументом), то программа вызывает функцию рореп для выполнения команды и вывода на консоль данных, поступающих на стандартный вывод выполняемой команды. Если же программа вызывается с двумя аргументами, она с помощью рореп выполняет указанную в первом аргументе команду, а второй аргумент передает на стандартный ввод выполняемой команды. Для заверщения вызова рореп программа вызывает функцию pclose. Ее пробное выполнение, как правило, дает такие результаты: % СС test popen.C % a.out date Sat Apr 12 21:42:22 PST 1997 % a.out wc Hello world 12 11 8.3. Атрибуты процессов Описание процессов не будет полным без упоминания различных API, предназначенных для запроса и установки некоторых атрибутов процессов. В этом разделе будут описаны API запроса атрибутов процесса, являющиеся общими для UNIX и POSIX.l. В следующем разделе мы рассмотрим API UNIX и POSIX.l, меняющие атрибуты процессов. #include <sys/types.h> #include <unistd.h> pid t getpid (void); pid t getppid (void); pid t getpgrp (void); uid t getuid (void); uid t geteuid (void); getgid (У1о\6); gid t getegid (У10\6); Необходимо отметить, что в старых версиях UNIX все перечисленные API возвращают значения типа int. Типы данных pidj, uidt и gidj определяются в заголовке <sys/types.h>. API getpid и getppid возвращают идентификаторы текущего и родительского процессов соответственно. Для этих системных вызовов аргументы не требуются. API getpgrp возвращает идентификатор группы вызывающего процесса. Каждый процесс в системах UNIX и POSIX принадлежит к группе процессов. Когда пользователь входит в систему, регистрационный процесс становится лидером сеанса и лидером группы процессов. Идентификатор сеанса и идентификатор группы процесса для лидера сеанса совпадают с PID данного процесса. Если регистрационный процесс создает для выполнения заданий новые порожденные процессы, эти процессы будут принадлежать к тому же сеансу и группе, что и регистрационный процесс. Если регистрационный процесс переводит определенные задания в фоновый режим, то процессу, связанному с каждым фоновым заданием, будет присвоен другой идентификатор группы. Если фоновое задание выполняется более чем одним процессом, то процесс, создавший все остальные процессы с целью выполнения данного фонового задания, станет лидером этой группы процессов. Системные вызовы getuid и getgid возвращают соответственно реальный идентификатор владельца и реальный идентификатор группы вызывающего процесса. Реальные идентификаторы группы и владельца являются идентификаторами лица, создавшего этот процесс. Например, когда вы входите в UNIX-систему, реальными идентификаторами группы и владельца регистрационного shell являются соответственно ваш идентификатор группы и ваш идентификатор пользователя. Все порожденные процессы, созданные регистрационным shell, также будут иметь ваши реальные идентификаторы группы и пользователя. Вышеупомянутые реальные идентификаторы используются ядром UNIX для того, чтобы следить за тем, какой пользователь создал процесс в системе. Системные ъызоъы geteuid и getegid возвращают значения атрибутов eUID и eGID вызывающего процесса. Эти идентификаторы используются ядром для определения прав вызывающего процесса на доступ к файлам. Такие атрибуты присваиваются также идентификаторам группы и владельца для файлов, создаваемых процессом. В нормальных условиях эффективный идентификатор пользователя процесса совпадает с его реальным идентификатором. Однако в случае, когда установлен бит смены идентификатора пользователя set-UID выполняемого файла, эффективный идентификатор владельца процесса будет равен идентификатору владельца исполняемого файла. Это дает процессу такие же права доступа, какими обладает пользователь, владеющий исполняемым файлом. Аналогичный механизм применим и к эффективному идентификатору группы. Так, эффективный идентификатор группы процесса будет отличаться от реального идентификатора фуппы, если установлен бит смены идентификатора группы set-GID соответствующего исполняемого файла. Примером использования флага set-UID является команда /Ып/passwd. Эта команда помогает пользователям изменять пароли в файле /etc/passwd. Так как файл /etc/passwd обычные пользователи могут только читать, то для того, чтобы записывать данные в файл /etc/passwd, процесс, созданный в результате выполнения программы /Ып/passwd, должен иметь права привилегированного пользователя. Поэтому идентификатор владельца программы /bin/passwd является идентификатором привилегированного пользователя, а флаг set-UID, определяющий режим доступа к этому файлу, установлен. Процесс, созданный в результате выполнения программы /bin/passwd, будет иметь эффективный идентификатор привилегированного пользователя и обладать правом модифицирования фа.Шй/etc/passwd в ходе его выполнения. Флаги set- UID и set-GID исполняемого файла можно изменить с помощью команды chmod или с помощью API chmod. Способ получения атрибутов процесса демонстрируется на примере программы getproc. С: ♦include <iostream.h> tinclude <sys/types.h> tinclude <unistd.h> int main ( ) ( cout Process PID: (int)getpid() << endl; cout Process PPID: (int)getppid() << endl; cout Process PGID: (int)getpgrp () endl; cout Process real-UID: (int)getuid() endl; cout Process real-GID: (int)getgidO endl; cout Process effective-UID: (int)geteuid() endl; cout . Process effective-GID: << (int)getegidO endl; return 0; Результат выполнения программы может быть следующим: СС getproc.с \% а. out Process PID: 1254 Process PPID: 200 Process PGID: 50 Process real-UID: 751 . Process real-GID: 77 Process effective-UID: 205 Process effective-GID:77 8.4. Изменение атрибутов процесса в этом разделе описаны API POSIX. 1 и UNIX, которые изменяют атрибуты процесса. Следует отмететь, что некоторые из атрибутов (например, вдентификатор процесса и идентификатор родетельского процесса) можно запросить, но нельзя изменеть, в то время как другие атрибуты (например, вдентификатор сеанса процесса) нельзя запросить, но можно изменить. #include <sys/types.h> #include <unistd.h> int setsid (void); int setpgid (pid t pid, pid t pgid); int setuid (uid t uid); , int seteuid (uid t uid); int setgid (gid t gid);,., int setegid (gid t gid); API setsid делает вызывающий процесс лидером нового сеанса и новой группы процессов. Идентификатор сеанса и идентификатор группы вызывающего процесса совпадают с его PID. Процесс будет отсоединен от своего управляющего терминала. Этот API обычно вызывается процессом-демоном после создания последнего, чтобы процесс-демон мог работать независимо от своего родотельского процесса. Такой API характерен для POSIX. 1. API setpgid делает вызывающий процесс лвдером рювой группы процессов. Идентификатор группы вызывающего процесса совпадает с его PID. Этот процесс будет единственным членом в новой группе. Вызов рассматриваемого API будет неудачным, если вызывающий процесс уже является лидером сеанса. В UNIX System V API setpgrp эквивалентен API setpgid. Реальные и эффективные идентификаторы не будут совпадать, если для файла a.out посредством команды chmod установлены биты смены идентификаторов пользователя и группы. - Прим. ред. Если эффективный идентификатор владельца процесса совпадает с идентификатором привилегированного пользователя, системный вызов setuidf изменяет реальный UID, эффективный UID и установленный UID щ значение аргумента uid. Если, однако, эффективный идентификатор вызывающего процесса не равен ГО привилегированного пользователя, то, если uid равен реальному, либо установленному UID, этот API изменяет эффективный идентификатор пользователя на значение uid. В противном случае API возвращает код неудачного заверщения -1. Если эффективный идентификатор группы процесса - это идентификатор группы привилегированного пользователя, системный вызов setgid определяет реальный идентификатор группы, эффективный идентификатор группы и установленный идентификатор группы как значение аргумента gid. Если, однако, идентификатор вызывающего процесса не равен эффективному идентификатору привилегированного пользователя, то, если gid равен либо реальному, либо установленному GID, этот API заменяет эффективный идентификатор группы значением gid. В противном случае API возвращает код неудачного заверщения -1. API seteuid изменяет эффективный идентификатор владельца вызывающего процесса на значение uid. Если процесс не обладает правами привилегированного пользователя, значение uid должно быть либо реальным идентификатором пользователя, .тибо сохраненным установленным идентификатором пользователя процесса. С другой стороны, если процесс обладает правами привилегированного пользователя, uid может иметь любое значение. API setegid изменяет эффективный идентификатор группы вызывающего процесса на значение gid. Если процесс не имеет прав привилегированного пользователя, gid должен быть либо реальным идентификатором группы, либо установленным сохраненным идентификатором фуппы процесса. С другой стороны, если процесс имеет права привилегированного пользователя, gid может иметь любое значение. 8.5. Программа minishell Чтобы показать, как используются API процессов, в данном разделе описывается простая программа эмуляции shell, создающая процессы, которые могут последовательно или параллельно выполнять любое количество UNIX-команд. Это могут бьп-ь любые указанные пользователем команды с переназначением ввода и (или) вывода, а также команды в фоновом и (или) приоритетном (foreground) режимах. Единственным недостатком этой программы является то, что она не поддерживает переменные shell и метасимволы. Программа minishell построена следующим образом. Простая UNIX-команда состоит из имени, необязательных ключей и любого количества аргументов. Кроме того, для каждой команды может быть использовано переназначение ввода-вывода, для соединения различных простых команд можно организовать каналы, а для выполнения команды в фоновом режиме указать в конце команды символ & . Ниже приведены примеры команд UNIX, приемлемых для нащей программы: % pwd > foo % sort-r /etc/passwd S % cat -n < abc > foo % Is -1 I sort-r I cat -n % cat foo; date; pwd > zz # простая команда с переназначением вывода # команда, выполняемая в фоновом режиме # команда с переназначением ввода-вывода # два канала с тремя командами # три команды, выполняемые последовательно % (spell/etc/motd I sort) > хх; date # выполнение двух команд во вторичном shell Для обработки этих команд создается класс CMD INFO, в котором каждый из объектов хранргг информацию о простой команде. Определение данного класса выглядит так: class CMD INFO { public: char** char* char* int , argv; список команд и аргументов infile; переназначенный файл стандартного ввода outfile переназначенный файл стандартного вывода backgrnd; 1, если команда подлежит выполнению в фоновом режиме GMD INFO* pSubcmd; команды, подлежащие запуску ,во вторичном shell CMD INFO* Pipe; следующая команда после I CMD INFO* Next; следующая команда после ; Г В частности, в переменной argv хранятся имя команды, ее ключи и аргументы в виде массива (вектора) указателей на символьные строки. Так, в команде % sort -г /etc/motd > foo & переменная argv объекта CMD INFO, выполняющего эту команду, будет выглядеть следующим образом: argv[0] argv[l] argv[2] argv[3] sort II 11 /etc/motd 0; В переменных infde и outfde хранятся имена переназначенных файлов ввода и вывода, которые указаны в команде. Для приведенного выще примера с командой sort переменные infde и oufile объекта CMD 1NF0 будут содержать такие значения: infile = о; outfile = foo Переменная backgrnd указывает приоритетный или фоновый режим выполнения команды. По умолчанию эта переменная равна 0. Это означает, что соответствующую команду следует выполнять в приоритетном режиме.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |