Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Books
  Краткое описание
 Linux
 W. R. Стивенс TCP 
 W. R. Стивенс IPC 
 A.Rubini-J.Corbet 
 K. Bauer 
 Gary V. Vaughan 
 Д Вилер 
 В. Сталлинг 
 Pramode C.E. 
 Steve Pate 
 William Gropp 
 K.A.Robbins 
 С Бекман 
 Р Стивенс 
 Ethereal 
 Cluster 
 Languages
 C
 Perl
 M.Pilgrim 
 А.Фролов 
 Mendel Cooper 
 М Перри 
 Kernel
 C.S. Rodriguez 
 Robert Love 
 Daniel Bovet 
 Д Джеф 
 Максвелл 
 G. Kroah-Hartman 
 B. Hansen 
NEWS
Последние статьи :
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
  SQL 30.07   
  JFS 10.06   
  B-trees 01.06   
 
TOP 20
 Go Web ...603 
 2.0-> Linux IP Networking...354 
 Secure Programming for Li...294 
 2.6-> Kernel 2.6.17...226 
 William Gropp...222 
 Kamran Husain...221 
 Robbins 4...218 
 Advanced Bash Scripting G...211 
 Rodriguez 9...197 
 Rodriguez 6...195 
 Ethreal 1...193 
 UML 3...192 
 Стивенс 8...189 
 Daniel Bovet 2...189 
 Steve Pate 1...187 
 Steve Pate 3...186 
 Kamran Husain...184 
 Advanced Bash Scripting G...182 
 Rodriguez 8...179 
 Kernel Notes...176 
 
  01.03.2019 : 2682145 посещений 

iakovlev.org

Глава 9 , Блокировка записей

Исходники для этой страницы лежат тут

Рассмотрим тип блокировки чтения-записи при совместном доступе к файлу разными программами . Обращение к файлу идет через дескриптор , блокировка активируется с помощью fcntl. Такой тип блокировки может использоваться разными процессами , но не разными потоками одного процесса.

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

       
 #define	SEQFILE	"seqno"		/* filename */
 
 void	my_lock(int), my_unlock(int);
 
 int main(int argc, char **argv)
 {
 	int		fd;
 	long	i, seqno;
 	pid_t	pid;
 	ssize_t	n;
 	char	line[MAXLINE + 1];
 
 	pid = getpid();
 	fd = Open(SEQFILE, O_RDWR, FILE_MODE);
 
 	for (i = 0; i < 20; i++) {
 		my_lock(fd);				/* lock the file */
 
 		Lseek(fd, 0L, SEEK_SET);	/* rewind before read */
 		n = Read(fd, line, MAXLINE);
 		line[n] = '\0';				/* null terminate for sscanf */
 
 		n = sscanf(line, "%ld\n", &seqno);
 		printf("%s: pid = %ld, seq# = %ld\n", argv[0], (long) pid, seqno);
 
 		seqno++;					/* increment sequence number */
 
 		snprintf(line, sizeof(line), "%ld\n", seqno);
 		Lseek(fd, 0L, SEEK_SET);	/* rewind before write */
 		Write(fd, line, strlen(line));
 
 		my_unlock(fd);				/* unlock the file */
 	}
 	exit(0);
 }
 
Программа пишет число в файл seqno.

Интерфейсом для блокировки записей является функция fcntl

       
 	int fcntl(int fd , int cmd , ... (struct flock * arg))
 
 Возвращаемый результат произволен 
 
Аргумент cmd может принимать 3 значения :
       
 	1  F_SETLK  - установка блокировки или сброс блокировки	
 	2  F_SETLKW - то же , но в ждцщем режиме , пока блокировка будет установлена (wait)
 	3  F_GETLK  - проверка блокировки  
 
Структура flock описывает тип блокировки - чтение или запись - и диапазон блокировки .

Существует 2 способа заблокировать файл целиком :

       
 	1 указать в flock.l_whence = SEEK_SEET , flock.l_start = 0 , flock.l_len = 0
 	2 перейти к началу файла с помощью lseek , потом flock.l_whence = SEEK_CUR , flock.l_start = 0 , flock.l_len = 0
 
 	Чаще всего используется первый метод.
 
На один файл может быть установлено несколько блокировок на чтение , и только одна на запись. Нельзя установить блокировку на чтение для файла , который заблокирован на запись . Рекомендательная блокировка - advisory lock - в соответствии со стандартами POSIX говорит следующее : Если файл заблокирован на чтение , в него можно писать . Если файл заблокирован на запись , из него можно читать .

Некоторые системы предоставляют возможность обязательной блокировки - mandatory locking . для нее требуется выполнение 2-х условий :

       
 	Бит group-execute должен быть снят
 	Бит set-group-ID должен быть установлен
 

Напишем следующую программу , устанавливающую блокировку на чтение для всего файла и порождающую 2 процесса с помощью fork . Первый из них делает блокировку на запись , а второй процесс секунду спустя пытается сделать блокировку на чтение . Временная диаграмма :

       
 //lock/test2
 
 int
 main(int argc, char **argv)
 {
 	int		fd;
 
 	fd = Open("test1.data", O_RDWR | O_CREAT, FILE_MODE);
 
 	Read_lock(fd, 0, SEEK_SET, 0);		/* parent read locks entire file */
 	printf("%s: parent has read lock\n", Gf_time());
 
 	if (Fork() == 0) {
 			/* 4first child */
 		sleep(1);
 		printf("%s: first child tries to obtain write lock\n", Gf_time());
 		Writew_lock(fd, 0, SEEK_SET, 0);	/* this should block */
 		printf("%s: first child obtains write lock\n", Gf_time());
 		sleep(2);
 		Un_lock(fd, 0, SEEK_SET, 0);
 		printf("%s: first child releases write lock\n", Gf_time());
 		exit(0);
 	}
 
 	if (Fork() == 0) {
 			/* 4second child */
 		sleep(3);
 		printf("%s: second child tries to obtain read lock\n", Gf_time());
 		Readw_lock(fd, 0, SEEK_SET, 0);
 		printf("%s: second child obtains read lock\n", Gf_time());
 		sleep(4);
 		Un_lock(fd, 0, SEEK_SET, 0);
 		printf("%s: second child releases read lock\n", Gf_time());
 		exit(0);
 	}
 
 	/* 4parent */
 	sleep(10);
 	Un_lock(fd, 0, SEEK_SET, 0);
 	printf("%s: parent releases read lock\n", Gf_time());
 	exit(0);
 }
 
 
Родительский процесс открывает файл и устанавливает блокировку на чтение на весь файл. При этом мы выводим время получения этой блокировки. Создаем первый процесс , который блокирует файл на запись , снимает эту блокировку и завершается. Создаем второй процесс , который пытается получить блокировку на чтение .
       
 	21:11:43.472154: parent has read lock
 	21:11:44.473772: first child tries to obtain write lock
 	21:11:46.479094: second child tries to obtain read lock
 	21:11:46.479385: second child obtains read lock
 	21:11:50.481361: second child releases read lock
 	21:11:53.477565: first child obtains write lock
 	21:11:53.477605: parent releases read lock
 
Единственная разница со стивенсом - на моей машине пришлось увеличить время ожидания родительского процесса с 5 секунд до 10 .

Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье