ورودی/خروجی برداری
در رایانش، ورودی خروجی برداری (به انگلیسی: vectored I/O) یا ورودی خروجی پاشیدنی/انباشتنی (به انگلیسی: scatter/gather I/O) یک نوع روش انجام عمل ورودی/خروجی است که در آن تنها یک بار فراخوانی کردن یک روال خواندن/نوشتن، باعث میشود تا بیکباره چندین بافر به صورت متوالی و پشت سر هم در یک جریان داده نوشته یا از آن خوانده شود. این بافرها در یک «بردار» (یا آرایه) به روال مورد نظر ارسال میشوند، به همین خاطر این روش ورودی/خروجی برداری نام گرفتهاست. پاشیدن/انباشتن اشاره به نوشتن دادهها در آن بافرها یا خواندن اطلاعات از آن بافرها دارد. این نوع روش ورودی/خروجی، میتواند به صورت همگام یا ناهمگام باشد. دلیل اصلی برای استفاده از ورودی/خروجی برداری، کارا بودن و راحت بودن آن است.
چندین کاربرد برای این نوع ورودی/خروجی وجود دارد:
- به صورت اتمیک و تجزیهناپذیر: اگر یک پیادهسازی خاص از ورودی/خروجی برداری، انجام این عمل به صورت اتمی را پشتیبانی کند، یک پروسه میتواند بدون خطر مزاحمت دیگر پروسهها و به وجود آمدن شرایط رقابتی، اطلاعات را در بافرها بخواند یا بنویسد. به این ترتیب، صحت و یکپارچگی دادهها به خطر نخواهد افتاد. در صورتی که پیادهسازی از روش اتمی پشتیبانی نکند، پروسه باید تدبیری بیندیشد تا در حین ورود به ناحیه بحرانی (نوشتن و خواندن) هیچ پروسه دیگری سعی در نوشتن یا خواندن از همان محل نکند (این کار با سمافورها، قفل کردن رکوردها و روشهای مشابه انجام میشود)
- خروجی زنجیرهای: اگر یک برنامه بخواهد اطلاعاتی که به صورت پشت سر هم در حافظه قرار ندارند را به صورت پشت سر هم در یک توصیفگر پرونده یا هر جریان داده دیگری بنویسد، میتواند با این روش این کار را انجام دهد. به عنوان مثال، در صورتی که یک برنامه بخواهد یک سرآیند با اندازه ثابت و محموله مرتبط با آن سرآیند را که به صورت غیرمتوالی در حافظه قرار گرفتهاند را در جایی بنویسد، میتواند این کار را با تنها یک بار فراخوانی روال نوشتن و بدون نیاز به متوالیکردن سرآیند و محمولهاش در حافظه، انجام دهد.
- کارایی: بدون استفاده از روش ورودی/خروجی برداری، نیاز است تا روال مربوط به خواندن و نوشتن، چندین بار به ازای هر بافر فراخوانی شود، اما در این روش، کل عمل با یک بار فراخوانی کردن روال نوشتن یا خواندن انجام میشود. در نتیجه، سربار مربوط به فراخوانی کردن فراخوانهای سیستمی کاهش مییابد.
- ورودی تسهیمشده: یک برنامهنویس میتواند در حین خواندن دادههایی که در یک قالب خاص با یک سرآیند با اندازه ثابت هستند، از آرایهای از بافرها استفاده کند که اولین بافر در این آرایه، اندازه سرایند مورد نظر است و دومین بافر (یا بقیه بافرها) میتوانند حاوی محموله مرتبط با آن سرایند باشند.
در استاندارد پازیکس دو تابع writev و readv تعریف شدهاند که به ترتیب میتوان از آنها برای نوشتن و خواندن استفاده کرد. در API ویندوز هم توابع مشابه ReadFileScatter و WriteFileGather تعریف شدهآند.
مثال
برنامه زیر پیغام Hello Wikipedia Community! را بر روی خروجی استاندارد چاپ میکند، هر کلمه در یا بافر مختلفی قرار گرفتهاست که تنها با یک بار فراخوانی تابع writev، تمام این بافرها در خروجی استاندارد نوشته میشوند:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/uio.h>
#define NUMBUFS 3
int
main(int argc, char *argv[])
{
const char *buf1 = "Hello ";
const char *buf2 = "Wikipedia ";
const char *buf3 = "Community!\n";
struct iovec bufs[NUMBUFS];
bufs[0].iov_base = (void*) buf1;
bufs[0].iov_len = strlen(buf1);
bufs[1].iov_base = (void*) buf2;
bufs[1].iov_len = strlen(buf2);
bufs[2].iov_base = (void*) buf3;
bufs[2].iov_len = strlen(buf3);
if (-1 == writev(STDOUT_FILENO, bufs, NUMBUFS))
{
perror("writev()");
exit(EXIT_FAILURE);
}
return 0;
}
منابع
Wikipedia contributors. Vectored I/O. Wikipedia, The Free Encyclopedia. June 24, 2014, 05:01 UTC. Available at: http://en.wikipedia.org/w/index.php?title=Vectored_I/O&oldid=614187174. Accessed February 17, 2015.