Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MET_VS~2.DOC
Скачиваний:
0
Добавлен:
10.11.2019
Размер:
271.87 Кб
Скачать

Програма 5.1

Після закінчення роботи з програмою 5.1 необхідно використовувати стандартні механізми Unix маніпуляцій з чергами rpcs, ipcrm (роздрук 5.1).

Наступна програма є більш "інтелектуальною" по відно­шенню до попередньої і демонструє розширені маніпуляції з чергами, які складаються з відкриття черги, записом та отриманням повідомлень, їх знищенням, зміною параметрів доступу до черги за допомогою програмного шляху:

  1. #include <stdio.h>

  2. #include <stdlib.h>

  3. #include <ctype.h>

  4. #include <sys/types.h>

  5. #include <sys/ipc.h>

  6. #include <sys/msg.h>

  7. #define MAX_SEND_SIZE 80

  8. struct mymsgbuf {

  9. long mtype;

  10. char mtext[MAX_SEND_SIZE];

  11. };

  12. void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text);

  13. void read_message(int qid, struct mymsgbuf *qbuf, long type);

  14. void remove_queue(int qid);

  15. void change_queue_mode(int qid, char *mode);

  16. void usage(void);

  17. int main(int argc, char *argv[])

  18. {

  19. key_t key;

  20. int msgqueue_id;

  21. struct mymsgbuf qbuf;

  22. if(argc == 1)

  23. usage();

  24. key = ftok(".", 'm');

  25. if((msgqueue_id = msgget(key, IPC_CREAT|0660)) == -1) {

  26. perror("msgget");

  27. exit(1);

  28. }

  29. switch(tolower(argv[1][0]))

  30. {

  31. case 's': send_message(msgqueue_id, (struct mymsgbuf *)&qbuf,

  32. atol(argv[2]), argv[3]);

  33. break;

  34. case 'r': read_message(msgqueue_id, &qbuf, atol(argv[2]));

  35. break;

  36. case 'd': remove_queue(msgqueue_id);

  37. break;

  38. case 'm': change_queue_mode(msgqueue_id, argv[2]);

  39. break;

  40. default: usage();

  41. return(0);

  42. }

  43. void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text)

  44. {

  45. printf("Sending a message ...\n");

  46. qbuf->mtype = type;

  47. strcpy(qbuf->mtext, text);

  48. if((msgsnd(qid, (struct msgbuf *)qbuf,

  49. strlen(qbuf->mtext)+1, 0)) ==-1)

  50. {

  51. perror("msgsnd");

  52. exit(1);

  53. }

  54. }

  55. void read_message(int qid, struct mymsgbuf *qbuf, long type)

  56. {

  57. printf("Reading a message ...\n");

  58. qbuf->mtype = type;

  59. msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0);

  60. printf("Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);

  61. }

  62. void remove_queue(int qid)

  63. {

  64. msgctl(qid, IPC_RMID, 0);

  65. }

  66. void change_queue_mode(int qid, char *mode)

  67. {

  68. struct msqid_ds myqueue_ds;

  69. msgctl(qid, IPC_STAT, &myqueue_ds);

  70. sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);

  71. msgctl(qid, IPC_SET, &myqueue_ds);

  72. }

  73. void usage(void)

  74. {

  75. fprintf(stderr, "msgtool - A utility for tinkering with msg queues\n");

  76. fprintf(stderr, "\nUSAGE: msgtool (s)end <type> <messagetext>\n");

  77. fprintf(stderr, " (r)ecv <type>\n");

  78. fprintf(stderr, " (d)elete\n");

  79. fprintf(stderr, " (m)ode <octal mode>\n");

  80. exit(1);

  81. }

Програма 5.2

Як параметри програми для запису повідомлень слід задавати поля:

$ prog5_2 s 1 Message_text_1

$ prog5_2 s 2 Message_text_2

………

$ prog5_2 s n Message_text_n

Для читання повідомлення задається опція r з номером черги:

$ prog5_2 r 1,

де користувач по даному прикладу отримує таке пові­домлення:

Type: 1 Text: Message_1

Для вилучення всіх повідомлень з черги користувач повинен задати команду:

$ prog5_2 d

В деяких випадках є необхідність спостереження за роботою програм, які складають міжпроцесні (ipc, inter process communication) комунікації. Для цього існує команда з опціями:

ipcs -q - стеження за викликами повідомлень,

ipcs -s - стеження за викликами семафорів;

ipcs -m - стеження за викликами поділяючої пам'яті.

Вилучити повідомлення з черги можна за допомогою команди ipcrm з опцією msg та ідентифікаційним номером черги. Роздрук 5.1 демонструє роботу команд ipcs та ipcrm з програмою 5.1:

login: hoshaba

Password:

Last login: Thu Feb 12 18:10:06 on tty2

[root@lili hoshaba]# cd test/

[root@lili test]# ls

exampl~1.txt prog1 prog1.c prog2 prog2.c

[root@lili test]# ipcs -q

------ Message Queues --------

key msqid owner perms used-bytes messages

0x00000000 0 root 700 0 0

[root@lili test]# ./prog1

[root@lili test]# ipcs -q

------ Message Queues --------

key msqid owner perms used-bytes messages

0x00000000 0 root 700 0 0

0x6d030811 129 root 660 12 1

[root@lili test]# ipcrm msg 129

resource deleted

[root@lili test]# ipcs -q

------ Message Queues --------

key msqid owner perms used-bytes messages

0x00000000 0 root 700 0 0

[root@lili test]# exit

logout

Роздрук 5.1

Контрольні питання

  1. Назвіть відмінності між програмними каналами та чергами повідомлень.

  2. Назвіть переваги черг повідомлень перед програмними каналами.

  3. Назвіть функції роботи з чергами, їх призначення.

  4. У програмі 5.2 визначіть основні блоки: відкриття черги, запис та отримання повідомлень, їх знищення, зміна параметрів доступу до черги.

  5. Назвіть команди спостереження за роботою міжпроцесних комунікацій (ipcs, ipcrm). Їх функції та робота.

  6. Поясніть призначення та роботу функції sizeof у рядку 41 програми 5.1.

  7. Поясніть призначення та роботу функції atol у рядку 33 програми 5.2.

Завдання

  1. Одержати та відкомпілювати програму 5.1. Запам'ятати попередні значення системи черг. Виконати програму 5.1. і записати значення системи черг. Вилучити наслідки роботи програми з чергами повідомлень за допомогою команди ipcrm;

  2. Одержати та відкомпілювати програму 5.2. Записати декілька повідомлень до черги, отримати їх та знищити чергу.

  3. Підготувати звіт по лабораторній роботі.

Зміст звіту:

  • короткі відповіді на контрольні питання;

  • призначення програми 5.1 та 5.2;

  • алгоритм і текст програми 5.1 та 5.2.

Лабораторна робота №6

Робота з семафорами

Мета роботи: ознайомити з семафорами та маніпуляціями над ними.

Загальні відомості

Семафори є досить потужними засобами синхронізації процесів. Вони дуже потрібні у випадках, коли існують критичні ресурси з кожним з яких у певну годину може працювати тільки один процес. В цьому випадку процес може захоплювати критичний ресурс і в певний момент часу його звільнювати.

Для керуванням подібним доступом до критичних ресурсів семафори використовують цілі числа або масиви цілих чисел, з якими припустимі тільки дві атомарні (неподільні) операції.

Семафори завжди працюють як засоби затримки процесів, котрі гальмують чи "засинають" на світлофорах та "проки­даються" чи переходять до руху при зміні стану світлофора.

Таким чином, дескриптор семафора є інформаційною керуючою структурою ipc-perm, інформація про яку збері­гається у файлі <sys/ipc.h>.

Будь-який процес може створити семафор за допомогою функції semget. При успішному використанні функції semget повертається змінна semid, що є ідентифікатором створеного чи вже існуючого семафора.

Після створення семафора будь-який процес, котрий знає його ідентифікатор, може на нього впливати за допомогою системного виклика semctl. В даному випадку він здійснює надбудову та перевірку стану множинного семафору.

Семафор також є засобом реєстрації деякої події (подій) в системі. У виявлені таких подій повідомляють процеси, які використовують системний виклик semop, що приводить до зміни поточних значень семафору.

Процес, який виконує системний виклик semop, повинен використовувати поле sem_op в структурі sembuf, що в ній знахо­диться необхідна операція:

struct sembuf {

ushort sem_num; // номер елемента семафора

short sem_op; // значення конкретної дії над

// семафором

short sem_flg; // прапорці

}

Розрізняють три типи операцій:

  1. sem_op > 0 - процес звільнення, який контролює поточний елемент семафора. Значення елементу семафора semval інкрементується (збільшується) на величину sem_op.

  2. sem_op = 0 - процес, який виконав такий виклик sem_op, буде переведений в очікування до тих пір, поки не звільниться ресурс (semval не буде дорівнювати нулю).

  3. sem_op < 0 - процес, який викликав виконання даної операції, очікує до тих пір, поки sem_op не стане більше чи дорівнюватиме значенню semval. У даному випадку відбувається декремент (зменьшення) поточного значення семафора на абсолютну величину sem_op. Ця операція використовується при захопленні ресурсу.

При реалізації механізмів семафорів припустимо вико­ристовувати спеціальні прапорці, наприклад IPC_NOWAIT, котрі інформують ядро про небажання процесу переходити до стану очіку­вання, не дивлячись на "червоне" світло семафора. Насамперед, бувають випадки, коли з тієї чи іншої причини процес, який захопив ресурс, раптом аварійно завершився або достроково одержав сигнал закінчення. Оскільки цей сигнал неможливо перехопити, то "загинувший" процес неспроможний нічого вдіяти для звільнення ресурсу семафора.

Приклад 6.1 показує можливі маніпуляції з чергами, які можна здійснити програмним шляхом.

  1. #include <stdio.h>

  2. #include <ctype.h>

  3. #include <stdlib.h>

  4. #include <sys/types.h>

  5. #include <sys/ipc.h>

  6. #include <sys/sem.h>

  7. #define SEM_RESOURCE_MAX

  8. void opensem(int *sid, key_t key);

  9. void createsem(int *sid, key_t key, int members);

  10. void locksem(int sid, int member);

  11. void unlocksem(int sid, int member);

  12. void removesem(int sid);

  13. unsigned short get_member_count(int sid);

  14. int getval(int sid, int member);

  15. void dispval(int sid, int member);

  16. void changemode(int sid, char *mode);

  17. void usage(void);

  18. int main(int argc, char *argv[])

  19. {

  20. key_t key;

  21. int semset_id;

  22. if(argc == 1)

  23. usage();

  24. key = ftok(".", 's');

  25. switch(tolower(argv[1][0]))

  26. {

  27. case 'c': if(argc != 3)

  28. usage();

  29. createsem(&semset_id, key, atoi(argv[2]));

  30. break;

  31. case 'l': if(argc != 3)

  32. usage();

  33. opensem(&semset_id, key);

  34. locksem(semset_id, atoi(argv[2]));

  35. break;

  36. case 'u': if(argc != 3)

  37. usage();

  38. opensem(&semset_id, key);

  39. unlocksem(semset_id, atoi(argv[2]));

  40. break;

  41. case 'd': opensem(&semset_id, key);

  42. removesem(semset_id);

  43. break;

  44. case 'm': opensem(&semset_id, key);

  45. changemode(semset_id, argv[2]);

  46. break;

  47. default: usage();

  48. }

  49. return(0);

  50. }

  51. void opensem(int *sid, key_t key)

  52. {

  53. if((*sid = semget(key, 0, 0666)) == -1)

  54. {

  55. printf("Semaphore set does not exist!\n");

  56. exit(1);

  57. }

  58. }

  59. void createsem(int *sid, key_t key, int members)

  60. {

  61. int cntr;

  62. union semun semopts;

  63. if(members > SEMMSL) {

  64. printf("Sorry, max number of semaphores in a set is %d\n",

  65. SEMMSL);

  66. exit(1);

  67. }

  68. printf("Attempting to create new semaphore set with %d members\n",

  69. members);

  70. if((*sid = semget(key, members, IPC_CREAT|IPC_EXCL|0666))

  71. == -1)

  72. {

  73. fprintf(stderr, "Semaphore set already exists!\n");

  74. exit(1);

  75. }

  76. semopts.val = SEM_RESOURCE_MAX;

  77. for(cntr=0; cntr<members; cntr++)

  78. semctl(*sid, cntr, SETVAL, semopts);

  79. }

  80. void locksem(int sid, int member)

  81. {

  82. struct sembuf sem_lock={ 0, -1, IPC_NOWAIT};

  83. if( member<0 || member>(get_member_count(sid)-1))

  84. {

  85. fprintf(stderr, "semaphore member %d out of range\n", member);

  86. return;

  87. }

  88. if(!getval(sid, member))

  89. {

  90. fprintf(stderr, "Semaphore resources exhausted (no lock)!\n");

  91. exit(1);

  92. }

  93. sem_lock.sem_num = member;

  94. if((semop(sid, &sem_lock, 1)) == -1)

  95. {

  96. fprintf(stderr, "Lock failed\n");

  97. exit(1);

  98. }

  99. else

  100. printf("Semaphore resources decremented by one (locked)\n");

  101. dispval(sid, member);

  102. }

  103. void unlocksem(int sid, int member)

  104. {

  105. struct sembuf sem_unlock={ member, 1, IPC_NOWAIT};

  106. int semval;

  107. if( member<0 || member>(get_member_count(sid)-1))

  108. {

  109. fprintf(stderr, "semaphore member %d out of range\n", member);

  110. return;

  111. }

  112. semval = getval(sid, member);

  113. if(semval == SEM_RESOURCE_MAX) {

  114. fprintf(stderr, "Semaphore not locked!\n");

  115. exit(1);

  116. }

  117. sem_unlock.sem_num = member;

  118. if((semop(sid, &sem_unlock, 1)) == -1)

  119. {

  120. fprintf(stderr, "Unlock failed\n");

  121. exit(1);

  122. }

  123. else

  124. printf("Semaphore resources incremented by one (unlocked)\n");

  125. dispval(sid, member);

  126. }

  127. void removesem(int sid)

  128. {

  129. semctl(sid, 0, IPC_RMID, 0);

  130. printf("Semaphore removed\n");

  131. }

  132. unsigned short get_member_count(int sid)

  133. {

  134. union semun semopts;

  135. struct semid_ds mysemds;

  136. semopts.buf = &mysemds;

  137. return(semopts.buf->sem_nsems);

  138. }

  139. int getval(int sid, int member)

  140. {

  141. int semval;

  142. semval = semctl(sid, member, GETVAL, 0);

  143. return(semval);

  144. }

  145. void changemode(int sid, char *mode)

  146. {

  147. int rc;

  148. union semun semopts;

  149. struct semid_ds mysemds;

  150. semopts.buf = &mysemds;

  151. rc = semctl(sid, 0, IPC_STAT, semopts);

  152. if (rc == -1) {

  153. perror("semctl");

  154. exit(1);

  155. }

  156. printf("Old permissions were %o\n", semopts.buf->sem_perm.mode);

  157. sscanf(mode, "%ho", &semopts.buf->sem_perm.mode);

  158. semctl(sid, 0, IPC_SET, semopts);

  159. printf("Updated...\n");

  160. }

  161. void dispval(int sid, int member)

  162. {

  163. int semval;

  164. semval = semctl(sid, member, GETVAL, 0);

  165. printf("semval for member %d is %d\n", member, semval);

  166. }

  167. void usage(void)

  168. {

  169. fprintf(stderr, "semtool - A utility for tinkering with semaphores\n");

  170. fprintf(stderr, "\nUSAGE: semtool4 (c)reate <semcount>\n");

  171. fprintf(stderr, " (l)ock <sem #>\n");

  172. fprintf(stderr, " (u)nlock <sem #>\n");

  173. fprintf(stderr, " (d)elete\n");

  174. fprintf(stderr, " (m)ode <mode>\n");

  175. exit(1);

  176. }

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]