Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Контрольная по ОС (вариант 8)

.doc
Скачиваний:
25
Добавлен:
01.04.2014
Размер:
53.25 Кб
Скачать

Задача

  1. Написать программу поиска одинаковых по их содержимому файлов в двух каталогов, например, Dir1 и Dir2. Пользователь задаёт имена Dir1 и Dir2. В результате работы программы файлы, имеющиеся в Dir1, сравниваются с файлами в Dir2 по их содержимому. Процедуры сравнения должны запускаться с использованием функции fork() в отдельном процессе для каждой пары сравниваемых файлов. Каждый процесс выводит на экран свой pid, имя файла, число просмотренных байт и результаты сравнения. Число запущенных процессов в любой момент времени не должно превышать N (вводится пользователем).Проверить работу программы для каталога /usr/include/ и любого другого каталога в /homeN=6.

Программный код

#include <iostream>

#include <string>

#include <vector>

#include <dirent.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <errno.h>

#include <semaphore.h>

#include <fstream>

using namespace std;

void compareFiles(string, string);

sem_t *semaphore;

int main()

{

string sDir1, sDir2;

unsigned int nProcess;

// Вводим входные данные

cout<<"Enter 1-th dir: ";

cin>>sDir1;

cout<<"Enter 2-th dir: ";

cin>>sDir2;

cout<<"Enter max process count: ";

cin>>nProcess;

// Создаем семафор

semaphore = sem_open("/search.0", O_CREAT, S_IRWXU, nProcess);

vector<string> aFiles1, aFiles2;

DIR *phDir;

// Открываем каталог 1 для чтения файлов

if((phDir = opendir(sDir1.c_str())) == NULL) {

cerr<<"Error("<<errno<<") opening "<<sDir1<<endl;

return errno;

}

// Читаем содержимое 1го каталога

struct dirent *pDirInner;

struct stat statv;

while ((pDirInner = readdir(phDir)) != NULL) {

// Составляем полное имя файла

string sFileName(sDir1);

sFileName += "/";

sFileName += pDirInner->d_name;

// Получаем информацию о файле

if (stat(sFileName.c_str(), &statv) == -1) {

cerr<<"Error getting file info '"<<sFileName.c_str()<<"'"<<endl;

return -1;

}

// Если найденный элемент файл, добавляем его в массив для сравнения

if ((statv.st_mode & S_IFMT) == S_IFREG) {

aFiles1.push_back(sFileName);

}

}

// Закрываем 1ый каталог

closedir(phDir);

// Открываем каталог 2 для чтения файлов

if((phDir = opendir(sDir2.c_str())) == NULL) {

cerr<<"Error("<<errno<<") opening "<<sDir2<<endl;

return errno;

}

// Читаем содержимое 2го каталога

while ((pDirInner = readdir(phDir)) != NULL) {

// Составляем полное имя файла

string sFileName(sDir2);

sFileName += "/";

sFileName += pDirInner->d_name;

// Получаем информацию о файле

if (stat(sFileName.c_str(), &statv) == -1) {

cerr<<"Error getting file info '"<<sFileName.c_str()<<"'"<<endl;

return -1;

}

// Если найденный элемент файл, добавляем его в массив для сравнения

if ((statv.st_mode & S_IFMT) == S_IFREG) {

aFiles2.push_back(sFileName);

}

}

// Закрываем 2ый каталог

closedir(phDir);

// Запускаем цикл сравнивания всех файлов 2х каталогов друг с другом

for (unsigned int i = 0; i < aFiles1.size(); i++) {

for (unsigned int j = 0; j < aFiles2.size(); j++) {

// Блокируем выполение программы, пока все семафоры заняты

int iSemValue;

do { sem_getvalue(semaphore, &iSemValue); } while (!iSemValue);

// Сравниваем 2 файла

compareFiles(aFiles1[i], aFiles2[j]);

}

}

// Блокируем выполнение программы, пока хотя бы один семафор занят

int iSemValue;

do { sem_getvalue(semaphore, &iSemValue); } while (iSemValue != nProcess);

// Уничтожаем семафор

sem_unlink("/search.0");

return 0;

}

void compareFiles(string sFile1, string sFile2)

{

// Создание нового процесса

pid_t pid;

pid = fork();

// Если произошла ошибка - выходим из процесса

if (pid == (pid_t)-1) {

cerr<<"Error during creation process"<<endl;

return;

}

// Если новый процесс создан успешно - начинаем сравнивать файлы

if (pid == (pid_t)0) {

// Занимаем один семафор

sem_wait(semaphore);

cout<<"Process "<<getpid()<<": started"<<endl;

cout<<"Process "<<getpid()<<": compare '"<<sFile1<<"' with '"<<sFile2<<"'"<<endl;

// Получаем размеры 2х файлов

struct stat stat1, stat2;

stat(sFile1.c_str(), &stat1);

stat(sFile2.c_str(), &stat2);

if (stat1.st_size != stat2.st_size) {

cout<<"Process "<<getpid()<<": files '"<<sFile1<<"'("<<stat1.st_size<<" bytes) and '"<<sFile2<<"'("<<stat2.st_size<<" bytes) are not equal"<<endl;

} else {

fstream sfile1(sFile1.c_str(), fstream::in);

fstream sfile2(sFile2.c_str(), fstream::in);

char ch1, ch2;

while (!sfile1.eof() && !sfile2.eof()) {

sfile1.get(ch1);

sfile2.get(ch2);

if (ch1 != ch2 && !sfile1.eof() && !sfile2.eof()) {

cout<<"Process "<<getpid()<<": files '"<<sFile1<<"'("<<stat1.st_size<<" bytes) and '"<<sFile2<<"'("<<stat2.st_size<<" bytes) are not equal"<<endl;

break;

}

}

if (sfile1.eof() && sfile2.eof()) {

cout<<"Process "<<getpid()<<": files '"<<sFile1<<"'("<<stat1.st_size<<" bytes) and '"<<sFile2<<"'("<<stat2.st_size<<" bytes) are equal"<<endl;

}

sfile1.close();

sfile2.close();

}

cout<<"Process "<<getpid()<<": done"<<endl;

// Освобождаем семафор

sem_post(semaphore);

// Завершаем процесс

_exit(0);

}

}

Результат выполнения программы

# Компилируем и запускаем скрипт

nik@virtual:~$ make && ./search

g++ -lpthread main.cpp -o search

# Вводим исходные данные

Enter 1-th dir: /tmp/f1

Enter 2-th dir: /tmp/f2

Enter max process count: 3

# Результат работы скрипта

Process 2150: started

Process 2150: compare '/tmp/f1/test1.php' with '/tmp/f2/test1.php'

Process 2150: files '/tmp/f1/test1.php'(3 bytes) and '/tmp/f2/test1.php'(3 bytes) are equal

Process 2150: done

Process 2151: started

Process 2151: compare '/tmp/f1/test1.php' with '/tmp/f2/2.txt'

Process 2151: files '/tmp/f1/test1.php'(3 bytes) and '/tmp/f2/2.txt'(8031766 bytes) are not equal

Process 2151: done

Process 2152: started

Process 2152: compare '/tmp/f1/test1.php' with '/tmp/f2/1.txt'

Process 2152: files '/tmp/f1/test1.php'(3 bytes) and '/tmp/f2/1.txt'(8031766 bytes) are not equal

Process 2152: done

Process 2153: started

Process 2153: compare '/tmp/f1/2.txt' with '/tmp/f2/test1.php'

Process 2153: files '/tmp/f1/2.txt'(8031766 bytes) and '/tmp/f2/test1.php'(3 bytes) are not equal

Process 2153: done

Process 2154: started

Process 2154: compare '/tmp/f1/2.txt' with '/tmp/f2/2.txt'

Process 2155: started

Process 2155: compare '/tmp/f1/2.txt' with '/tmp/f2/1.txt'

Process 2156: started

Process 2156: compare '/tmp/f1/1.txt' with '/tmp/f2/test1.php'

Process 2156: files '/tmp/f1/1.txt'(8031766 bytes) and '/tmp/f2/test1.php'(3 bytes) are not equal

Process 2156: done

Process 2157: started

Process 2157: compare '/tmp/f1/1.txt' with '/tmp/f2/2.txt'

Process 2154: files '/tmp/f1/2.txt'(8031766 bytes) and '/tmp/f2/2.txt'(8031766 bytes) are equal

Process 2154: done

Process 2158: started

Process 2158: compare '/tmp/f1/1.txt' with '/tmp/f2/1.txt'

Process 2155: files '/tmp/f1/2.txt'(8031766 bytes) and '/tmp/f2/1.txt'(8031766 bytes) are equal

Process 2155: done

Process 2157: files '/tmp/f1/1.txt'(8031766 bytes) and '/tmp/f2/2.txt'(8031766 bytes) are equal

Process 2157: done

Process 2158: files '/tmp/f1/1.txt'(8031766 bytes) and '/tmp/f2/1.txt'(8031766 bytes) are equal

Process 2158: done

Литература

1. Таненбаум, Э. Современные опреационные системы / Э.Таненбаум. – 2-е изд. – СПб.: Питер, 2002-1040 с.

2. Столингс, В. Операционные системы / В.Столингс. – 3-е изд. – М.: Вильямс, 2002. – 848 с.

3. Олифер, В.Г. Сетевые операционные системы: учеб. /В.Г.Олифер, Н.А. Олифер. – СПб.: Питер, 2001.-544 с.

4. Робачевский, А.М, Операционная система Unix / А.М,Робачевский. – СПб.: BHV – Санкт-Петергбург, 1997.- 528 с.