You are on page 1of 11

Федеральное агентство по образованию

Государственное образовательное учреждение высшего профессионального


образования
«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

Факультет – Автоматики и Вычислительной Техники


Направление – Информатика и Вычислительная Техника
Кафедра – Вычислительной техники

Отчет по лабораторной работе № 4


по дисциплине «Операционные системы»

«Процессы и межпроцессное взаимодействие»

Студент гр. 8В53 ______________________ Афанасьев А.А.


(подпись)

Преподаватель ______________________ Шерстнев В.С.


(подпись)

Томск – 2008
ЦЕЛЬ РАБОТЫ: Практическое знакомство с объектом процесс, основными
механизмами передачи данных между процессами, а также синхронизацией
взаимодействующих процессов в ОС Unix.

ЗАДАНИЕ НА ЛАБОРАТОРНУЮ РАБОТУ: Изучить базовые


возможностей оболочки bash ОС Unix по управлению
процессами (заданиями). Разработать приложения реализующие схему
«клиент»-«сервер» с использованием средств межпроцессного
взаимодействия: семафоров, разделяемой памяти, программных каналов и
одной очереди сообщений.

1. Изучение команд для работы с процессами.

Команда ps выдает список протекающих в настоящее время процессов.


Если указать праметр –aux то будет выведен полный список процессов.
Команда jobs выдает список процессов запущенных пользователем.
Команды fg и bg служат для возобновления приостановленного процесса
соответственно на «переднем плане» или в фоновом режиме.
Команда kill служит для уничтожения процессов, а killall – для уничтожения
процессов по имени.

[root:~]# ps
PID TTY STAT TIME COMMAND
41 v01 S 0:12 -bash
42 v02 S 0:00 /sbin/getty tty2 VC console
43 v03 S 0:00 /sbin/getty tty3 VC console
44 v04 S 0:00 /sbin/getty tty4 VC console
142 v01 R 0:01 ps

[root:~]# ps -aux
USER PID %CPU %MEM SIZE RSS TTY STAT START TIME COMMAND
root 1 0.0 0.6 44 192 ? S 19:13 0:03 init
root 41 0.0 1.5 360 472 v01 S 19:15 0:13 -bash
root 42 0.0 0.6 56 192 v02 S 19:15 0:00 /sbin/getty tty2 VC c
root 22 0.0 0.7 68 240 ? S 19:15 0:01 /usr/sbin/crond
root 17 0.0 0.7 54 228 ? S 19:15 0:02 /sbin/syslogd
root 19 0.0 0.6 68 212 ? S 19:15 0:01 /usr/sbin/inetd
root 24 0.0 0.5 64 172 ? S 19:15 0:00 /usr/sbin/lpd
root 27 0.0 1.0 288 324 ? S 19:15 0:07 /usr/lib/sendmail -q1
root 43 0.0 0.6 56 192 v03 S 19:15 0:00 /sbin/getty tty3 VC c
root 44 0.0 0.6 56 192 v04 S 19:15 0:00 /sbin/getty tty4 VC c
root 31 2.0 0.2 5 68 ? S 19:15 5:57 /sbin/update
root 143 0.0 0.7 72 224 v01 R 23:59 0:01 ps -aux
[root:~]#
[root:~]# ./q2 &
[1] 144
[root:~]# jobs
[1]+ Running ./q2 &
[root:~]# fg
./q2

[1]+ Stopped ./q2


[root:~]# bg
[1]+ ./q2 &

[root:~]# ./q2

[1]+ Stopped ./q2


[root:~]# jobs
[1]+ Stopped ./q2
[root:~]# kill %1

[1]+ Stopped ./q2


[root:~]# jobs
[1]+ Terminated ./q2
[root:~]#

2. Межроцессное взаимодействие.

Взаимодействие посредством разделяемой памяти.


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

Текст программы:

#include <stdio.h>
#include <cerrno>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>

#define SVSEM_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH


