Uploaded by d-1953

10

advertisement
МИНОБРНАУКИ РОССИИ
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ
ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА)
Кафедра ВТ
ОТЧЕТ
по лабораторной работе № 10
по дисциплине «Организация процессов и программирования Linux»
Тема: Синхронизация процессов с помощью семафоров
Студентка гр. 7308
Латышева В.А.
Преподаватель
Разумовский Г.В.
Санкт-Петербург
2020
Цель работы
Знакомство с организацией семафоров, системными функциями, обеспечивающими
управление семафорами, и их использованием для решения задач взаимоисключения и
синхронизации.
Первая работа
Текст программы
provider.cpp
#include <iostream>
#include <sys/sem.h>
#include <sys/shm.h>
#include <fstream>
#define BUFFER_SIZE 10
class cycleBuffer {
private:
char buffer[BUFFER_SIZE] = {'\0'};
int size = 0;
public:
bool empty() {
return size == 0;
}
void push(char symbol) {
++size;
for (int i = size; i > 0; --i) {
buffer[i] = buffer[i - 1];
}
buffer[0] = symbol;
}
char pop() {
char symbol = buffer[size];
buffer[size] = '\0';
if (size!= 0) size--;
return symbol;
}
};
void clear(cycleBuffer *cycleBuffer, int semID, int bufID) {
shmdt(cycleBuffer);
shmctl(bufID, IPC_RMID, 0);
semctl(semID, IPC_RMID, 0);
exit(-1);
}
int main() {
int bufKey = 2036, semKey = 2037;
int bufID = shmget(bufKey, sizeof(cycleBuffer), 0666 | IPC_CREAT);
if (bufID == -1){
std::cout << "Wasn't able to create buffer\n";
exit(-1);
}
cycleBuffer *cycleBuf = (cycleBuffer *)shmat(bufID, 0, 0);
int semID = semget(semKey, 4, 0666 | IPC_CREAT);
if (semID == -1){
std::cout << "Wasn't able to create semaphore\n";
exit(-1);
}
if (semctl(semID, 0, SETVAL, BUFFER_SIZE) == -1) { // buffer size for
provider
std::cout << "The first semaphore wasn't initialized\n";
clear(cycleBuf, semID, bufID);
}
if (semctl(semID, 1, SETVAL, 1) == -1) { // provider end work
std::cout << "The second semaphore wasn't initialized\n";
clear(cycleBuf, semID, bufID);
}
if (semctl(semID, 2, SETVAL, 1) == -1) { // customer end work
std::cout << "The third semaphore wasn't initialized\n";
clear(cycleBuf, semID, bufID);
}
if (semctl(semID, 3, SETVAL, 0) == -1) { // block access for buffer
std::cout << "The fourth semaphore wasn't initialized\n";
clear(cycleBuf, semID, bufID);
}
struct sembuf checkBuffer, accessBuffer[2], freeBuffer[2], endWork[2];
checkBuffer.sem_num = 0; // check if buffer is full
checkBuffer.sem_op = 0;
checkBuffer.sem_flg = IPC_NOWAIT;
accessBuffer[0].sem_num = 3; // check if buffer is busy
accessBuffer[0].sem_op = 0;
accessBuffer[1].sem_num = 3; // access buffer
accessBuffer[1].sem_op = 1;
freeBuffer[0].sem_num = 3; // free buffer
freeBuffer[0].sem_op = -1;
freeBuffer[1].sem_num = 0; // symbol was added to buffer
freeBuffer[1].sem_op = -1;
endWork[0].sem_num = 1; // provider is over
endWork[0].sem_op = -1;
endWork[1].sem_num = 2; // check if customer is over
endWork[1].sem_op = 0;
std::ifstream file("file.txt");
if(!file.is_open()){
std::cout << "Wasn't able to open the file\n";
clear(cycleBuf, semID, bufID);
}
char ch;
while(!file.eof()) {
if(semop(semID, &checkBuffer, 1) != -1) // check if buffer is full
continue;
semop(semID, accessBuffer, 2);
ch = file.get();
cycleBuf->push((char)ch);
semop(semID, freeBuffer, 2);
}
semop(semID, &endWork[0], 1); // provider is over
semop(semID, &endWork[1], 1); // check if customer is over
clear(cycleBuf, semID, bufID);
return 0;
}
customer.cpp
#include <iostream>
#include <sys/sem.h>
#include <sys/shm.h>
#define BUFFER_SIZE 10
class cycleBuffer {
private:
char buffer[BUFFER_SIZE] = {'\0'};
int size = 0;
public:
bool empty() {
return size == 0;
}
void push(char symbol) {
++size;
for (int i = size; i > 0; --i) {
buffer[i] = buffer[i - 1];
}
buffer[0] = symbol;
}
char pop() {
char symbol = buffer[size];
buffer[size] = '\0';
if (size!= 0) size--;
return symbol;
}
};
int main() {
int bufKey = 2036, semKey = 2037;
int bufID = shmget(bufKey, sizeof(cycleBuffer), 0666 | IPC_CREAT |
IPC_EXCL);
if (bufID != -1) {
std::cout << "Wasn't able to connect to buffer\n";
exit(-1);
}
else
bufID = shmget(bufKey, sizeof(cycleBuffer), 0666 | IPC_CREAT);
cycleBuffer *cycleBuf = (cycleBuffer *)shmat(bufID, 0, 0);
int semID = semget(semKey, 4, 0666 | IPC_CREAT | IPC_EXCL);
if (semID != -1) {
std::cout << "Wasn't able to connect to semaphore\n";
exit(-1);
}
else
semID = semget(semKey, 4, 0666 | IPC_CREAT);
struct sembuf accessBuffer[2], freeBuffer[2], endWork[2];
accessBuffer[0].sem_num = 3; // check if buffer is busy
accessBuffer[0].sem_op = 0;
accessBuffer[1].sem_num = 3; // access buffer
accessBuffer[1].sem_op = 1;
freeBuffer[0].sem_num = 3; // free buffer
freeBuffer[0].sem_op = -1;
freeBuffer[1].sem_num = 0; // symbol was removed from buffer
freeBuffer[1].sem_op = 1;
endWork[0].sem_num = 2; // customer is over
endWork[0].sem_op = -1;
endWork[1].sem_num = 1; // check if provider is over
endWork[1].sem_op = 0;
endWork[1].sem_flg = IPC_NOWAIT;
std::cout << "File content: \n";
while(semop(semID, &endWork[1], 1) == -1 || !cycleBuf->empty()) {
int x = semctl(semID, 0, GETVAL, 0);
if (semctl(semID, 0, GETVAL, 0) == BUFFER_SIZE)
continue;
semop(semID, accessBuffer, 2);
std::cout << cycleBuf->pop();
semop(semID, freeBuffer, 2);
}
std::cout << std::endl;
semop(semID, &endWork[0], 1); // customer is over
shmdt(cycleBuf);
return 0;
}
Результат работы программы
Вторая работа
Reader.cpp
#include <iostream>
#include <fstream>
#include <sys/sem.h>
#include <unistd.h>
int main (int argc, char **argv) {
int period = atoi(argv[1]);
int semID = semget(854, 3, IPC_CREAT | IPC_EXCL | 0666);
if (semID != -1) {
semctl(semID, 0, SETVAL, 1);
semctl(semID, 1, SETVAL, 0);
semctl(semID, 2, SETVAL, 0);
} else
semID = semget(854, 3, IPC_CREAT | 0666);
std::ifstream file("output.txt");
if (!file.is_open()) {
std::cout << "Error: file wasn't opened\n";
exit(-1);
}
struct sembuf addReader[1], removeReader[1], waitWriters[1];
addReader[0].sem_num = 2;
addReader[0].sem_op = 1;
removeReader[0].sem_num = 2;
removeReader[0].sem_op = -1;
waitWriters[0].sem_num = 1;
waitWriters[0].sem_op = 0;
semop(semID, waitWriters, 1);
semop(semID, addReader, 1);
std::string line;
while (!file.eof()) {
getline(file, line);
std::cout << line << std::endl;
sleep(period);
}
semop(semID, removeReader, 1);
file.close();
return 0;
}
Writer.cpp
#include <iostream>
#include <fstream>
#include <sys/sem.h>
#include <unistd.h>
int main (int argc, char **argv) {
int writerNumber = atoi(argv[1]);
int N = atoi(argv[2]);
int period = atoi(argv[3]);
int semID = semget(854, 3, IPC_CREAT | IPC_EXCL | 0666);
bool creator = false;
if (semID != -1) {
semctl(semID, 0, SETVAL, 1);
semctl(semID, 1, SETVAL, 0);
semctl(semID, 2, SETVAL, 0);
creator = true;
} else
semID = semget(854, 3, IPC_CREAT | 0666);
std::ofstream file("output.txt", std::ios::app);
if (!file.is_open()) {
std::cout << "Error: file wasn't opened\n";
exit(-1);
}
struct sembuf busyFile[1], freeFile[1], addWriter[1], removeWriter[1],
waitReaders[1];
busyFile[0].sem_num = 0;
busyFile[0].sem_op = -1;
freeFile[0].sem_num = 0;
freeFile[0].sem_op = 1;
addWriter[0].sem_num = 1;
addWriter[0].sem_op = 1;
removeWriter[0].sem_num = 1;
removeWriter[0].sem_op = -1;
waitReaders[0].sem_num = 2;
waitReaders[0].sem_op = 0;
for (int i = 0; i < N; ++i) {
semop(semID, addWriter, 1);
semop(semID, waitReaders, 1);
semop(semID, busyFile, 1);
file << "Writer " << writerNumber << std::endl;
std::cout << "Writer " << writerNumber << std::endl;
semop(semID, removeWriter, 1);
semop(semID, freeFile, 1);
sleep(period);
}
while (true)
if (semop(semID, waitReaders, 1) == 0)
break;
if (creator)
semctl(semID, IPC_RMID, 0);
file.close();
return 0;
}
Результаты работы
Download