/* Программа иллюстрирует
возможности системного вызова semctl()
(управление семафорами) */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define MAXSETSIZE 25
main ()
{
extern int errno;
struct semid_ds semid_ds;
int length, rtrn, i, c;
int semid, semnum, cmd, choice;
union semun {
int val;
struct semid_ds *buf;
ushort array [MAXSETSIZE];
} arg;
/* Инициализация указателя на структуру данных */
arg.buf = &semid_ds;
/* Ввести идентификатор множества семафоров */
printf ("Введите ид-р множества семафоров: ");
scanf ("%d", &semid);
/* Выбрать требуемое управляющее действие */
printf ("\nВведите номер требуемого действия:\n");
printf (" GETVAL = 1\n");
printf (" SETVAL = 2\n");
printf (" GETPID = 3\n");
printf (" GETNCNT = 4\n");
printf (" GETZCNT = 5\n");
printf (" GETALL = 6\n");
printf (" SETALL = 7\n");
printf (" IPC_STAT = 8\n");
printf (" IPC_SET = 9\n");
printf (" IPC_RMID = 10\n");
printf (" Выбор = ");
scanf ("%d", &cmd);
/* Проверить значения */
printf ("идентификатор = %d, команда = %d\n",
semid, cmd);
/* Сформировать аргументы и выполнить вызов */
switch (cmd) {
case 1: /* Получить значение */
printf ("\nВведите номер семафора: ");
scanf ("%d", &semnum);
/* Выполнить системный вызов */
rtrn = semctl (semid, semnum, GETVAL, 0);
printf ("\nЗначение семафора = %d\n", rtrn);
break;
case 2: /* Установить значение */
printf ("\nВведите номер семафора: ");
scanf ("%d", &semnum);
printf ("\nВведите значение: ");
scanf ("%d", &arg.val);
/* Выполнить системный вызов */
rtrn = semctl (semid, semnum, SETVAL, arg.val);
break;
case 3: /* Получить ид-р процесса */
rtrn = semctl (semid, 0, GETPID, 0);
printf ("\Последнюю операцию выполнил: %d\n",rtrn);
break;
case 4: /* Получить число процессов, ожидающих
увеличения значения семафора */
printf ("\nВведите номер семафора: ");
scanf ("%d", &semnum);
/* Выполнить системный вызов */
rtrn = semctl (semid, semnum, GETNCNT, 0);
printf ("\nЧисло процессов = %d\n", rtrn);
break;
case 5: /* Получить число процессов, ожидающих
обнуления значения семафора */
printf ("Введите номер семафора: ");
scanf ("%d", &semnum);
/* Выполнить системный вызов */
rtrn = semctl (semid, semnum, GETZCNT, 0
printf ("\nЧисло процессов = %d\n", rtrn);
break;
case 6: /* Опросить все семафоры */
/* Определить число семафоров в множестве */
rtrn = semctl (semid, 0, IPC_STAT, arg.buf);
length = arg.buf->sem_nsems;
if (rtrn == -1)
goto ERROR;
/* Получить и вывести значения всех
семафоров в указанном множестве */
rtrn = semctl (semid, 0, GETALL, arg.array);
for (i = 0; i < length; i++)
printf (" %d", arg.array [i]);
break;
case 7: /* Установить все семафоры */
/* Определить число семафоров в множестве */
rtrn = semctl (semid, 0, IPC_STAT, arg.buf);
length = arg.buf->sem_nsems;
if (rtrn == -1)
goto ERROR;
printf ("\nЧисло семафоров = %d\n", length);
/* Установить значения семафоров множества */
printf ("\nВведите значения:\n");
for (i = 0; i < length; i++)
scanf ("%d", &arg.array [i]);
/* Выполнить системный вызов */
rtrn = semctl (semid, 0, SETALL, arg.array);
break;
case 8: /* Опросить состояние множества */
rtrn = semctl (semid, 0, IPC_STAT, arg.buf);
printf ("\nИдентификатор пользователя = %d\n",
arg.buf->sem_perm.uid
printf ("Идентификатор группы = %d\n",
arg.buf->sem_perm.gid);
printf ("Права на операции = 0%o\n",
arg.buf->sem_perm.mode);
printf ("Число семафоров в множестве = %d\n",
arg.buf->sem_nsems);
printf ("Время последней операции = %d\n",
arg.buf->sem_otime);
printf ("Время последнего изменения = %d\n",
arg.buf->sem_ctime);
break;
case 9: /* Выбрать и изменить поле
ассоциированной структуры данных */
/* Опросить текущее состояние */
rtrn = semctl (semid, 0, IPC_STAT, arg.buf);
if (rtrn == -1)
goto ERROR;
printf ("\nВведите номер поля, ");
printf ("которое нужно изменить: \n");
printf (" sem_perm.uid = 1\n");
printf (" sem_perm.gid = 2\n");
printf (" sem_perm.mode = 3\n");
printf (" Выбор = ");
scanf ("%d", &choice);
switch (choice) {
case 1: /* Изменить ид-р владельца */
printf ("\nВведите ид-р владельца: ");
scanf ("%d", &arg.buf->sem_perm.uid);
printf ("\nИд-р владельца = %d\n",
arg.buf->sem_perm.uid);
break;
case 2: /* Изменить ид-р группы */
printf ("\nВведите ид-р группы = ");
scanf ("%d", &arg.buf->sem_perm.gid);
printf ("\nИд-р группы = %d\n",
arg.buf->sem_perm.uid);
break;
case 3: /* Изменить права на операции */
printf ("\nВведите восьмеричный код прав: ");
scanf ("%o", &arg.buf->sem_perm.mode);
printf ("\nПрава = 0%o\n",
arg.buf->sem_perm.mode);
break;
}
/* Внести изменения */
rtrn = semctl (semid, 0, IPC_SET, arg.buf);
break;
case 10: /* Удалить ид-р множества семафоров и
ассоциированную структуру данных */
rtrn = semctl (semid, 0, IPC_RMID, 0);
}
if (rtrn == -1) {
/* Сообщить о неудачном завершении */
ERROR:
printf ("\nsemctl завершился неудачей!\n");
printf ("\nКод ошибки = %d\n", errno);
}
else {
printf ("\nmsgctl завершился успешно,\n");
printf ("идентификатор semid = %d\n", semid);
}
exit (0);
}
/* Программа иллюстрирует
возможности системного вызова semop()
(операции над множеством семафоров) */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define MAXOPSIZE 10
main ()
{
extern int errno;
struct sembuf sops [MAXOPSIZE];
int semid, flags, i, rtrn;
unsigned nsops;
/* Ввести идентификатор множества семафоров */
printf ("\nВведите идентификатор множества семафоров,");
printf ("\nнад которым будут выполняться операции: ");
scanf ("%d", &semid);
printf ("\nИд-р множества семафоров = %d", semid);
/* Ввести число операций */
printf ("\nВведите число операций ");
printf ("над семафорами из этого множества: \n");
scanf ("%d", &nsops);
printf ("\nЧисло операций = %d", nsops);
/* Инициализировать массив операций */
for (i = 0; i < nsops; i++) {
/* Выбрать семафор из множества */
printf ("\nВведите номер семафора: ");
scanf ("%d", &sops [i].sem_num);
printf ("\nНомер = %d", sops [i].sem_num);
/* Ввести число, задающее операцию */
printf ("\nЗадайте операцию над семафором: ");
scanf ("%d", &sops [i].sem_op);
printf ("\nОперация = %d", sops [i].sem_op);
/* Указать требуемые флаги */
printf ("\nВведите код, ");
printf ("соответствующий требуемым флагам:\n");
printf (" Нет флагов = 0\n");
printf (" IPC_NOWAIT = 1\n");
printf (" SEM_UNDO = 2\n");
printf (" IPC_NOWAIT и SEM_UNDO = 3\n");
printf (" Выбор = ");
scanf ("%d", &flags);
switch (flags) {
case 0:
sops [i].sem_flg = 0;
break;
case 1:
sops [i].sem_flg = IPC_NOWAIT;
break;
case 2:
sops [i].sem_flg = SEM_UNDO;
break;
case 3:
sops [i].sem_flg = IPC_NOWAIT | SEM_UNDO;
break;
}
printf ("\nФлаги = 0%o", sops [i].sem_flg);
}
/* Распечатать все структуры массива */
printf ("\nМассив операций:\n");
for (i = 0; i < nsops; i++) {
printf (" Номер семафора = %d\n", sops [i].sem_num);
printf (" Операция = %d\n", sops [i].sem_op);
printf (" Флаги = 0%o\n", sops [i].sem_flg);
}
/* Выполнить системный вызов */
rtrn = semop (semid, sops, nsops);
if (rtrn == -1) {
printf ("\nsemop завершился неудачей!\n");
printf ("Код ошибки = %d\n", errno);
}
else {
printf ("\nsemop завершился успешно.\n");
printf ("Идентификатор semid = %d\n", semid);
printf ("Возвращенное значение = %d\n", rtrn);
}
exit (0);
}