| Векторная запись: writev() |
|
Векторная запись осуществляется практически так же, как и векторное чтение. Для этого предназначен системный вызов writev(), объявленный в файле sys/uio.h следующим образом: ssize_t writev (int FD, const struct iovec * VECTOR, int VSIZE); Все аргументы этого системного вызова несут тот же смысл, что и в readv(). Чтобы продемонстрировать работу системного вызова writev(), напишем несложную адресную книгу. Рабочие данные (имена, телефоны и адреса электронной почты) будут храниться в файле, который будет представлять собой небольшую базу данных с полями фиксированной длины. Программа может работать с пользователем в двух режимах:
Пример адресной книги #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(): считывает данные до тех пор, пока не будет достигнут конец файла. Отличие лишь в том, что читается не одиночный буфер, а структурированный набор данных фиксированной длины.
Related Articles
Set as favorite
Bookmark
Email This
Hits: 333 Комментарии (0)RSS feed CommentsНаписать комментарий |