Skip to content

Home Программирование Векторная запись: writev()
Векторная запись: writev()

Векторная запись осуществляется практически так же, как и векторное чтение. Для этого предназначен системный вызов writev(), объявленный в файле sys/uio.h следующим образом:

ssize_t writev (int FD, const struct iovec * VECTOR, int VSIZE); 

Все аргументы этого системного вызова несут тот же смысл, что и в readv(). Чтобы продемонстрировать работу системного вызова writev(), напишем несложную адресную книгу. Рабочие данные (имена, телефоны и адреса электронной почты) будут храниться в файле, который будет представлять собой небольшую базу данных с полями фиксированной длины.

Программа может работать с пользователем в двух режимах:

  1. Добавление новой записи (аргумент add).
  2. Поиск номера телефона и адреса электронной почты по имени их вла-i дельца (аргумент find).

Пример адресной книги

#include <sys/uio.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#define ABOOK_FNAME "abook"

#define NAME_LENGTH 50

#define PHONE_LENGTH 30

#define EMAIL_LENGTH 30

struct iovec ab_entry[3]; /* 1) NAME;2) PHONE and 3) E-MAIL */

char name_buffer [NAME_LENGTH]; char phone_buffer [PHONEJLENGTH]; char email_buffer [EMAIL_.LENGTH];

void abook_failed (int retcode) {

fprintf (stderr, "Cannot open address book\n");

exit (retcode); }

void abook_add (void)

{

int fd;

printf ("Name: ");

scanf ("%s", ab_entry[0].iov_base);

printf ("Phone number: ");

scanf ("%s", ab_entry[1].iov_base);

printf ("E-mail: ");

scanf ("%s", ab_entry[2].iov_base);

fd = open (AB0OK_FNAME, 0_WRONLY | 0_CREAT | 0_APPEND,

S_IRUSR | S_IWUSR | S_IRGRP); if (fd == -1) abook_failed (1);

if (writev (fd, ab_entry, 3) <= 0) {

fprintf (stderr, "Cannot write to address book\n");

exit (1); } close (fd);

void abook^find (void) {

int fd;

char find_buffer [NAME_LENGTH];

printf ("Name: ");

scanf ("%s", find_buffer);

fd = open (ABOOK_FNAME, 0_RDONLY);

if (fd == -1) abook_failed (1);

while (readv (fd, ab_entry, 3) > 0) {

if (Istrcmp (find_buffer, ab_entry[0].iov_base)) {

printf ("Phone: %s\n",

ab_entry[1].iov_base); printf ("E-mail: %s\n",

ab_entry[2].iov_base); goto close; } }

printf ("Name '%s' hasn't found\n", find_buffer); close:

close (fd); }

int main (int argc, char ** argv)

{

if (argc < 2) {

fprintf (stderr, "Too few argumentsXn");

return 1; }

ab_entry[0].iov_base = name_buffer; ab_entry[0].iov_len = NAME_LENGTH; ab_entry[l],iov_base = phone_buffer; ab_entry[l].iov_len = PHONE_LENGTH; ab_entry[2].iov_base = email_buffer; ab_entry[2].iov_len = EMAIL_LENGTH;

if (Istrcmp ( argv[1], "add")) {

abook_add (); } else if (Istrcmp ( argv[1], "find")) {

abook_find (); } else {

fprintf (stderr, "%s: unknown commandXn"

"Usage: abook { add , find }\n", argv[1]);

return 1; }

return 0; }

Особого внимания заслуживает функция abook_f ind(). Многие программисты считают, что "вредоносный" оператор goto не имеет права на существование. Действительно, злоупотребление этим оператором может запутать программу и привести к многим скрытым ошибкам. Но в нашем случае использование goto оправдано и не несет в себе никаких негативных последствий.

В данной программе для чтения и записи предусмотрен общий массив структур iovec. Память для буферов iov_base здесь выделяется статически. Функция abook_faiied() служит для обработки ошибок, связанных с невозможностью открытия файла адресной книги. Функция abook_add() добавляет запись в адресную книгу. Для этого файл открывается с флагом o_append (добавить в конец файла). Функция abook_find() осуществляет поиск в адресной книге. Обратите внимание, что функция readv() работает так же, как и read(): считывает данные до тех пор, пока не будет достигнут конец файла.

Отличие лишь в том, что читается не одиночный буфер, а структурированный набор данных фиксированной длины.

Комментарии (0)

RSS feed Comments

Написать комментарий

smaller | bigger

busy
 

Регистрация




Top