#define SKEY 1234L
int main()
{

union semun arg;


struct semid_ds seminfo;
int oflag = SVSEM_MODE|IPC_CREAT;
struct sembuf psmb;

//Semaphore
int semid = semget(SKEY,1,oflag);
arg.buf = &seminfo;
arg.val = 1;
semctl(semid, 0, SETVAL, arg);

//Memory

int length = 10;


int id = shmget(ftok("SH", 0), length, oflag);

char *pointer;
struct shmid_ds sharedMemoryBuf;

// lock

psmb.sem_num = 0;
psmb.sem_flg = 0;
psmb.sem_op = -1;
semop(semid, &psmb, 1);

//Child_____________________

pid_t pid;
if ((pid = fork()) == 0)
{

//lock
int flag = SVSEM_MODE|IPC_EXCL;
int smd = semget(SKEY, 1, flag);
struct sembuf csmb;
csmb.sem_num = 0;
csmb.sem_flg = 0;
csmb.sem_op = -1;
semop(semid, &csmb, 1);

pointer = (char*)shmat(id, NULL, 0);


shmctl(id, IPC_STAT, &sharedMemoryBuf);
printf("Getted numbers:");
int sum=0;
for (int i=0; i<sharedMemoryBuf.shm_segsz;i++) {

printf("%i",(int)*pointer); printf(" ");


sum+= (int)*pointer++;

}
printf ("Sum= "); printf ("%i",sum); printf(" ");

// unlock
csmb.sem_num = csmb.sem_flg = 0;
csmb.sem_op = 1;
semop(smd, &csmb, 1);

exit(0);
}
//End of child process

pointer = (char*)shmat(id, NULL, 0);


shmctl(id, IPC_STAT, &sharedMemoryBuf);

//Memory filling

for (int i = 0; i < sharedMemoryBuf.shm_segsz; i++)


{

int num=rand()%10;

*pointer++ = (char)num;

//unlock
psmb.sem_num = psmb.sem_flg = 0;
psmb.sem_op = 1;
semop(semid,&psmb,1);

waitpid(pid, NULL, 0);


semctl(semid, 0, IPC_RMID,arg);
shmctl(id, IPC_RMID, NULL);

exit(0);
}
В общем виде работу программы можно описать следующим образом.
Родительский процесс блокирует семафор, заполняет память, разблокирует
семафор и дожидается окончания дочернего процесса, дочерний процесс
извлекает данные из памяти и находит сумму.

Результат выполнения.

[root:~]# ./b
Getted numbers:9 4 1 8 7 5 2 3 3 8 Sum= 50 [root:~]#

Взаимодействие посредством именованных каналов.

Имеются 2 программы клиент и сервер. Создаются 2 именованных канала


один для передачи сообщения от клиента к серверу, другой – от сервера к
клиенту.
Клиентский процесс отправляет строку серверу, сервер к этой строке
добавляет свою и отправляет обратно клиенту.

Тексты программ:

Файл cf.cpp

#include <unistd.h>
#include <stdio.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream.h>
#include <strings.h>
#include <fstream.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define MAXLINE 128
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define FIFO1 "fifo1"
#define FIFO2 "fifo2"

int main() {
int readfd = -1,writefd = -1;
pid_t childpid = 0;
size_t n = 0;
char str[MAXLINE];

strcpy(str,"String from client ");

writefd = open(FIFO1, O_WRONLY, 0);


write(writefd,str,strlen(str));

sleep(1);

readfd = open(FIFO2, O_RDONLY, 0);


if (readfd != -1) {

cout <<str;

while ((n = read(readfd,str, MAXLINE)) > 0) {


str[n] = 0;

break;
}

cout<< str;

close(readfd);
close(writefd);

return 1;
}

Файл sf.cpp

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <cerrno>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
#include <strings.h>
#include <iostream.h>
#include <error.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>

#define MAXLINE 128


#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define FIFO1 "fifo1"
#define FIFO2 "fifo2"

int main() {
char str[MAXLINE];
ssize_t n;
int readfd = -1,writefd = -1;

unlink(FIFO1);
unlink(FIFO2);
if (mkfifo(FIFO1, FILE_MODE) == EEXIST) cout<<"\n Pipes is exists"<<endl;
if (mkfifo(FIFO2, FILE_MODE) == EEXIST) cout<<"\n Pipes is exists"<<endl;

readfd = open(FIFO1, O_RDONLY);


while ((n = read(readfd,str, MAXLINE)) > 0) {
str[n] = 0;

break;
}

strcat(str," was catched by server");

writefd = open(FIFO2, O_WRONLY);


if ((writefd != -1)) write(writefd,str,strlen(str));

close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);

Результат: (сначала запускается серверный процесс в фоновом режиме, а затем


клиентский)

[root:~]# ./sf &


[1] 192
[root:~]# ./cf
String from client String from client was catched by server[1]+ Done
./sf
[root:~]#

Взаимодействие посредством очереди сообщений.

Один из процессов помещает строку, введенную пользователем, в очередь


сообщений, а другой получив это сообщение кодирует его по методу Юлия
Цезаря и выводит на экран.
Файл q1

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <error.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <strings.h>
#include <iostream.h>

#define SVMSG_MODE (S_IWUSR)

struct {
long mtype;
char mtext[100];
} ptr;

int main()
{

int flag =SVMSG_MODE|IPC_CREAT;


int mqid;

char text[100];
gets(text);

mqid = msgget(ftok("queue", 0), flag);

ptr.mtype = 1;
strcpy(ptr.mtext,text);
msgsnd(mqid, (struct msgbuf*)(&ptr),strlen(text)+1, 0);

msgctl(mqid,IPC_RMID,NULL);
return 0;
}
Файл q2

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <cerrno>
#include <iostream.h>

#define MSG_R (S_IRUSR | S_IRGRP | S_IROTH)


#define MAXMSG 100

struct {
long mtype;
char mtext[100];
} ptr;

int main()
{

int flag, mqid;


long type;

flag = 0;
type =1;

mqid = msgget(ftok("queue", 0), MSG_R|IPC_CREAT);


msgrcv(mqid,(struct msgbuf*)(&ptr), MAXMSG, type, flag);

char text[MAXMSG];
strcpy(text,ptr.mtext);

for (int i=0;i<MAXMSG;i++){


char c=text[i]; int num=(int)c;

switch(num) {
case 90: text[i]= 'A'; break;
case 122: text[i]='a'; break;

default: if ( ( (num>=65)&&(num<90) )||( (num>=97)&&(num<122) ) ) text[i]=(char)(num+1);


}

}
cout<< text;
return 0;
}
Результат выполнения.

[root:~]# ./q2 &


[5] 874
[root:~]# ./q1
render to Caesar the things that are Caesar's
sfoefs up Dbftbs uif uijoht uibu bsf Dbftbs't[5] Done ./q2
[root:~]#

Вывод: В лабораторной работе было рассмотрено такое понятие как процесс


и методы работы с процессами, а также такие способы обмена данными
между процессами, как разделяемая память, каналы сообщения и очереди
сообщений. При этом был рассмотрен способ синхронизации посредством
семафоров.