Лабораторна робота №2-4
Блокування файлів. Необхідність блокування
Виконаємо наступну програму
#include<stdio.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
Int main()
{
int fd;
int x,y;
pid_t pid;
unlink("/tmp/file");/*Видаляємо попередній файл*/
fd=open("/tmp/file", O_WRONLY|O_CREAT, 0777);
if(fd==-1)
{
perror("open:");
exit(0);
}
if((pid=fork())==-1)
{
perror("fork:");
exit(0);
}
else if(pid)
{/*Батьківський процес*/
while(1)
{
for(x=0; x<10; x++)
{
sleep(1);
write(fd,(char *)"x",1);
}
break;
}
else
{/*Процес-нащадок*/
while(1)
{
for(y=0; y<10; y++)
{
sleep(1);
write(fd,(char *)"X",1);
}
break;
}
return0;
}
Після виконання цієї програми вміст файлу``/tmp/file'' може виглядати наступним чином:
XXXXXXXXXXXXXXXXXXX
Для зберігання даних було б краще, щоб кожен процес записував свої дані в окрему частину файлу. При цьому вміст файлу "/tmp/file" мав би бути наступним:
XXXXXXXXXXXXXXXXXXXX
Для розділення даних у файлі використовується функція:
Int fcntl(int fd, int сommand,...
/*struct flock *flockptr*/)
Cтруктура flock
Ця структура використовується для управління блокуванням і має такий зміст:
struct flock
{
short l_type;/*3 режими блокування
F_RDLCK(Розділення читання)
F_WRLCK(Розділення запису)
F_UNLCK(Зупинити розділення)*/
off_t l_start;/*відносне зміщення у байтах, залежить від l_whence*/
short l_whence;/*SEEK_SET;SEEK_CUR;SEEK_END*/
off_t l_len;/*довжина, 0=розділення до кінця файлу*/
pid_t l_pid;/*ідентифікатор, повертається F_GETLK*/
};
Перед встановленням режиму блокування файлу необхідно заповнити поля структури flock потрібним чином:
flockptr.l_start=0;/*починаємо з зміщення 0*/
flockptr.l_whence=SEEK_SET;/*з початку файлу*/
Якщо необхідно дописувати в кінець файлу, то l_len приймає значення 0.
flockptr.l_len=0;
У цьому випадку файл блокується до його кінця.
Режими блокування
Функції блокування можна використовувати в наступних режимах:
F_GETLK. За допомогою цього режиму можна встановити, який з видів блокування застосовується до даного файлу:
struct flock flptr;
fd=open(data, O_CREAT|O_WRONLY);
fcntl(fd, F_GETLK, &flptr);
if(flptr.l_type==F_UNLCK)
{/*Дані,які не блоковано*/}
else if(flptr.l_type==F_RDLCK)
{/*Блокування по читанню*/}
else if(flptr.l_type==F_WRLCK)
{/*Блокування по запису*/}
F_SETLK. За допомогою цього режиму організовується блокування. Якщо блокування неможливо, функція fcntl завершується і встановлює змінну errno в значення EACCES або EAGAIN. За допомогою F_SETLK можна також видалити встановлене блокування (F_UNLCK):
flptr.l_start=0;
flptr.l_whence=SEEK_SET;
flptr.l_len=0;
flptr.l_type=F_RDLCK;
if((fcntl(fd, F_SETLK, &flptr)!=-1)
{/*Встановлено блокування по читанню*/}
flptr.l_start=0;
flptr.l_whence=SEEK_SET;
flptr.l_len=0;
flptr.l_type=F_WRLCK);
if((fcntl(fd, F_SETLK, &sperre)!=-1)
{/*Встановлення блокування по запису*/}
flptr.l_type=F_UNLCK;
if((fcntl(fd, F_SETLK, &flptr)!=-1)
{/*Блокування знято*/}
F_SETLKW. За допомогою цього режиму процес припиняється доти, поки не реалізує необхідне блокування.
Якщо для файлу потрібно передбачити блокування запису (F_WRLCK), то файл повинен бути відкритий для запису (O_WRONLY). Таким же чином, якщо необхідне блокування читання (F_RDLCK), тоді файл відкривається в режимі читання (O_RDONLY). Це означає також, що блокування не повинні одночасно встановлюватися на певний байт.
Програма, яка виконує блокування:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#define FNAME "locki.lck"