Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции иртегова / Лекция 3 - Захват файлов и записей.doc
Скачиваний:
36
Добавлен:
06.06.2015
Размер:
70.14 Кб
Скачать
      1. Изменение записи - Пример

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

... Файл служащих открывается для чтения и записи. После входа в цикл for вводится номер записи.

28-36 Запись захватывается по чтению. Процесс подвешивается, если запись уже захвачена по изменению.

... Если попытка прочитать запись неуспешна, то захват по чтению снимается и программа идет на начало цикла. Иначе печатается имя служащего и его оклад.

50-54 Если пользователь не хочет изменять запись, захват по чтению снимается и программа продолжается с начала цикла. Предупреждение: Не забудьте освободить запись перед переходом на начало цикла.

55-59 Захват по чтению переводится в захват по изменению. fcntl(2) блокируется, если есть другие процессы, захватившие эту запись по чтению. После того как все процессы освободят эту запись, наш процесс просыпается и захватывает запись.

... Запись о служащем изменяется.

66-67 Захват по изменению снимается с записи.

Файл: update2.c

ИЗМЕНЕНИЕ ЗАПИСИ - ПРИМЕР

ЗАХВАТ ЗАПИСИ ПО ЧТЕНИЮ И ИЗМЕНЕНИЮ

1 #include <sys/types.h>

2 #include <stdlib.h>

3 #include <stdio.h>

4 #include <fcntl.h>

5 #include <unistd.h>

6 #include <errno.h>

7 #include "employee.h"

8

9 main(int argc, char *argv[])

10 {

11 struct flock lock;

...

28 position = (recnum-1) * sizeof(record);

29 lock.l_type = F_RDLCK; /* read lock */

30 lock.l_whence = SEEK_SET;

31 lock.l_start = position;

32 lock.l_len = sizeof(record);

33 if (fcntl(fd, F_SETLKW, &lock) == -1) {

34 perror(argv[1]);

35 exit(2);

36 }

...

50 if (ans[0] != 'y') {

51 lock.l_type = F_UNLCK;

52 fcntl(fd, F_SETLK, &lock);

53 continue;

54 }

55 lock.l_type = F_WRLCK; /* write lock */

56 if (fcntl(fd, F_SETLKW, &lock) == -1) {

57 perror(argv[1]);

58 exit(3);

59 }

...

66 lock.l_type = F_UNLCK; /* release record */

67 fcntl(fd, F_SETLK, &lock);

...

70 }

      1. Выдача информации о захватах записи - Пример

Так как несколько пользователей могут изменять различные записи в файле, может быть необходимо выдать отчет о захваченных записях. Например, полезно знать, что какие-то записи в файле захватываются слишком часто в одной и той же программе. Тогда эту программу можно исправить.

Программа, приведенная на следующей странице, печатает список всех захваченных записей, тип захвата и идентификатор процесса, захватившего запись. Программа проанализирует на захват все записи в файле. Для этого используется системный вызов fcntl(2) с запросом F_GETLK. Тип захвата должен быть равен F_WRLCK, потому что такой запрос конфликтует со всеми другими типами запросов и, таким образом выдаст информацию обо всех установленных захватах. Тип F_RDLCK конфликтует только с захватами на запись и выдаст информацию только о них.

Эта программа работает следующим образом:

12 Описание переменной типа struct flock.

... Файл открывается для чтения и определяется его размер при помощи lseek(2).

22 Записи проверяются с начала файла.

25-26 Этот цикл for проверяет каждую запись в файле.

27-30 Тип захвата запроса - это захват по изменению, но fcntl(2) при возврате изменяет поле l_type на тип захвата, установленного на проверяемой записи. Поле длины записи (l_len) и ее начальная позиция (l_start) также могут быть изменены. Именно поэтому l_start используется как переменная цикла в операторе for. Если запись, задаваемая l_start и l_len, свободна, цикл продолжается со следующей записи.

32-33 Печатается тип захвата.

34-35 Печатается номер записи. Заметим, что программа предполагает, что все записи одного и того же размера.

36-39 Если конец файла, начиная с l_start, захвачен, то l_len станет равным нулю. Тогда вычисляется число оставшихся в файле записей.

40-41 Печатается число захваченных записей.

Помните, что l_start и l_len могут измениться при вызове fcntl(2) с F_GETLK. Это происходит, когда расположение существующего захвата или не точно соответствует значениям, переданным fcntl(2) в структуре flock. Эта программа работает следующим образом:

$ getlocks data

File: data

Pid: 14585 Write lock Record number: 1 Number of

records: 1

Pid: 14605 Read lock Record number: 3 Number of

records: 1

Файл: getlocks.c

ВЫДАЧА ИНФОРМАЦИИ О ЗАХВАТАХ ЗАПИСИ - ПРИМЕР

1 #include <sys/types.h>

2 #include <stdlib.h>

3 #include <stdio.h>

4 #include <fcntl.h>

5 #include <unistd.h>

6 #include <errno.h>

7 #include "employee.h"

8

9 main(int argc, char *argv[])

10 {

11 struct employee record;

12 struct flock lock;

13 off_t size;

...

22 lock.l_whence = SEEK_SET;

23 lock.l_len = sizeof(record);

24 printf("File: %s\n", argv[1]);

25 for (lock.l_start = 0; lock.l_start < size;

26 lock.l_start += lock.l_len) {

27 lock.l_type = F_WRLCK;

28 fcntl(fd, F_GETLK, &lock);

29 if (lock.l_type == F_UNLCK) /* not locked */

30 continue;

31 printf("Pid: %ld", lock.l_pid);

32 printf("\t%s lock",

33 (lock.l_type == F_WRLCK)? "Write" : "Read");

34 printf("\tRecord number: %ld",

35 lock.l_start/sizeof(record));

36 if (lock.l_len == 0) { /* rest of file */

37 lock.l_len = size - lock.l_start;

38 lock.l_start = size; /* terminate for loop */

39 }

40 printf("\tNumber of records: %ld\n",

41 lock.l_len/sizeof(record));

42 }

43 }