Проведение и оценка эффективности рекламной кампании в сети Internet
СОДЕРЖАНИЕ
ВВЕДЕНИЕ
1
Анализ
задания и разработка алгоритма
2
Теоретические
сведения
3
Листинг
программы
4
Тестирование
ВЫВОДЫ
ЛИТЕРАТУРА
ВВЕДЕНИЕ
Целью выполнения работы является закрепление
знаний умений и навыков в области взаимодействия модулей, использования
системных вызовов и библиотечных функций управления процессами и файлами
современных операционных систем для создания системных и пользовательских
программ, процедур и функций на примере ОС семейства UNIX/Linux. В ходе
выполнения работы студенту необходимо продемонстрировать знания функций,
алгоритмов, механизмов управления процессами, разделяемыми ресурсами, файлами,
вводом-выводом.
Процесс — понятие, которое определяется
по-разному. Это может быть — “упорядоченный набор команд и принадлежащих ему
ресурсов”. С точки зрения ОС Unix процесс — это объект, зарегистрированный в
специальной таблице процессов.
Телом процесса называется набор команд и данных,
которыми оперирует процесс.
Контекст процесса — атрибут, который присутствует
практически во всех ОС, в разных ОС он может называться по-разному. Контексты
всех процессов размещаются в адресном пространстве ОС и содержат оперативную
информацию о состоянии процесса и текущую информацию, связанную с процессом и
его запуском.
1 АНАЛИЗ ЗАДАНИЯ И
РАЗРАБОТКА АЛГОРИТМА
По заданию
согласно варианта по списку необходимо организовать копирование содержимого из
Файла 1 в остальные файлы (1->2, 1->3, 1->4).
Основные
принципы по которым будет создаваться программа:
·
Будут
созданы 4-е процесса, а именно 1-ый процесс породит 2-ый процесс, 1-ый процесс,
в свою очередь породит 3-ий процесс, 1-ый процесс породит 4-тый процесс.
·
Каждый
процесс будет иметь файл с соответствующими именами – file1, file2, file3,
file4.
·
Процессы
будут обмениваться через разделяемую память и временный файл.
·
Обмен
содержимым файлов будет происходить по сигналу, семафорам и обмену сообщениями.
Процессы Process1 и Process4 обмениваются пользовательскими
сигналами, по которым выполняется запись процессом Process1 во временный файл Temp file, после чего Process4 считывает из него
данные, удаляет временный файл, затем записывает информацию в File4, ждет
завершения обмена между процессами Process2, Process3, закрывает разделяемую
память и уничтожает всю группу процессов.
Процессы Process1 и Process2 взаимодействуют с
помощью семафоров. Process1 записывает в разделяемую память содержимое файла
File1, после этого по семафору Process2 считывает из памяти
данные и пишет в File2.
Процессы Process2 и Process3 взаимодействуют с помощью
очереди сообщений. Когда данные уже записаны процессом Process2 в File2, он
отсылает сообщение своему потомку, после чего Process3 считывает из разделяемой
памяти данные, пишет в свой файл File3, отсылает сообщение назад и
завершается, после чего закрывается и его родитель Process2.
Рис.1 Схема
взаимодействия процессов
2 ТЕОРЕТИЧЕСКИЕ
СВЕДЕНИЯ
С
использованием функций в языке СИ связаны три понятия - определение функции
(описание действий, выполняемых функцией), объявление функции (задание формы
обращения к функции) и вызов функции.
Определение
функции задает тип возвращаемого значения, имя функции, типы и число формальных
параметров, а также объявления переменных и операторы, называемые телом
функции, и определяющие действие функции. В определении функции также может
быть задан класс памяти.
Функция
fork:
int
fork ( )
Вызов
fork приводит к созданию нового процесса (порожденного процесса) - точной копии
процесса, сделавшего вызов (родительского процесса). Точнее, порожденный
процесс наследует у родительского процесса следующие характеристики:
·
Окружение.
·
Флаг "закрыть при выполнении вызова exec"
·
Способы обработки сигналов (то есть SIG_DFL, SIG_IGN, SIG_HOLD,
адреса функций обработки сигналов).
·
Разрешение переустанавливать действующий идентификатор
пользователя.
·
Разрешение переустанавливать действующий идентификатор группы.
·
Состояние профилирования (включено/выключено).
·
Значение поправки к приоритету.
·
Все присоединенные разделяемые сегменты памяти.
·
Идентификатор группы процессов.
·
Идентификатор группы терминала.
·
Текущий рабочий каталог.
·
Корневой каталог.
·
Маска режима создания файлов.
·
Ограничение на размер файла.
Порожденный
процесс отличается от родительского процесса следующим:
·
Порожденный процесс имеет свой уникальный идентификатор процесса.
·
Порожденный процесс имеет иной идентификатор родительского
процесса, равный идентификатору процесса, его породившего.
·
Порожденный процесс имеет свои собственные копии родительских
дескрипторов файлов. Каждый дескриптор файла порожденного процесса разделяет с
соответствующим родительским дескриптором файла общий указатель текущей позиции
в файле.
·
Все semadj значения сбрасываются.
·
Порожденный процесс не наследует у родительского процесса
признаков удержания в памяти сегмента команд, данных или всего процесса
целиком.
·
Обнуляются счетчики времени, потраченного для обслуживания этого
процесса (tms_utime, tms_stime, tms_cutime, tms_cstime). Отменяется запрос к
будильнику.
3 ЛИСТИНГ ПРОГРАММЫ
Программа
состоит из главного модуля rgr.c:
#include
<sys/types.h>
#include
<sys/ipc.h>
#include
<sys/shm.h>
#include
<sys/sem.h>
#include
<unistd.h>
#include
<signal.h>
#include
<fcntl.h>
#include
<stdio.h>
#include
<errno.h>
#define SHMKEY
5
#define SEMKEY
5
#define K
32
#define Count
4
#define InitVal {1,0,0,0}
#define MSGKEY
5
#define InitT
3
void
creat_sem(void);
void
prss1(void);
void
prss2(void);
void
prss3(void);
void
prss4(void);
int
pid1; int pid2; int pid3; int pid4; int pid; int ppid;
int
fd; int st;
extern
int p14(int), p41(int);
//mem
int
shmid;
int
*pint;
char
*addr;
//sem
int
semid;
short
initarray[Count] = InitVal;
struct
sembuf p, v;
//message:
int
prnum;
int
msgid;
long
nextT;
struct {
long
mtype;
int
Data;
}
Message;
int
main(void)
{
remove("file2");
remove("file3");
remove("file4");
creat_mem();
creat_sem();
pid1
= getpid();
pid
= fork();
if
(!pid) prss2();
else
prss1();
sleep(2);
wait(&st);
}
void
creat_mem(void)
{
printf("---
func creat_mem(): memory creating: %dbytes --- pid=%d\n", K, getpid());
shmid
= shmget(SHMKEY, 1*K, 0777|IPC_CREAT);
addr
= shmat(shmid, 0, 0);
pint
= (int *) addr;
}
void
creat_sem(void)
{
printf("---
func creat_sem(): semaphor creating: --- pid=%d\n", getpid());
semid
= semget(SEMKEY, Count, 0777|IPC_CREAT);
semctl(semid,
Count, SETALL, initarray);
p.sem_op
= -1;
p.sem_flg
= SEM_UNDO;
v.sem_op
= 1;
v.sem_flg
= SEM_UNDO;
}
void
creat_mesg(void)
{
msgid
= msgget(MSGKEY, 0666|IPC_CREAT);
msgsnd(msgid,
(struct msgbuf *) &Message, 8, 0);
}
void
prss1(void)
{
int
i;
char
buf[32] = " ";
prnum
= 1;
p.sem_num
= 0;
v.sem_num
= 1;
ppid
= getppid();
printf("
=I= prss%d, pid = %d, parent: %d\n", prnum, pid1, ppid);
pid
= fork();
else
{
fd
= open("file1", O_RDONLY);
read(fd,buf,strlen(buf));
close(fd);
printf("I:
reading from FILE1:\t%s\n",buf);
signal(SIGUSR2,
p41);
sleep(1);//ojidanie
priema signala ot prssa4
kill(pid1+2,SIGUSR1);
printf("==================
prss1: writing to memory\n");
for(i
= 0; i <= 31; ++i) pint[i] = buf[i];
semop(semid,
&p, 1);
semop(semid,
&v, 1);
sleep(2);
wait(&st);
wait(&st);
printf("
=I= __eto konec prssa%d\n", prnum);
}
}
void
prss2(void)
{
int
i;
char
buf_2[32]=" ";
prnum
= 2;
p.sem_num
= 1;
pid2
= getpid();
ppid
= getppid();
printf("
=II= prss%d, pid = %d, parent: %d\n", prnum, pid2, ppid);
creat("file2",fd);
pid
= fork();
if
(!pid) prss3();
else
{
semop(semid,
&p, 1);
printf("==================
prss%d: file2 editing /Semaphor/\n", prnum);
fd
= open("file2", O_WRONLY);
for(i
= 0; i <= 31; ++i) buf_2[i] = pint[i];
write(fd,buf_2,strlen(buf_2));
printf("II:
writing to FILE2:\t%s\n",buf_2);
printf("---
func creat_mesg(): message creating: --- pid=%d\n", pid2);
Message.mtype
= InitT;
Message.Data=3;
creat_mesg();
printf("
=II= __eto konec prssa%d\n", prnum);
fclose(fd);
}
}
void
prss3(void)
{
int
i;
char
buf_3[32]=" ";
prnum
= 3;
pid3
= getpid();
ppid
= getppid();
printf("
=III= prss%d, pid = %d, parent: %d\n", prnum, pid3, ppid);
creat("file3",fd);
msgrcv(msgid,
(struct msgbuf *) (&Message), 8, prnum, 0);
if
(Message.Data==3)
{
printf("==================
prss%d: file3 editing /Message/\n", prnum);
fd
= open("file3", O_WRONLY);
for(i
= 0; i <= 31; ++i) buf_3[i] = pint[i];
write(fd,buf_3,strlen(buf_3));
printf("III:
writing to FILE3:\t%s\n",buf_3);
printf("
=III= __eto konec prssa%d\n", prnum);
fclose(fd);
}
}
void
prss4(void)
int
i;
prnum
= 4;
pid4
= getpid();
ppid
= getppid();
printf("
=IV= prss%d, pid = %d, parent: %d\n", prnum, pid4, ppid);
creat("file4",fd);
signal(SIGUSR1,
p14);
kill(pid1,SIGUSR2);
sleep(1);
printf("
=IV= __eto konec prssa%d\n", prnum);
shmctl(shmid,IPC_RMID,0);
printf("==================
prss4: memory closed\n");
kill(0,SIGKILL);
}
int
p14(int signum) //2-oj sig
{
char
temp_buf4[32]=" ";
signal(SIGUSR1,
p14);
printf("***SIGUSR1***
: prss 4 (%d) has got a signal from prss 1 (%d)\n",pid4,pid1);
fd
= open("temp_file", O_RDONLY);
read(fd,temp_buf4,strlen(temp_buf4));
close(fd);
creat("file4",fd);
printf("*
*SIGUSR1* * : writing from temp_file to file4\n");
fd
= open("file4", O_WRONLY);
write(fd,temp_buf4,strlen(temp_buf4));
close(fd);
printf("IV:
writing to FILE4:\t%s\n",temp_buf4);
remove("temp_file");
printf("*
*SIGUSR1* * : temp_file was removed\n");
printf("***SIGUSR1***
: end\n");
}
int
p41(int signum) //1-ij sig
{
char
temp_buf1[32]=" ";
signal(SIGUSR2,
p41);
printf("***SIGUSR2***
prss 1 (%d) has got a signal from prss 4 (%d)\n",pid1,pid1+2);
fd
= open("file1", O_RDONLY);
read(fd,temp_buf1,strlen(temp_buf1));
close(fd);
creat("temp_file",fd);
printf("*
*SIGUSR2* * : temp_file was created\n");
fd
= open("temp_file", O_WRONLY);
write(fd,temp_buf1,strlen(temp_buf1));
close(fd);
printf("***SIGUSR2***
: end\n");
}
4 ТЕСТИРОВАНИЕ
Результат
выполнения программы в консоли:
yuna@YunieHost:/media/8_Gb_hard_ONPU/LINUX/rgr
28march$ ./rgr
---
func creat_mem(): memory creating: 32bytes --- pid=6798
---
func creat_sem(): semaphor creating: --- pid=6798
=II=
prss2, pid = 6799, parent: 6798
=I=
prss1, pid = 6798, parent: 6655
=III=
prss3, pid = 6801, parent: 6799
=IV=
prss4, pid = 6800, parent: 6798
I:
reading from FILE1: << RGR sPO by yuna 18.05.2008 >>
***SIGUSR2***
prss 1 (6798) has got a signal from prss 4 (6800)
*
*SIGUSR2* * : temp_file was created
***SIGUSR2***
: end
==================
prss1: writing to memory
==================
prss2: file2 editing /Semaphor/
II:
writing to FILE2: << RGR sPO by yuna 18.05.2008 >>
---
func creat_mesg(): message creating: --- pid=6799
=II=
__eto konec prssa2
***SIGUSR1***
: prss 4 (6800) has got a signal from prss 1 (6798)
==================
prss3: file3 editing /Message/
III:
writing to FILE3: << RGR sPO by yuna 18.05.2008 >>
=III=
__eto konec prssa3
*
*SIGUSR1* * : writing from temp_file to file4
*
*SIGUSR1* * : temp_file was removed
***SIGUSR1***
: end
=IV=
__eto konec prssa4
==================
prss4: memory closed
Killed
Рис.2 Результат работы
программы (содержимое из file1 было скопировано в остальные файлы)
Следовательно,
программа работает корректно и поставленная на данную расчетно-графическую
работу задача была решена.
ВЫВОДЫ
В данной
работе частично описана структура системы UNIX, взаимоотношения между
процессами, выполняющимися в режиме задачи и в режиме ядра. Процессы
выполняются в режиме задачи или в режиме ядра, в котором они пользуются
услугами системы благодаря наличию набора обращений к операционной системе.
Архитектура
системы поддерживает такой стиль программирования, при котором из небольших
программ, выполняющих только отдельные функции, но хорошо, составляются более
сложные программы, использующие механизм каналов и переназначение ввода-вывода.
Обращения к
операционной системе позволяют процессам производить операции, которые иначе не
выполняются. В дополнение к обработке подобных обращений ядро операционной
системы осуществляет общие учетные операции, управляет планированием процессов,
распределением памяти и защитой процессов в оперативной памяти, обслуживает
прерывания, управляет файлами и устройствами и обрабатывает особые ситуации, возникающие
в системе.
В функции
ядра системы UNIX намеренно не включены многие функции, являющиеся частью
других операционных систем, поскольку набор обращений к системе позволяет
процессам выполнять все необходимые операции на пользовательском уровне.
ЛИТЕРАТУРА
1.
Дж.
Такет (мл.), С.Барнет. Использование Linux/ Специальное издание.: 5-е изд.:
Пер. с англ.: Уч.пос. – М.: Издательский дом «Вильямс», 2000. – 784 с.
2.
Максимальная
защита Linux. Искусство настройки.: Пер. с англ./ под.ред. Дж.Рея – СПб.: ООО
«ДиаСофтЮП», 2002. – 752 с.
3.
Браун
С. Операционная система UNIX - М.: Мир, 1986 - 463 с.