Нейл Мэтью - Основы программирования в Linux
- Название:Основы программирования в Linux
- Автор:
- Жанр:
- Издательство:«БХВ-Петербург»
- Год:2009
- Город:Санкт-Петербург
- ISBN:978-5-9775-0289-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Нейл Мэтью - Основы программирования в Linux краткое содержание
В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стандартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым.
Для начинающих Linux-программистов
Основы программирования в Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
□ IPC_RMID
— применяется для удаления идентификатора семафора, когда он больше не нужен.
Функция semctl
возвращает разные значения, зависящие от параметра command
. Если значение команды — IPC_RMID
, функция в случае успешного завершения вернет 0 и -1 в противном случае.
Применение семафоров
Как видно из содержания предыдущих разделов, операции с семафорами могут быть очень сложными. Это не самое печальное, потому что программирование многих процессов или потоков с критическими секциями — очень трудная задача сама по себе, и наличие сложного программного интерфейса лишь увеличивает интеллектуальную нагрузку.
К счастью, большинство задач, нуждающихся в семафорах, можно решить, применяя единственный бинарный семафор — простейший тип семафора. В следующем примере (упражнение 14.1) вы используете полный программный интерфейс для создания очень простого интерфейса типа Р и V для бинарного семафора. Затем вы примените этот простенький интерфейс для демонстрации того, как функционируют семафоры.
В экспериментах с семафорами будет использоваться единственная программа sem1.с, которую вы сможете запускать несколько раз. Необязательный параметр будет применяться для того, чтобы показать, отвечает ли программа за создание и уничтожение семафора.
Вывод двух разных символов будет обозначать вход в критическую секцию и выход из нее. Программа, запущенная с параметром, выводит X
при входе в критическую секцию и выходе из нее. Другие экземпляры запущенной программы будут выводить символ О
при входе в свои критические секции и выходе из них. Поскольку в любой заданный момент времени только один процесс способен войти в свою критическую секцию, все символы X
и O
должны появляться парами.
1. После системных директив #include
вы включаете файл semun.h. Он определяет объединение типа semun
в соответствии со стандартом X/Open, если оно уже не описано в системном файле sys/sem.h. Далее следуют прототипы функций и глобальная переменная, расположенные перед входом в функцию main
. В ней создается семафор с помощью вызова semget
, который возвращает ID семафора. Если программа вызывается первый раз (т.е. вызывается с параметром и argc > 1
), выполняется вызов set_semvalue
для инициализации семафора и переменной op_char
присваивается значение O
.
#include
#include
#include
#include
#include "semun.h"
static int set_semvalue(void);
static void del_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);
static int sem_id;
int main(int argc, char *argv[]) {
int i;
int pause_time;
char op_char = 'О';
srand((unsigned int)getpid());
sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);
if (argc >1) {
if (!set_semvalue()) {
fprintf(stderr, "Failed to initialize semaphore\n");
exit(EXIT_FAILURE);
}
op_char = 'X';
sleep(2);
}
2. Далее следует цикл, в котором 10 раз выполняется вход в критическую секцию и выход из нее. Вы сначала выполняете вызов функции semaphore_p
, которая заставляет семафор ждать, когда эта программа будет готова войти в критическую секцию.
for (i = 0; i < 10; i++) {
if (!semaphore_p()) exit(EXIT_FAILURE);
printf("%c", op_char);
fflush(stdout);
pause_time = rand() % 3;
sleep(pause_time);
printf("%c", op_char);
fflush(stdout);
3. После критической секции вы вызываете функцию semaphore_v
, которая освобождает семафор перед повторным проходом цикла for
после ожидания в течение случайного промежутка времени. После цикла выполняется вызов функции del_semvalue
для очистки кода.
if (!semaphore_v()) exit(EXIT_FAILURE);
pause_time = rand() % 2;
sleep(pause_time);
}
printf("\n%d - finished\n", getpid());
if (argc > 1) {
sleep(10);
del_semvalue();
}
exit(EXIT_SUCCESS);
}
4. Функция set_semvalue
инициализирует семафор с помощью команды SETVAL
в вызове semctl
. Это следует сделать перед использованием семафора.
static int set_semvalue(void) {
union semun sem_union;
sem_union.val = 1;
if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);
return(1);
}
5. У функции del_semvalue
почти та же форма за исключением того, что в вызове semctl
применяется команда IPC_RMID
для удаления ID семафора.
static void del_semvalue(void) {
union semun sem_union;
if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
fprintf(stderr, "Failed to delete semaphore\n");
}
6. Функция semaphore_p изменяет счетчик семафора на -1. Это операция ожидания или приостановки процесса.
static int semaphore_p(void) {
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; /* P() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_p failed\n");
return(0);
}
return(1);
}
7. Функция semaphore_v
аналогична за исключением задания элемента sem_op
структуры sembuf
, равного 1. Это операция "освобождения", в результате которой семафор снова становится доступен.
static int semaphore_v(void) {
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; /* V() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_v failed\n");
return(0);
}
return(1);
}
Обратите внимание на то, что эта простая программа разрешает существование единственного двоичного семафора для каждой программы, хотя можно было бы увеличить количество, передав переменную семафора при необходимости. Обычно одного бинарного семафора достаточно.
Вы можете протестировать вашу программу, запустив ее несколько раз. В первый раз вы передадите параметр, чтобы сообщить программе о том, что она отвечает за создание и удаление семафора. У других экземпляров выполняющейся программы не будет параметра.
Далее приведен примерный вывод для двух запущенных экземпляров программы:
$ cc sem1.с -о sem1
$ ./sem1 1 &
[1] 1082
$ ./sem1
OOXXOOXXOOXXOOXXOOXXOOOOXXOOXXOOXXOOXXXX
1083 - finished
1082 - finished
Напоминаем, что символ О
представляет первый запущенный экземпляр программы, а символ X
— второй экземпляр выполняющейся программы. Поскольку каждый экземпляр программы выводит символ при входе в критическую секцию и при выходе из нее, каждый символ должен появляться только попарно. Как видите, символы О
и Х
на самом деле образуют пары, указывая на корректную обработку критических секций. Если программа не работает на вашей системе, можно применить команду stty -tostop
перед запуском программы, чтобы гарантировать, что фоновая программа, генерирующая вывод на tty
, не вызывает возбуждение сигнала.
Интервал:
Закладка: