Программирование >>  Структура ядра и системные вызовы 

1 ... 51 52 53 [ 54 ] 55 56 57 ... 98


в случае успешного выполнения этот API возвращает нуль, а в случае неудачи -1.

finclude <sys/types.h> finclude <sys/ipc.h> finclude <sys/sem.h>

/* уменьшить значение 1-го семафора на 1, проверить значение 2-го

семафора на равенство нулю */ struct semid ds sbuf[2] = {{О, -1, SEMUNDO I IPC NOWIT), (1, 0, 1);

Int mainO

{ . .

int perms = S IRWXU S IRWXG S IRWXO; int fd = semget(100, 2, IRC CREAT \ perms); if (fd==-l) { perrot( semget ); exit; ) if (semop(fd, sbuf, 2)==-l) perror( semop; ); return 0;

в этом примере открьшается двухсемафорный набор с ключевым идентификатором 100. Этот набор создается (если такого набора еще не было) с разрешением на чтение и запись для всех категорий пользователей.

Если вызов semget проходит успешно, процесс вызьтает функцию semop, которая /меньшает значение первого семафора на 1 и проверяет значение второго семафора на равенство нулю. Кроме того, при обращении к первому семафору указываются флаги IPC NOWAIT и SEM UNDO.

10.5.5. Функция semcti

Прототип функции semcti имеет следующий вид:

#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>

int semcti (int semfd, int num, int cmd, union semun arg );

С помощью этого API можно запрашивать и изменять управляющие параметры набора семафоров, указанного аргументом semfd, а также удалять семафор.

Значение semfd - это дескриптор набора семафоров, который берется из вызова функции semget.

Значение пит - это индекс семафора, а следующий аргумент, cmd, задает операцию, которая должна бьггь выполнена над конкретным семафором данного набора.

Аргумент arg - это объект типа union, который может использоваться для задания или выборки управляющих параметров одного или нескольких

семафоров набора в соответствии t аргументом cmd. Тип данных union semun определяется в заголовке <sys/sem.h>:

union semun {

int val; значение семафора

struct semid ds *buf; управляющие параметры набора

ushort *array; массив значений семафоров

Ниже перечислены возможные значения аргумента cmd и их смысл.

Значение cmd Что должен сделать процесс

IPC STAT Копировать управляющие параметры набора в объект, указан-

ный аргументом arg.buf. У вызывающего процесса должно быть право на чтение набора

IPC SET Заменить управляющие параметры набора семафоров данными,

~ определенными в объекте, на который указывает аргумент

arg.buf. Чтобы выполнить эту операцию, вызывающий процесс должен иметь права привилегированного пользователя, создателя или назначенного владельца набора. Этот API может устанавливать UID владельца набора и идентификатор его группы, а также права доступа

IPC RMID Удалить семафор из системы. Чтобы выполнить эту операцию,

вызывающий процесс должен иметь права привилегированного пользователя, создателя или назначенного владельца набора

GETALL Скопировать все значения семафоров в массив, на который

указывает arg.array

SETALL Установить все значения семафоров равными значениям, со-

держащимся в массиве, на который указывает arg.array

GETVAL Возвратить значение семафора с номером пит. Аргумент arg не

используется

SETVAL Установить значение семафора с номером пит равным значе-

нию, указанному в arg.val

GETPID Возвратить идентификатор процесса, который выполнял опе-

рации над семафором с номером пит последним. Аргумент arg не используется

GETNCNT Возвратить количество процессов, которые в текущий момент

заблокированы и ожидают увеличения значения семафора с номером пит. Аргумент arg не используется ;

GETZCNT Возвратить количество процессов, которые в текущий момент заблокированы и ожидают обращения значения семафора с; номером пит в нуль. Аргумент arg не используется

в случае успешного выполнения этот API возвращает значение, соответ* ствующее конкретному cmd, а в случае неудачи -1.

Приведенная ниже программа test sem. С открывает набор семафоров с ключевым идентификатором 100 и вызьшает semcti для получения управляющих параметров набора. Если вызовы функций semget и semcU выполняются успешно, процесс направляет на стандартное устройство вьшода количество семафоров, содержащихся в наборе. Посредством еще одного вызова semcti



процесс устанавливает UID владельца набора равным UID процесса. Наконец, вызвав semctl в третий раз, процесс удаляет набор.

finclude <iostream.h> finclude <stdio.h> finclude <unistd.h> finclude <sys/ipc.h> finclude <sys/sein.h>

union semun { int val;

struct seinid ds *mbuf; ushort *array; } arg;

int mainO (

struct semid ds mbuf;

arg.mbuf = Smbuf;

int fd = semget (100, 0, 0);

if (fd>0 && semctl(fd,0, IPCSTAT, arg)) {

cout fsemaphores in the set arg.mbuf->sem nsems endl;

arg.mbuf->sem perm.uid = getuidO; изменить UID владельца , , if (semctl(fd,0,IPC SET,arg)==-1) perror( semctl );

else perror( semctl ) ;

if (semctl(fd,0,IPC RMID,0)) perror( semctl - IPC RMlD )j return 0;

10.6. Семафоры POSIX.lb

Семафоры POSIX.lb создаются и обрабатываются приблизительно так же, как семафоры UNIX System V. В частности, в стандарте POSIX.lb определяются заголовок <semaphore.h> и следующий набор API:

#include <semaphore.h>

sem t sem open ( char* name, int flags, mode t mode, unsigned init value );

int semjnit ( sem t* addr, int pshared, unsigned init value);

int sem getvalue ( sem t* idp, int* valuep );

int sem close ( sem t* idp );

int sem destroy ( sem t* id );

int semjunlink ( char* name );

int semjwait ( sem t* idp );

int sem trywait ( sem t* idp );

int sem post ( sem t* idp );

Семафоры POSIX. lb отличаются от семафоров UNIX System V следующим:

Семафоры POSIX.lb либо обозначаются путевым UNIX-именем (если создаются с помощью semjopen), либо остаются безымянными (но с присвоением начального виртуального адреса, если они создаются посредством вызова функции semjnit). Напомним, что семафоры System V обозначаются целочисленным ключом.

В POSIX.lb с каждым вызовом sem ppen и semjnit создается один семафор, тогда как каждый вызов semget в System V позволяет создать несколько семафоров.

Значение семафора POSIX. lb увеличивается и уменьщается на единицу с каждь ! вызовом semjpost и sem wait соответственно. В UNIX System V пользователи могут увеличивать и уменьшать значения семафоров на любую целую величину с каждым вызовом semop.

Функция sem open создает семафор, имя которого задано аргументом пате. Синтаксис аргумента пате такой же, как в сообщениях POSIX.lb. Значение аргумента flags может быть равно нулю, если функции известно, что указанный семафор уже существует. Флаг 0 CREAT показьгеает, что следует создать семафор с заданным именем. Вместе с этим флагом можно указывать флаг 0 EXCL, который заставляет функцию возвращать код неудачного завершения, если семафор с заданным именем уже существует. Аргументы mode и init value используются при создании нового семафора. Значение аргумента mode - это права доступа на чтение и запись для владельца, группы и прочих пользователей, которые должны быть установлены для нового семафора. Аргумент init value задает значение, которое должно бьггь присвоено семафору. Тип этого аргумента - целое без знака.

В случае успешного выполнения рассматриваемая функция возвращает указатель на структуру типа semj, а в случае неудачи - 1.

Функция semjnit - альтернатива функции sem open. Процесс, использующий semjnit, сначала вьщеляет область памяти для создаваемого семафора. Эта область памяти может бьггь разделяемой, если к семафору должны обращаться другие процессы. Адрес этой области передается как значение в аргумент addr функции semjnit. Аргумент pshared имеет значение 1, если семафор должен использоваться несколькими процессами совместно. В противном случае значение этого аргумента - 0. Аргумент init value содержит целое значение, которое должно бьггь присвоено семафору как начальное. Это значение не должно быть отрицательным числом.

В случае успешного выполнения данная функция возвращает О, а в случае неудачи -1.

Функция sem getvalue позволяет определить текущее значение семафора, указанного аргументом idp. Это значение передается с помощью аргумента valuep. В случае успешного вьшолнения данная функция возвращает О, а в случае неудачи--1.

Функция sem ;>oj/увеличивает значение семафора на единицу, а функция Jem wa;7 уменьшает его на единицу. Семафор в обеих функциях обозначается



аргументом idp. Если его значение уже равно нулю, функция semwait блокирует вызывающий процесс до тех пор, пока не будут созданы условия для его успешного продолжения. Функция semjrywait похожа на semjwait, но она неблокирующая и возвращает -1 (если не может уменьшить указанное значение семафора).

Функции sem close и semunlink используются с семафорами, созданными функцией sem open. Первая из этих функций отсоединяет семафор от процесса, а вторая - удаляет его из системы.

Функция sem destroy используется с семафорами, созданными функцией semjnit. Она удаляет семафор из системы.

В случае успешного выполнения функции sem post, semwait, semjtrywait, sem close, sem unlink и semdestroy возвращают 0, a в случае неудачи--1.

В приведенной ниже программе testsemp. С создается набор семафоров с именем /sem.О, который инициализируется значением 1. Если семафор создается нормально, процесс выполняет функцию semjwait, которая уменьшает значение семафора до нуля, а затем функцию sem post, которая вновь увеличивает его значение до единицы. Наконец, процесс закрывает указатель семафора с помощью функции sem close и удаляет его из системы посредством вызова функции semjinlink.

♦include <stdio.h> ♦include <sys/stat.h> ♦include <semaphore.h>

int main() {

sem t *semp = sem open( /sem.0 , if (semp==(sem t*)-1) if (sem wait(semp)==-1) if (sem post(semp)==-1) if (sem close(semp)==-1) if (sem unlink( /sem.O ) == -1) return 0;

0 CREAT, S IRWXU, 1);

(perror( sem open ); return -1;}

perror( sem wait );

perror( sem post );

perror( sem close );

perror( sem unlink );

В следующем примере, test semp2.C, с помощью функции semjnit семафор размещается по адресу, полученному процессом с помощью функции malloc. Этот семафор задается как неразделяемый (pshare = 0),а его начальное значение устанавливается равным единице. Если он создается нормально, то вызывается API sem getvalue для получения текущего значения и процесс направляет это значение на стандартное устройство вывода. Наконец, семафор удаляется из системы с помощью API semjestroy.

♦include <iostream.h> ♦include <stdio.h> ♦include <malloc.h> ♦include <semaphore.h>

int mainO

int val;

sem t *semp = (sem t*)malloc(sizeof(sem t)); if (!semp) { perror ( malloc ); return 1; }

if (sem init (semp, 0, 1 )==-l) { perror( sem init ); return 2; } if (sem getvalue(semp, &val)==0)

cout << semaphore value: val << endl; if (sem destroy(semp) == -1) perror( sem destroy ); return 0;

10.7. Разделяемая память в UNIX System V

Разделяемая память позволяет множеству процессов отображать часть своих виртуальных адресов в общую область памяти. Благодаря этому любой процесс может записывать данные в разделяемую область памяти, и эти данные будут доступны для чтения и модификации другим процессам.

Разделяемая память была задумана как средство повышения производительности при обработке сообщений. Дело в том, что при передаче сообщения из процесса в очередь сообщений данные копируются из виртуального адресного пространства процесса в область данных ядра. Затем, когда другой процесс принимает это сообщение, ядро копирует данные сообщения из своей области в виртуальное адресное пространство процесса-получателя. Таким образом, содержащиеся в сообщении данные копируются дважды: вначале из процесса в ядро, а затем в другой процесс. При наличии разделяемой памяти такие дополнительные издержки отсутствуют: эта память выделяется в виртуальном адресном пространстве ядра всякий раз, когда процессу необходимо записывать данные. Они обрабатываются непосредственно в области памяти ядра. При этом, однако, в разделяемой памяти не предусмотрены какие-либо методы управления доступом для процессов, которые ею пользуются. Поэтому среда межпроцессного взаимодействия формируется, как правило, путем использования разделяемой памяти и семафоров.

Процесс, подсоединившийся к разделяемой области памяти, получает указатель на эту разделяемую память. Им можно пользоваться так, как будто он получен в результате вызова функции динамического распределения памяти (т.е. с помощью функции new). Единственное различие состоит в том, что данные в разделяемой памяти не исчезают, даже если процесс, создавший разделяемую область, завершается.

В любой момент времени в системе может существовать множество разделяемых областей памяти.

10.7.1. Поддержка разделяемой памяти ядром UNIX

В UNIX System V.3 и V.4 в адресном пространстве ядра имеется таблица разделяемой памяти, в которой отслеживаются все разделяемые области



1 ... 51 52 53 [ 54 ] 55 56 57 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика