'\" t .\" Man page generated from reStructuredText .\" by the Docutils 0.23 manpage writer. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "LIBUV" "1" "Aug 26, 2026" "1.52.1" "libuv API documentation" .SH "نام (NAME)" libuv \- کتابخانه پشتیبانی از ورودی/خروجی ناهمگام و رویدادمحور چندسکویی .SH "نمای کلی (OVERVIEW)" .sp کتابخانه libuv یک کتابخانه پشتیبانی چندسکویی با تمرکز بر ورودی/خروجی ناهمگام است. این کتابخانه در ابتدا برای استفاده در Node.js \% توسعه داده شد، اما توسط Luvit \%، Julia \%، uvloop \% و پروژه‌های دیگر \% نیز استفاده می‌شود. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در صورت مشاهده خطا در این مستندات، می‌توانید با ارسال درخواست‌های پول (Pull Requests) در \% به بهبود آن کمک کنید! .UNINDENT .UNINDENT .SH "ویژگی‌ها (FEATURES)" .INDENT 0.0 .IP \(bu 2 حلقه رویداد کامل با پشتیبانی از epoll، kqueue، IOCP و event ports. .IP \(bu 2 سوکت‌های ناهمگام TCP و UDP .IP \(bu 2 تفکیک نام دامنه (DNS) به‌صورت ناهمگام .IP \(bu 2 عملیات ناهمگام فایل و سیستم فایل .IP \(bu 2 رویدادهای سیستم فایل .IP \(bu 2 پایانه TTY کنترل‌شده با کدهای گریز ANSI .IP \(bu 2 ارتباط بین‌پردازشی (IPC) همراه با اشتراک‌گذاری سوکت، با استفاده از سوکت‌های دامنه یونیکس یا لوله‌های نام‌گذاری‌شده (ویندوز) .IP \(bu 2 فرآیندهای فرزند (Child processes) .IP \(bu 2 استخر ریسه‌ها (thread pool) .IP \(bu 2 مدیریت سیگنال‌ها .IP \(bu 2 ساعت با دقت بالا (High resolution clock) .IP \(bu 2 مفاهیم پایه‌ای ریسه‌بندی و همگام‌سازی .UNINDENT .SH "مستندات (DOCUMENTATION)" .SS "نمای کلی طراحی (Design overview)" .sp کتابخانه libuv یک کتابخانه پشتیبانی چندسکویی است که در ابتدا برای Node.js \% نوشته شد. این کتابخانه بر اساس مدل ورودی/خروجی ناهمگام و رویدادمحور طراحی شده است. .sp این کتابخانه امکاناتی بسیار فراتر از یک لایه انتزاعی ساده بر روی سازوکارهای مختلف پایش (polling) ورودی/خروجی ارائه می‌دهد: «هندل‌ها» (handles) و «جریان‌ها» (streams) یک انتزاع سطح بالا برای سوکت‌ها و دیگر موجودیت‌ها فراهم می‌کنند؛ همچنین قابلیت‌های چندسکویی ورودی/خروجی فایل و کار با ریسه‌ها نیز در میان سایر موارد ارائه شده است. .sp نمودار زیر بخش‌های گوناگون تشکیل‌دهنده libuv و زیرسیستم مربوط به هر یک را نشان می‌دهد: [image] .SS "هندل‌ها و درخواست‌ها (Handles and requests)" .sp کتابخانه libuv در ترکیب با حلقه رویداد، ۲ مفهوم انتزاعی برای کار در اختیار کاربران قرار می‌دهد: هندل‌ها (handles) و درخواست‌ها (requests). .sp هندل‌ها نشان‌دهنده اشیایی با طول عمر بالا هستند که قادرند در زمان فعال بودن عملیات خاصی را انجام دهند. چند مثال: .INDENT 0.0 .IP \(bu 2 یک هندل آماده‌سازی (prepare handle) که در زمان فعال بودن، کالبک آن یک بار در هر تکرار حلقه فراخوانی می‌شود. .IP \(bu 2 یک هندل سرور TCP که هر بار با برقراری یک اتصال جدید، کالبک اتصال آن فراخوانی می‌شود. .UNINDENT .sp درخواست‌ها معمولاً نشان‌دهنده عملیاتی با طول عمر کوتاه هستند. این عملیات می‌توانند روی یک هندل انجام شوند: درخواست‌های نوشتن برای نوشتن داده روی یک هندل استفاده می‌شوند؛ یا به‌صورت مستقل عمل کنند: درخواست‌های getaddrinfo نیازی به هندل ندارند و مستقیماً روی حلقه رویداد اجرا می‌شوند. .sp رهنمودهای کار با هندل‌ها و درخواست‌ها: .INDENT 0.0 .IP 1. 3 اگر \fIuv_foo_init()\fP در مقداردهی اولیه هندل موفق شد، باید \fBuv_close()\fP \%<#\:c\:.uv_close> را فراخوانی کنید. اگر تابع مقداردهی اولیه هندل با خطا مواجه شود، نیازی به انجام کاری ندارید. .IP 2. 3 فقط هندل‌ها بسته می‌شوند، نه درخواست‌ها. برای مثال، \fBuv_tcp_t\fP \%<#\:c\:.uv_tcp_t> یک هندل است و \fBuv_write_t\fP \%<#\:c\:.uv_write_t> یک درخواست است. .IP 3. 3 حافظه هندل فقط از داخل کالبک \fBuv_close_cb\fP \%<#\:c\:.uv_close_cb> یا پس از آن قابل آزادسازی یا استفاده مجدد است، نه قبل از آن. .IP 4. 3 بیشتر هندل‌ها دارای توابع init + start/stop هستند؛ برخی هندل‌ها این‌گونه نیستند. مثال: \fBuv_tcp_t\fP \%<#\:c\:.uv_tcp_t> در مقایسه با \fBuv_process_t\fP \%<#\:c\:.uv_process_t>؛ تابع \fBuv_spawn()\fP \%<#\:c\:.uv_spawn> مقداردهی اولیه هندل و شروع فرآیند را در یک تابع ترکیب می‌کند. .IP 5. 3 درخواست‌ها پس از تکمیل، یا در صورت لغو شدن با \fBuv_cancel()\fP \%<#\:c\:.uv_cancel>\&، به‌صورت خودکار بسته می‌شوند. .IP 6. 3 هیچ پاک‌سازی اضافه‌ای لازم نیست مگر برای درخواست‌های \fBuv_fs_t\fP \%<#\:c\:.uv_fs_t> و \fBuv_getaddrinfo_t\fP \%<#\:c\:.uv_getaddrinfo_t>\&. برای \fBuv_fs_t\fP \%<#\:c\:.uv_fs_t>، پس از اتمام کار تابع \fBuv_fs_req_cleanup()\fP \%<#\:c\:.uv_fs_req_cleanup> را فراخوانی کنید؛ برای \fBuv_getaddrinfo_t\fP \%<#\:c\:.uv_getaddrinfo_t>، این تابع \fBuv_freeaddrinfo()\fP \%<#\:c\:.uv_freeaddrinfo> است. .IP 7. 3 حافظه درخواست فقط از آن نقطه به بعد قابل آزادسازی یا استفاده مجدد است. .UNINDENT .SS "حلقه ورودی/خروجی (The I/O loop)" .sp حلقه ورودی/خروجی (یا حلقه رویداد) بخش مرکزی libuv است. این حلقه بستر تمام عملیات ورودی/خروجی را مشخص می‌کند و باید به یک ریسه (thread) منفرد متصل باشد. تا زمانی که هر حلقه در ریسه‌ای جداگانه اجرا شود، می‌توان چندین حلقه رویداد را همزمان اجرا کرد. حلقه رویداد libuv (یا هر API دیگری که شامل حلقه یا هندل‌ها باشد) به جز در مواردی که صراحتاً خلاف آن ذکر شده باشد، \fBاز نظر همروندی ریسه‌ها امن نیست (thread-safe نیست)\fP. .sp حلقه رویداد از رویکرد رایج ورودی/خروجی ناهمگام تک‌ریسه‌ای پیروی می‌کند: تمام ورودی/خروجی‌های (شبکه) روی سوکت‌های مسدودنشدنی (non-blocking) انجام می‌شوند که با استفاده از بهترین سازوکار موجود در سکوی مربوطه پایش (poll) می‌شوند: epoll در لینوکس، kqueue در OSX و دیگر سیستم‌های BSD، event ports در SunOS و IOCP در ویندوز. به عنوان بخشی از یک تکرار حلقه، حلقه منتظر فعالیت ورودی/خروجی روی سوکت‌هایی می‌ماند که به پایشگر (poller) اضافه شده‌اند و کالبک‌هایی اجرا می‌شوند که وضعیت سوکت را مشخص می‌کنند (خواندنی، نوشتنی، قطع اتصال) تا هندل‌ها بتوانند عملیات خواندن، نوشتن یا ورودی/خروجی مورد نظر را انجام دهند. .sp برای درک بهتر نحوه عملکرد حلقه رویداد، نمودار زیر تمام مراحل یک تکرار حلقه را نشان می‌دهد: [image] .INDENT 0.0 .IP 1. 4 مفهوم زمان جاری («اکنون» یا now) در حلقه مقداردهی اولیه می‌شود. .IP 2. 4 اگر حلقه با \fBUV_RUN_DEFAULT\fP اجرا شده باشد، تایمرهای سررسیدشده اجرا می‌شوند. کالبک‌های تمام تایمرهای فعالی که زمان‌بندی آن‌ها قبل از زمان \fInow\fP حلقه باشد، فراخوانی می‌شوند. .IP 3. 4 اگر حلقه \fIزنده (alive)\fP باشد یک تکرار آغاز می‌شود، در غیر این صورت حلقه فوراً پایان می‌یابد. چه زمانی یک حلقه \fIزنده\fP در نظر گرفته می‌شود؟ اگر حلقه‌ای دارای هندل‌های فعال و دارای ارجاع (ref'd)، درخواست‌های فعال یا هندل‌های در حال بسته شدن باشد، \fIزنده\fP در نظر گرفته می‌شود. .IP 4. 4 کالبک‌های معوق (Pending) فراخوانی می‌شوند. در بیشتر موارد، تمام کالبک‌های ورودی/خروجی بلافاصله پس از پایش (polling) ورودی/خروجی فراخوانی می‌شوند. با این حال، مواردی وجود دارد که فراخوانی یک کالبک به تکرار بعدی حلقه موکول می‌شود. اگر تکرار قبلی کالبک ورودی/خروجی را به تعویق انداخته باشد، در این مرحله اجرا خواهد شد. .IP 5. 4 کالبک‌های هندل‌های بیکار (idle handles) فراخوانی می‌شوند. بر خلاف نام نه‌چندان مناسبشان، هندل‌های بیکار در صورت فعال بودن در تمام تکرارهای حلقه اجرا می‌شوند. .IP 6. 4 کالبک‌های هندل‌های آماده‌سازی (prepare handles) فراخوانی می‌شوند. کالبک‌های هندل‌های آماده‌سازی دقیقاً پیش از آنکه حلقه برای ورودی/خروجی مسدود شود، فراخوانی می‌شوند. .IP 7. 4 مهلت زمانی پایش (Poll timeout) محاسبه می‌شود. پیش از مسدود شدن برای ورودی/خروجی، حلقه مدت‌زمان مسدود ماندن را محاسبه می‌کند. قوانین محاسبه این مهلت زمانی به شرح زیر است: .INDENT 4.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 اگر حلقه با فلگ \fBUV_RUN_NOWAIT\fP اجرا شده باشد، مهلت زمانی 0 است. .IP \(bu 2 اگر قرار باشد حلقه متوقف شود (تابع \fBuv_stop()\fP \%<#\:c\:.uv_stop> فراخوانی شده باشد)، مهلت زمانی 0 است. .IP \(bu 2 اگر هیچ هندل یا درخواست فعالی وجود نداشته باشد، مهلت زمانی 0 است. .IP \(bu 2 اگر هرگونه هندل بیکار (idle) فعالی وجود داشته باشد، مهلت زمانی 0 است. .IP \(bu 2 اگر هندلی در انتظار بسته شدن باشد، مهلت زمانی 0 است. .IP \(bu 2 اگر هیچ‌یک از موارد بالا مطابقت نداشته باشد، مهلت زمانی نزدیک‌ترین تایمر در نظر گرفته می‌شود، یا در صورت نبود تایمر فعال، بی‌نهایت در نظر گرفته می‌شود. .UNINDENT .UNINDENT .UNINDENT .IP 8. 4 حلقه برای ورودی/خروجی مسدود می‌شود. در این مرحله حلقه برای مدتی که در گام پیشین محاسبه شد، برای ورودی/خروجی مسدود می‌ماند. تمام هندل‌های مرتبط با ورودی/خروجی که یک توصیف‌کننده فایل (file descriptor) را برای عملیات خواندن یا نوشتن تحت نظر داشتند، در این مرحله کالبک‌هایشان فراخوانی می‌شود. .IP 9. 4 کالبک‌های هندل‌های بررسی (check handles) فراخوانی می‌شوند. کالبک‌های هندل‌های بررسی بلافاصله پس از آنکه حلقه از حالت مسدود برای ورودی/خروجی خارج شد، فراخوانی می‌شوند. هندل‌های بررسی در واقع همتای هندل‌های آماده‌سازی هستند. .IP 10. 4 کالبک‌های بستن فراخوانی می‌شوند. اگر هندلی با فراخوانی \fBuv_close()\fP \%<#\:c\:.uv_close> بسته شده باشد، کالبک بستن آن فراخوانی خواهد شد. .IP 11. 4 مفهوم زمان جاری («اکنون» یا now) در حلقه به‌روزرسانی می‌شود. .IP 12. 4 تایمرهای سررسیدشده اجرا می‌شوند. توجه داشته باشید که «اکنون» تا تکرار بعدی حلقه مجدداً به‌روزرسانی نمی‌شود. بنابراین اگر تایمری در حین پردازش تایمرهای دیگر سررسید شود، تا تکرار بعدی حلقه رویداد اجرا نخواهد شد. .IP 13. 4 تکرار پایان می‌یابد. اگر حلقه در حالت‌های \fBUV_RUN_NOWAIT\fP یا \fBUV_RUN_ONCE\fP اجرا شده باشد، تکرار به پایان می‌رسد و تابع \fBuv_run()\fP \%<#\:c\:.uv_run> بازمی‌گردد. اگر حلقه با \fBUV_RUN_DEFAULT\fP اجرا شده باشد و هنوز \fIزنده\fP باشد از ابتدا ادامه می‌یابد، در غیر این صورت آن نیز پایان می‌یابد. .UNINDENT .sp \fBمهم:\fP .INDENT 0.0 .INDENT 3.5 کتابخانه libuv از یک استخر ریسه‌ها (thread pool) برای ممکن ساختن عملیات ناهمگام ورودی/خروجی فایل استفاده می‌کند، اما ورودی/خروجی شبکه \fBهمواره\fP در یک ریسه منفرد (ریسه اختصاصی هر حلقه) انجام می‌شود. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 با وجود تفاوت در سازوکار پایش (polling)، libuv مدل اجرایی یکدستی را در سیستم‌های یونیکس و ویندوز ارائه می‌دهد. .UNINDENT .UNINDENT .SS "ورودی/خروجی فایل (File I/O)" .sp برخلاف ورودی/خروجی شبکه، هیچ سازوکار پایه ورودی/خروجی فایل وابسته به سکویی وجود ندارد که libuv بتواند به آن متکی باشد، بنابراین رویکرد کنونی اجرای عملیات مسدودکننده ورودی/خروجی فایل در استخر ریسه‌ها (thread pool) است. .sp برای توضیحات جامع درباره وضعیت ورودی/خروجی فایل در سکوهای گوناگون، این مطلب را بررسی کنید: \%\&. .sp در حال حاضر libuv از یک استخر ریسه سراسری استفاده می‌کند که همه حلقه‌ها می‌توانند کارهای خود را در آن صف‌بندی کنند. در حال حاضر ۳ نوع عملیات در این استخر اجرا می‌شوند: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 عملیات سیستم فایل .IP \(bu 2 توابع DNS (مانند getaddrinfo و getnameinfo) .IP \(bu 2 کدهای مشخص‌شده توسط کاربر از طریق \fBuv_queue_work()\fP \%<#\:c\:.uv_queue_work> .UNINDENT .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 برای جزئیات بیشتر بخش زمان‌بندی کار در استخر ریسه‌ها \%<#\:threadpool> را ببینید، اما به یاد داشته باشید که اندازه استخر ریسه‌ها کاملاً محدود است. .UNINDENT .UNINDENT .SS "مستندات رابط برنامه‌نویسی (API documentation)" .SS "مدیریت خطاها (Error handling)" .sp در libuv، خطاها ثابت‌هایی با اعداد منفی هستند. به عنوان یک قاعده کلی، هر جا یک پارامتر وضعیت وجود دارد، یا یک تابع API یک عدد صحیح برمی‌گرداند، عدد منفی به معنای بروز خطا خواهد بود. .sp هنگامی که تابعی با دریافت کالبک دچار خطا می‌شود، کالبک هرگز فراخوانی نخواهد شد. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 جزئیات پیاده‌سازی: در یونیکس، کدهای خطا همان \fIerrno\fP منفی‌شده (یا \fI\-errno\fP) هستند، در حالی که در ویندوز توسط libuv به اعداد منفی دلخواه تعریف شده‌اند. .UNINDENT .UNINDENT .SS "ثابت‌های خطا (Error constants)" .INDENT 0.0 .TP .B UV_E2BIG لیست آرگومان‌ها بیش از حد طولانی است .UNINDENT .INDENT 0.0 .TP .B UV_EACCES دسترسی غیرمجاز است .UNINDENT .INDENT 0.0 .TP .B UV_EADDRINUSE آدرس قبلاً استفاده شده است .UNINDENT .INDENT 0.0 .TP .B UV_EADDRNOTAVAIL آدرس در دسترس نیست .UNINDENT .INDENT 0.0 .TP .B UV_EAFNOSUPPORT خانواده آدرس پشتیبانی نمی‌شود .UNINDENT .INDENT 0.0 .TP .B UV_EAGAIN منبع موقتاً در دسترس نیست .UNINDENT .INDENT 0.0 .TP .B UV_EAI_ADDRFAMILY خانواده آدرس پشتیبانی نمی‌شود .UNINDENT .INDENT 0.0 .TP .B UV_EAI_AGAIN شکست موقت .UNINDENT .INDENT 0.0 .TP .B UV_EAI_BADFLAGS مقدار ai_flags نامعتبر است .UNINDENT .INDENT 0.0 .TP .B UV_EAI_BADHINTS مقدار نامعتبر برای hints .UNINDENT .INDENT 0.0 .TP .B UV_EAI_CANCELED درخواست لغو شد .UNINDENT .INDENT 0.0 .TP .B UV_EAI_FAIL شکست دائمی .UNINDENT .INDENT 0.0 .TP .B UV_EAI_FAMILY مقدار ai_family پشتیبانی نمی‌شود .UNINDENT .INDENT 0.0 .TP .B UV_EAI_MEMORY کمبود حافظه .UNINDENT .INDENT 0.0 .TP .B UV_EAI_NODATA بدون آدرس .UNINDENT .INDENT 0.0 .TP .B UV_EAI_NONAME گره یا سرویس ناشناخته است .UNINDENT .INDENT 0.0 .TP .B UV_EAI_OVERFLOW سرریز بافر آرگومان .UNINDENT .INDENT 0.0 .TP .B UV_EAI_PROTOCOL پروتکل تفکیک‌شده ناشناخته است .UNINDENT .INDENT 0.0 .TP .B UV_EAI_SERVICE سرویس برای نوع سوکت در دسترس نیست .UNINDENT .INDENT 0.0 .TP .B UV_EAI_SOCKTYPE نوع سوکت پشتیبانی نمی‌شود .UNINDENT .INDENT 0.0 .TP .B UV_EALREADY اتصال از قبل در حال انجام است .UNINDENT .INDENT 0.0 .TP .B UV_EBADF توصیف‌کننده فایل نامعتبر است .UNINDENT .INDENT 0.0 .TP .B UV_EBUSY منبع مشغول یا قفل است .UNINDENT .INDENT 0.0 .TP .B UV_ECANCELED عملیات لغو شد .UNINDENT .INDENT 0.0 .TP .B UV_ECHARSET نویسه یونیکد نامعتبر است .UNINDENT .INDENT 0.0 .TP .B UV_ECONNABORTED قطع اتصال ناشی از نرم‌افزار .UNINDENT .INDENT 0.0 .TP .B UV_ECONNREFUSED اتصال رد شد .UNINDENT .INDENT 0.0 .TP .B UV_ECONNRESET اتصال توسط طرف مقابل بازنشانی شد .UNINDENT .INDENT 0.0 .TP .B UV_EDESTADDRREQ آدرس مقصد الزامی است .UNINDENT .INDENT 0.0 .TP .B UV_EEXIST فایل از قبل وجود دارد .UNINDENT .INDENT 0.0 .TP .B UV_EFAULT آدرس نامعتبر در آرگومان فراخوانی سیستمی .UNINDENT .INDENT 0.0 .TP .B UV_EFBIG فایل بیش از حد بزرگ است .UNINDENT .INDENT 0.0 .TP .B UV_EHOSTUNREACH میزبان در دسترس نیست .UNINDENT .INDENT 0.0 .TP .B UV_EINTR وقفه در فراخوانی سیستمی .UNINDENT .INDENT 0.0 .TP .B UV_EINVAL آرگومان نامعتبر است .UNINDENT .INDENT 0.0 .TP .B UV_EIO خطای ورودی/خروجی .UNINDENT .INDENT 0.0 .TP .B UV_EISCONN سوکت از قبل متصل است .UNINDENT .INDENT 0.0 .TP .B UV_EISDIR عملیات غیرمجاز روی دایرکتوری .UNINDENT .INDENT 0.0 .TP .B UV_ELOOP برخورد با پیوندهای نمادین بیش از حد .UNINDENT .INDENT 0.0 .TP .B UV_EMFILE تعداد فایل‌های باز بیش از حد است .UNINDENT .INDENT 0.0 .TP .B UV_EMSGSIZE پیام بیش از حد طولانی است .UNINDENT .INDENT 0.0 .TP .B UV_ENAMETOOLONG نام بیش از حد طولانی است .UNINDENT .INDENT 0.0 .TP .B UV_ENETDOWN شبکه قطع است .UNINDENT .INDENT 0.0 .TP .B UV_ENETUNREACH شبکه در دسترس نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENFILE سرریز جدول فایل‌ها .UNINDENT .INDENT 0.0 .TP .B UV_ENOBUFS فضای بافر در دسترس نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENODEV چنین دستگاهی وجود ندارد .UNINDENT .INDENT 0.0 .TP .B UV_ENOENT چنین فایل یا دایرکتوری وجود ندارد .UNINDENT .INDENT 0.0 .TP .B UV_ENOMEM حافظه کافی نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENONET رایانه در شبکه نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENOPROTOOPT پروتکل در دسترس نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENOSPC فضایی روی دستگاه باقی نمانده است .UNINDENT .INDENT 0.0 .TP .B UV_ENOSYS تابع پیاده‌سازی نشده است .UNINDENT .INDENT 0.0 .TP .B UV_ENOTCONN سوکت متصل نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENOTDIR دایرکتوری نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENOTEMPTY دایرکتوری خالی نیست .UNINDENT .INDENT 0.0 .TP .B UV_ENOTSOCK عملیات سوکت روی غیرسوکت .UNINDENT .INDENT 0.0 .TP .B UV_ENOTSUP عملیات روی سوکت پشتیبانی نمی‌شود .UNINDENT .INDENT 0.0 .TP .B UV_EOVERFLOW مقدار برای نوع داده تعریف‌شده بیش از حد بزرگ است .UNINDENT .INDENT 0.0 .TP .B UV_EPERM عملیات مجاز نیست .UNINDENT .INDENT 0.0 .TP .B UV_EPIPE لوله شکسته است .UNINDENT .INDENT 0.0 .TP .B UV_EPROTO خطای پروتکل .UNINDENT .INDENT 0.0 .TP .B UV_EPROTONOSUPPORT پروتکل پشتیبانی نمی‌شود .UNINDENT .INDENT 0.0 .TP .B UV_EPROTOTYPE نوع پروتکل برای سوکت نادرست است .UNINDENT .INDENT 0.0 .TP .B UV_ERANGE نتیجه بیش از حد بزرگ است .UNINDENT .INDENT 0.0 .TP .B UV_EROFS سیستم فایل فقط‌خواندنی است .UNINDENT .INDENT 0.0 .TP .B UV_ESHUTDOWN ارسال پس از خاموش شدن نقطه پایانی انتقال امکان‌پذیر نیست .UNINDENT .INDENT 0.0 .TP .B UV_ESPIPE جستجوی موقعیت نامعتبر است .UNINDENT .INDENT 0.0 .TP .B UV_ESRCH چنین فرآیندی وجود ندارد .UNINDENT .INDENT 0.0 .TP .B UV_ETIMEDOUT مهلت اتصال به پایان رسید .UNINDENT .INDENT 0.0 .TP .B UV_ETXTBSY فایل متنی مشغول است .UNINDENT .INDENT 0.0 .TP .B UV_EXDEV پیوند بین‌دستگاهی مجاز نیست .UNINDENT .INDENT 0.0 .TP .B UV_UNKNOWN خطای ناشناخته .UNINDENT .INDENT 0.0 .TP .B UV_EOF پایان فایل .UNINDENT .INDENT 0.0 .TP .B UV_ENXIO چنین دستگاه یا آدرسی وجود ندارد .UNINDENT .INDENT 0.0 .TP .B UV_EMLINK تعداد پیوندها بیش از حد است .UNINDENT .INDENT 0.0 .TP .B UV_ENOTTY دستور ioctl برای دستگاه نامناسب است .UNINDENT .INDENT 0.0 .TP .B UV_EFTYPE نوع فایل یا قالب آن نامناسب است .UNINDENT .INDENT 0.0 .TP .B UV_EILSEQ توالی بایت غیرمجاز .UNINDENT .INDENT 0.0 .TP .B UV_ESOCKTNOSUPPORT نوع سوکت پشتیبانی نمی‌شود .UNINDENT .INDENT 0.0 .TP .B UV_EUNATCH درایور پروتکل متصل نیست .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B UV_ERRNO_MAP(iter_macro) ماکرویی که به مجموعه‌ای از فراخوانی‌های \fIiter_macro\fP برای هر یک از ثابت‌های خطای فوق بسط می‌یابد. ماکروی \fIiter_macro\fP با دو آرگومان فراخوانی می‌شود: نام ثابت خطا بدون پیشوند \fIUV_\fP، و رشته متنی پیام خطا. .UNINDENT .INDENT 0.0 .TP .B const char *uv_strerror(int err) پیام خطای مربوط به کد خطای داده‌شده را برمی‌گرداند. در صورت فراخوانی با یک کد خطای ناشناخته، چند بایت حافظه نشت می‌کند. .UNINDENT .INDENT 0.0 .TP .B char *uv_strerror_r(int err, char *buf, size_t buflen) پیام خطای مربوط به کد خطای داده‌شده را برمی‌گرداند. پیام خاتمه‌یافته با صفر در بافر \fIbuf\fP ارائه‌شده توسط کاربر با حداکثر طول \fIbuflen\fP بایت ذخیره می‌شود. .sp در نسخه 1.22.0 اضافه شد. .UNINDENT .INDENT 0.0 .TP .B const char *uv_err_name(int err) نام خطای مربوط به کد خطای داده‌شده را برمی‌گرداند. در صورت فراخوانی با یک کد خطای ناشناخته، چند بایت حافظه نشت می‌کند. .UNINDENT .INDENT 0.0 .TP .B char *uv_err_name_r(int err, char *buf, size_t buflen) نام خطای مربوط به کد خطای داده‌شده را برمی‌گرداند. نام خاتمه‌یافته با صفر در بافر \fIbuf\fP ارائه‌شده توسط کاربر با حداکثر طول \fIbuflen\fP بایت ذخیره می‌شود. .sp در نسخه 1.22.0 اضافه شد. .UNINDENT .INDENT 0.0 .TP .B int uv_translate_sys_error(int sys_errno) کد خطای معادل در libuv را برای کد خطای وابسته به سکوی داده‌شده برمی‌گرداند: کدهای خطای POSIX در یونیکس (مواردی که در \fIerrno\fP ذخیره می‌شوند)، و کدهای خطای Win32 در ویندوز (مواردی که توسط \fIGetLastError()\fP یا \fIWSAGetLastError()\fP برگردانده می‌شوند). .sp اگر \fIsys_errno\fP از قبل یک خطای libuv باشد، صرفاً همان برگردانده می‌شود. .sp در نسخه 1.10.0 تغییر کرد: تابع به‌صورت عمومی اعلام شد. .UNINDENT .SS "ماکروها و توابع بررسی نسخه (Version-checking macros and functions)" .sp از نسخه 1.0.0 به بعد، libuv از طرح نسخه‌بندی معنایی \% پیروی می‌کند. این بدان معناست که در طول چرخه عمر یک انتشار اصلی می‌توان رابط‌های برنامه‌نویسی جدیدی اضافه کرد. در این بخش تمامی ماکروها و توابعی را خواهید یافت که امکان نوشتن یا کامپایل شرطی کد را برای کار با چندین نسخه مختلف libuv فراهم می‌کنند. .SS "ماکروها (Macros)" .INDENT 0.0 .TP .B UV_VERSION_MAJOR شماره اصلی نسخه libuv. .UNINDENT .INDENT 0.0 .TP .B UV_VERSION_MINOR شماره فرعی نسخه libuv. .UNINDENT .INDENT 0.0 .TP .B UV_VERSION_PATCH شماره وصله نسخه libuv. .UNINDENT .INDENT 0.0 .TP .B UV_VERSION_IS_RELEASE تنظیم روی 1 برای نشان دادن نسخه انتشار پایدار libuv، و 0 برای نسخه در حال توسعه. .UNINDENT .INDENT 0.0 .TP .B UV_VERSION_SUFFIX پسوند نسخه libuv. برخی از نسخه‌های در حال توسعه مانند کاندیداهای انتشار (Release Candidates) ممکن است دارای پسوندی مانند \(dqrc\(dq باشند. .UNINDENT .INDENT 0.0 .TP .B UV_VERSION_HEX نسخه libuv را در قالب یک عدد صحیح فشرده برمی‌گرداند. ۸ بیت برای هر مؤلفه استفاده می‌شود که شماره وصله در ۸ بیت کم‌ارزش‌تر ذخیره می‌شود. برای مثال برای libuv 1.2.3 این مقدار 0x010203 خواهد بود. .sp در نسخه 1.7.0 اضافه شد. .UNINDENT .SS "توابع (Functions)" .INDENT 0.0 .TP .B unsigned int uv_version(void) مقدار \fBUV_VERSION_HEX\fP را برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B const char *uv_version_string(void) شماره نسخه libuv را به صورت یک رشته برمی‌گرداند. برای نسخه‌های غیر انتشار، پسوند نسخه نیز گنجانده می‌شود. .UNINDENT .SS \fBuv_loop_t\fP \-\-\- حلقه رویداد (Event loop) .sp حلقه رویداد (Event loop) بخش مرکزی و هسته اصلی قابلیت‌های libuv است. این حلقه وظیفه سرکشی (polling) برای ورودی/خروجی (I/O) و زمان‌بندی اجرای توابع بازخوانی (callbacks) را بر اساس منابع مختلف رویداد بر عهده دارد. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_loop_t نوع داده حلقه رویداد. .UNINDENT .INDENT 0.0 .TP .B enum uv_loop_option گزینه‌های تکمیلی حلقه رویداد. ببینید: \fBuv_loop_configure()\fP\&. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_LOOP_BLOCK_SIGNAL = 0, UV_METRICS_IDLE_TIME, UV_LOOP_USE_IO_URING_SQPOLL } uv_loop_option; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_run_mode حالت مورد استفاده برای اجرای حلقه با \fBuv_run()\fP\&. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_RUN_DEFAULT = 0, UV_RUN_ONCE, UV_RUN_NOWAIT } uv_run_mode; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_walk_cb)(uv_handle_t \%<#\:c\:.uv_handle_t> *handle, void *arg) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_walk()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B void *uv_loop_t \%<#\:c\:.uv_loop_t>\&.data فضایی برای نگهداری داده‌های دلخواه تعریف‌شده توسط کاربر. libuv از این فیلد استفاده نمی‌کند و دست به آن نمی‌زند. .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_loop_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop) ساختار \fIuv_loop_t\fP داده‌شده را مقداردهی اولیه می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_loop_configure(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_loop_option \%<#\:c\:.uv_loop_option> option, \&...) اضافه‌شده در نسخه 1.0.2. .sp تنظیم گزینه‌های تکمیلی حلقه رویداد. معمولاً باید این تابع را قبل از اولین فراخوانی \fBuv_run()\fP صدا بزنید مگر اینکه خلاف آن ذکر شده باشد. .sp در صورت موفقیت مقدار 0 و در صورت شکست کد خطای UV_E* برمی‌گرداند. برای مدیریت خطای UV_ENOSYS آماده باشید؛ این خطا به این معنی است که گزینه حلقه توسط پلتفرم پشتیبانی نمی‌شود. .sp گزینه‌های پشتیبانی‌شده: .INDENT 7.0 .IP \(bu 2 UV_LOOP_BLOCK_SIGNAL: مسدود کردن یک سیگنال هنگام سرکشی (polling) برای رویدادهای جدید. آرگومان دوم به \fBuv_loop_configure()\fP شماره سیگنال است. .sp این عملیات در حال حاضر فقط برای سیگنال‌های SIGPROF پیاده‌سازی شده است تا از بیدارباش‌های غیرضروری هنگام استفاده از نمونه‌بردار کارایی (sampling profiler) جلوگیری شود. درخواست سایر سیگنال‌ها با خطای UV_EINVAL مواجه خواهد شد. .IP \(bu 2 UV_METRICS_IDLE_TIME: انباشت مقدار زمان بی‌کاری که حلقه رویداد در ارائه‌دهنده رویداد (event provider) سپری می‌کند. .sp این گزینه برای استفاده از \fBuv_metrics_idle_time()\fP \%<#\:c\:.uv_metrics_idle_time> ضروری است. .IP \(bu 2 UV_LOOP_USE_IO_URING_SQPOLL: فعال‌سازی نمونه SQPOLL io_uring برای مدیریت عملیات ناهمگام سیستم فایل. .UNINDENT .sp تغییریافته در نسخه 1.39.0: گزینه UV_METRICS_IDLE_TIME اضافه شد. .sp تغییریافته در نسخه 1.49.0: گزینه UV_LOOP_USE_IO_URING_SQPOLL اضافه شد. .UNINDENT .INDENT 0.0 .TP .B int uv_loop_close(uv_loop_t \%<#\:c\:.uv_loop_t> *loop) تمام منابع داخلی حلقه را آزاد می‌کند. این تابع را تنها زمانی فراخوانی کنید که اجرای حلقه به پایان رسیده باشد و تمام هندل‌ها و درخواست‌های باز بسته شده باشند، در غیر این صورت مقدار UV_EBUSY را برمی‌گرداند. پس از بازگشت این تابع، کاربر می‌تواند حافظه تخصیص‌یافته برای حلقه را آزاد کند. .UNINDENT .INDENT 0.0 .TP .B uv_loop_t \%<#\:c\:.uv_loop_t> *uv_default_loop(void) حلقه پیش‌فرض مقداردهی‌شده را برمی‌گرداند. در صورت شکست در تخصیص حافظه ممکن است NULL برگرداند. .sp این تابع صرفاً روشی مناسب برای داشتن یک حلقه سراسری در سرتاسر برنامه است، حلقه پیش‌فرض به هیچ وجه تفاوتی با حلقه‌های مقداردهی‌شده توسط \fBuv_loop_init()\fP ندارد. به همین ترتیب، حلقه پیش‌فرض می‌تواند (و باید) با \fBuv_loop_close()\fP بسته شود تا منابع مرتبط با آن آزاد شوند. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع از نظر ریسه‌ها امن نیست (thread-safe نیست). .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_run(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_run_mode \%<#\:c\:.uv_run_mode> mode) این تابع حلقه رویداد را اجرا می‌کند. رفتار آن بسته به حالت مشخص‌شده متفاوت خواهد بود: .INDENT 7.0 .IP \(bu 2 UV_RUN_DEFAULT: حلقه رویداد را تا زمانی که هیچ هندل یا درخواست فعال و ارجاع‌شده‌ای باقی نمانده باشد اجرا می‌کند. اگر \fBuv_stop()\fP فراخوانی شده باشد و همچنان هندل‌ها یا درخواست‌های فعالی وجود داشته باشند، مقدار غیرصفر برمی‌گرداند. در سایر موارد مقدار صفر برمی‌گرداند. .IP \(bu 2 UV_RUN_ONCE: یک بار برای ورودی/خروجی سرکشی (poll) می‌کند. توجه داشته باشید که اگر هیچ تابع بازخوانی معلقی وجود نداشته باشد، این تابع مسدود (block) می‌شود. در صورت اتمام (عدم وجود هندل یا درخواست فعال باقی‌مانده) مقدار صفر، یا اگر انتظار بازخوانی‌های بیشتری می‌رود (به این معنی که باید حلقه رویداد را در آینده دوباره اجرا کنید) مقدار غیرصفر برمی‌گرداند. .IP \(bu 2 UV_RUN_NOWAIT: یک بار برای ورودی/خروجی سرکشی می‌کند اما اگر هیچ تابع بازخوانی معلقی وجود نداشته باشد مسدود نمی‌شود. در صورت اتمام (عدم وجود هندل یا درخواست فعال باقی‌مانده) مقدار صفر، یا اگر انتظار بازخوانی‌های بیشتری می‌رود مقدار غیرصفر برمی‌گرداند. .UNINDENT .sp تابع \fBuv_run()\fP بازگشت‌پذیر مجدد (reentrant) نیست. نباید آن را از درون یک تابع بازخوانی فراخوانی کرد. .UNINDENT .INDENT 0.0 .TP .B int uv_loop_alive(const uv_loop_t \%<#\:c\:.uv_loop_t> *loop) اگر هندل‌های فعال دارای ارجاع، درخواست‌های فعال یا هندل‌های در حال بسته شدن در حلقه وجود داشته باشند، مقدار غیرصفر برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B void uv_stop(uv_loop_t \%<#\:c\:.uv_loop_t> *loop) حلقه رویداد را متوقف می‌کند و باعث می‌شود \fBuv_run()\fP در سریع‌ترین زمان ممکن به پایان برسد. این اتفاق زودتر از تکرار (iteration) بعدی حلقه رخ نخواهد داد. اگر این تابع قبل از مسدود شدن برای ورودی/خروجی فراخوانی شده باشد، حلقه در این تکرار برای ورودی/خروجی مسدود نخواهد شد. .UNINDENT .INDENT 0.0 .TP .B size_t uv_loop_size(void) اندازه ساختار \fIuv_loop_t\fP را برمی‌گرداند. برای نویسندگان بایندرهای FFI که مایل به دانستن ساختار درونی نیستند مفید است. .UNINDENT .INDENT 0.0 .TP .B int uv_backend_fd(const uv_loop_t \%<#\:c\:.uv_loop_t> *loop) توصیف‌کننده فایل (file descriptor) بک‌اند را دریافت می‌کند. فقط kqueue، epoll و event ports پشتیبانی می‌شوند. .sp این تابع می‌تواند همراه با \fIuv_run(loop, UV_RUN_NOWAIT)\fP برای سرکشی در یک ریسه (thread) و اجرای توابع بازخوانی حلقه رویداد در ریسه‌ای دیگر استفاده شود؛ برای مشاهده مثال به test/test\-embed.c مراجعه کنید. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 جاسازی fd مربوط به kqueue در مجموعه سرکشی (pollset) دیگر kqueue روی همه پلتفرم‌ها کار نمی‌کند. افزودن fd خطا نیست اما هرگز رویدادی تولید نمی‌کند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_backend_timeout(const uv_loop_t \%<#\:c\:.uv_loop_t> *loop) مهلت زمانی سرکشی (poll timeout) را برمی‌گرداند. مقدار برگشتی به میلی‌ثانیه است، یا \-1 برای عدم وجود مهلت زمانی. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_now(const uv_loop_t \%<#\:c\:.uv_loop_t> *loop) برچسب زمانی فعلی را به میلی‌ثانیه برمی‌گرداند. این برچسب زمانی در ابتدای تیک حلقه رویداد ذخیره (cache) می‌شود؛ برای جزئیات و دلایل آن به \fBuv_update_time()\fP مراجعه کنید. .sp برچسب زمانی به صورت یکنواخت (monotonically) از یک نقطه زمانی دلخواه افزایش می‌یابد. هیچ فرضی درباره نقطه شروع در نظر نگیرید. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 اگر به دقت زیر میلی‌ثانیه نیاز دارید از \fBuv_hrtime()\fP \%<#\:c\:.uv_hrtime> استفاده کنید. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B void uv_update_time(uv_loop_t \%<#\:c\:.uv_loop_t> *loop) مفهوم «اکنون» (now) را در حلقه رویداد به‌روزرسانی می‌کند. Libuv زمان فعلی را در ابتدای تیک حلقه رویداد ذخیره (cache) می‌کند تا تعداد فراخوانی‌های سیستمی مرتبط با زمان کاهش یابد. .sp معمولاً نیازی به فراخوانی این تابع نخواهید داشت مگر اینکه توابع بازخوانی داشته باشید که حلقه رویداد را برای مدت طولانی مسدود کنند، جایی که «طولانی» تا حدی نسبی است اما معمولاً در مقیاس یک میلی‌ثانیه یا بیشتر است. .UNINDENT .INDENT 0.0 .TP .B void uv_walk(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_walk_cb \%<#\:c\:.uv_walk_cb> walk_cb, void *arg) پیمایش لیست هندل‌ها: تابع \fIwalk_cb\fP با آرگومان \fIarg\fP داده‌شده اجرا خواهد شد. .UNINDENT .INDENT 0.0 .TP .B int uv_loop_fork(uv_loop_t \%<#\:c\:.uv_loop_t> *loop) اضافه‌شده در نسخه 1.12.0. .sp مقداردهی مجدد هرگونه وضعیت کرنل لازم در فرآیند فرزند پس از یک فراخوانی سیستمی fork(2) \%\&. .sp پایشگرهایی (watchers) که قبلاً شروع شده‌اند، در فرآیند فرزند نیز به کار خود ادامه خواهند داد. .sp فراخوانی صریح این تابع روی هر حلقه رویدادی که در فرآیند والد ایجاد شده و قصد ادامه استفاده از آن در فرآیند فرزند را دارید ضروری است، از جمله حلقه پیش‌فرض (حتی اگر دیگر در والد از آن استفاده نکنید). این تابع باید قبل از فراخوانی \fBuv_run()\fP یا هر تابع API دیگر که از حلقه در فرزند استفاده می‌کند فراخوانی شود. عدم انجام این کار منجر به رفتار تعریف‌نشده خواهد شد، از جمله احتمال تحویل رویدادهای تکراری به هر دو فرآیند والد و فرزند یا متوقف شدن غیرمنتظره فرآیند فرزند. .sp در صورت امکان، ترجیح داده می‌شود به جای استفاده مجدد از حلقه‌ای که در والد ایجاد شده، یک حلقه جدید در فرآیند فرزند ایجاد شود. حلقه‌های جدیدی که در فرآیند فرزند پس از fork ایجاد می‌شوند نباید از این تابع استفاده کنند. .sp این تابع روی ویندوز پیاده‌سازی نشده است و در آنجا مقدار \fBUV_ENOSYS\fP را برمی‌گرداند. .sp \fBاحتیاط:\fP .INDENT 7.0 .INDENT 3.5 این تابع آزمایشی است. ممکن است دارای باگ باشد و ممکن است تغییر کند یا حذف شود. پایداری API و ABI تضمین نمی‌شود. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در Mac OS X، اگر از هندل‌های رویداد سیستم فایل (FS event) پوشه در فرآیند والد \fIبرای هر حلقه رویدادی\fP استفاده شده باشد، فرآیند فرزند دیگر قادر به استفاده از کارآمدترین پیاده‌سازی FSEvent نخواهد بود. در عوض، استفاده از هندل‌های FS event پوشه در فرآیند فرزند به همان پیاده‌سازی استفاده‌شده برای فایل‌ها و سایر سیستم‌های مبتنی بر kqueue تنزل خواهد یافت. .UNINDENT .UNINDENT .sp \fBاحتیاط:\fP .INDENT 7.0 .INDENT 3.5 در AIX و SunOS، هندل‌های رویداد سیستم فایل که در زمان انشعاب (forking) از قبل در فرآیند والد شروع شده بودند، در فرآیند فرزند رویدادی تحویل \fIنخواهند داد\fP؛ آنها باید بسته شده و مجدداً راه‌اندازی شوند. در تمام پلتفرم‌های دیگر، آنها بدون نیاز به اقدام دیگری به طور عادی به کار خود ادامه می‌دهند. .UNINDENT .UNINDENT .sp \fBاحتیاط:\fP .INDENT 7.0 .INDENT 3.5 هر مقدار بازگشتی قبلی از \fBuv_backend_fd()\fP اکنون نامعتبر است. آن تابع باید دوباره فراخوانی شود تا توصیف‌کننده فایل بک‌اند صحیح مشخص گردد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B void *uv_loop_get_data(const uv_loop_t \%<#\:c\:.uv_loop_t> *loop) مقدار \fIloop\->data\fP را برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B void uv_loop_set_data(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, void *data) مقدار \fIloop\->data\fP را روی \fIdata\fP تنظیم می‌کند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .SS \fBuv_handle_t\fP \-\-\- هندل پایه (Base handle) .sp ساختار \fIuv_handle_t\fP نوع پایه برای تمامی انواع هندل‌ها در libuv است. .sp ساختارها به گونه‌ای تراز شده‌اند که هر هندل libuv را می‌توان به \fIuv_handle_t\fP تبدیل (cast) کرد. تمامی توابع API تعریف‌شده در اینجا با هر نوع هندلی کار می‌کنند. .sp هندل‌های Libuv غیرقابل جابه‌جایی (non-movable) هستند. اشاره‌گرهای ساختار هندل که به توابع ارسال می‌شوند باید در طول مدت عملیات درخواستی معتبر باقی بمانند. هنگام استفاده از هندل‌های تخصیص‌یافته در پشته (stack) دقت کنید. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_handle_t نوع هندل پایه در libuv. .UNINDENT .INDENT 0.0 .TP .B enum uv_handle_type نوع هندل libuv. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_UNKNOWN_HANDLE = 0, UV_ASYNC, UV_CHECK, UV_FS_EVENT, UV_FS_POLL, UV_HANDLE, UV_IDLE, UV_NAMED_PIPE, UV_POLL, UV_PREPARE, UV_PROCESS, UV_STREAM, UV_TCP, UV_TIMER, UV_TTY, UV_UDP, UV_SIGNAL, UV_FILE, UV_HANDLE_TYPE_MAX } uv_handle_type; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_any_handle اجتماع (Union) تمام انواع هندل‌ها. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_alloc_cb)(uv_handle_t \%<#\:c\:.uv_handle_t> *handle, size_t suggested_size, uv_buf_t \%<#\:c\:.uv_buf_t> *buf) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_read_start()\fP \%<#\:c\:.uv_read_start> و \fBuv_udp_recv_start()\fP \%<#\:c\:.uv_udp_recv_start>\&. کاربر باید حافظه تخصیص دهد و ساختار \fBuv_buf_t\fP \%<#\:c\:.uv_buf_t> داده‌شده را پر کند. اگر مقدار NULL به عنوان پایه بافر (base) یا 0 به عنوان طول آن تعیین شود، خطای \fBUV_ENOBUFS\fP در بازخوانی \fBuv_udp_recv_cb\fP \%<#\:c\:.uv_udp_recv_cb> یا \fBuv_read_cb\fP \%<#\:c\:.uv_read_cb> فعال خواهد شد. .sp هر بافر فقط یک بار استفاده می‌شود و کاربر مسئول آزادسازی آن در تابع بازخوانی \fBuv_udp_recv_cb\fP \%<#\:c\:.uv_udp_recv_cb> یا \fBuv_read_cb\fP \%<#\:c\:.uv_read_cb> است. .sp یک اندازه پیشنهادی (در حال حاضر در بیشتر موارد 65536) ارائه می‌شود، اما این صرفاً یک پیشنهاد است و ارتباطی با داده‌های معلق برای خواندن ندارد. کاربر در تخصیص میزان حافظه دلخواه خود آزاد است. .sp به عنوان مثال، برنامه‌هایی با الگوهای تخصیص سفارشی مانند استفاده از freelistها، استخرهای تخصیص (allocation pools) یا تخصیص‌دهنده‌های مبتنی بر slab ممکن است تصمیم بگیرند از اندازه متفاوتی متناسب با قطعات حافظه‌ای که از قبل در اختیار دارند استفاده کنند. .sp مثال: .INDENT 7.0 .INDENT 3.5 .sp .EX static void my_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { buf\->base = malloc(suggested_size); buf\->len = suggested_size; } .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_close_cb)(uv_handle_t \%<#\:c\:.uv_handle_t> *handle) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_close()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B uv_loop_t \%<#\:c\:.uv_loop_t> *uv_handle_t \%<#\:c\:.uv_handle_t>\&.loop اشاره‌گر به \fBuv_loop_t\fP \%<#\:c\:.uv_loop_t> که هندل روی آن در حال اجرا است. فقط‌خواندنی. .UNINDENT .INDENT 0.0 .TP .B uv_handle_type \%<#\:c\:.uv_handle_type> uv_handle_t \%<#\:c\:.uv_handle_t>\&.type مقدار \fBuv_handle_type\fP که نوع هندل زیرین را مشخص می‌کند. فقط‌خواندنی. .UNINDENT .INDENT 0.0 .TP .B void *uv_handle_t \%<#\:c\:.uv_handle_t>\&.data فضایی برای نگهداری داده‌های دلخواه تعریف‌شده توسط کاربر. libuv از این فیلد استفاده نمی‌کند. .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B UV_HANDLE_TYPE_MAP(iter_macro) ماکرویی که به مجموعه‌ای از فراخوانی‌های \fIiter_macro\fP برای هر یک از انواع هندل باز می‌شود. ماکروی \fIiter_macro\fP با دو آرگومان فراخوانی می‌شود: نام عنصر \fIuv_handle_type\fP بدون پیشوند \fIUV_\fP، و نام نوع ساختار متناظر بدون پیشوند \fIuv_\fP و پسوند \fI_t\fP. .UNINDENT .INDENT 0.0 .TP .B int uv_is_active(const uv_handle_t \%<#\:c\:.uv_handle_t> *handle) در صورتی که هندل فعال باشد مقدار غیرصفر و اگر غیرفعال باشد مقدار صفر را برمی‌گرداند. معنای «فعال» به نوع هندل بستگی دارد: .INDENT 7.0 .IP \(bu 2 یک هندل uv_async_t همیشه فعال است و نمی‌توان آن را غیرفعال کرد، مگر با بستن آن از طریق uv_close(). .IP \(bu 2 هندل‌های uv_pipe_t، uv_tcp_t، uv_udp_t و غیره \- اساساً هر هندلی که با ورودی/خروجی سروکار دارد \- زمانی فعال است که کاری مرتبط با ورودی/خروجی انجام می‌دهد، مانند خواندن، نوشتن، اتصال، پذیرش اتصالات جدید و غیره. .IP \(bu 2 هندل‌های uv_check_t، uv_idle_t، uv_timer_t و غیره زمانی فعال هستند که با فراخوانی uv_check_start()، uv_idle_start() و غیره راه‌اندازی شده باشند. .UNINDENT .sp قاعده سرانگشتی: اگر یک هندل از نوع \fIuv_foo_t\fP تابعی به نام \fIuv_foo_start()\fP دارد، از لحظه فراخوانی آن تابع فعال است. به طور مشابه، \fIuv_foo_stop()\fP مجدداً هندل را غیرفعال می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_is_closing(const uv_handle_t \%<#\:c\:.uv_handle_t> *handle) در صورتی که هندل در حال بسته شدن یا بسته شده باشد مقدار غیرصفر و در غیر این صورت صفر برمی‌گرداند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این تابع فقط باید بین مقداردهی اولیه هندل و رسیدن بازخوانی بستن (close callback) استفاده شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B void uv_close(uv_handle_t \%<#\:c\:.uv_handle_t> *handle, uv_close_cb \%<#\:c\:.uv_close_cb> close_cb) درخواست بسته شدن هندل. تابع \fIclose_cb\fP پس از این فراخوانی به صورت ناهمگام صدا زده خواهد شد. این تابع الزماً باید قبل از آزادسازی حافظه روی هر هندل فراخوانی شود. علاوه بر این، حافظه فقط در \fIclose_cb\fP یا پس از بازگشت آن قابل آزادسازی است. .sp هندل‌هایی که توصیف‌کننده‌های فایل را در بر می‌گیرند بلافاصله بسته می‌شوند اما \fIclose_cb\fP همچنان به تکرار بعدی حلقه رویداد موکول می‌شود. این به شما فرصت می‌دهد تا هرگونه منبع مرتبط با هندل را آزاد کنید. .sp درخواست‌های در حال انجام، مانند uv_connect_t یا uv_write_t، لغو می‌شوند و بازخوانی‌های آن‌ها به صورت ناهمگام با وضعیت status=UV_ECANCELED فراخوانی می‌شوند. .sp در مواردی که پاک‌سازی یا آزادسازی حافظه لازم نیست، \fIclose_cb\fP می‌تواند \fINULL\fP باشد. .UNINDENT .INDENT 0.0 .TP .B void uv_ref(uv_handle_t \%<#\:c\:.uv_handle_t> *handle) ارجاع به هندل داده‌شده اضافه می‌کند. ارجاع‌ها خودتوان (idempotent) هستند، یعنی اگر هندلی از قبل ارجاع داده شده باشد، فراخوانی مجدد این تابع اثری نخواهد داشت. .sp ببینید: شمارش ارجاع (Reference counting)\&. .UNINDENT .INDENT 0.0 .TP .B void uv_unref(uv_handle_t \%<#\:c\:.uv_handle_t> *handle) ارجاع از هندل داده‌شده را حذف می‌کند. ارجاع‌ها خودتوان هستند، یعنی اگر هندل ارجاعی نداشته باشد، فراخوانی مجدد این تابع اثری نخواهد داشت. .sp ببینید: شمارش ارجاع (Reference counting)\&. .UNINDENT .INDENT 0.0 .TP .B int uv_has_ref(const uv_handle_t \%<#\:c\:.uv_handle_t> *handle) اگر هندل دارای ارجاع باشد مقدار غیرصفر و در غیر این صورت صفر برمی‌گرداند. .sp ببینید: شمارش ارجاع (Reference counting)\&. .UNINDENT .INDENT 0.0 .TP .B size_t uv_handle_size(uv_handle_type \%<#\:c\:.uv_handle_type> type) اندازه نوع هندل داده‌شده را برمی‌گرداند. برای نویسندگان بایندرهای FFI که مایل به دانستن ساختار درونی نیستند مفید است. .UNINDENT .SS "توابع متفرقه رابط برنامه‌نویسی (Miscellaneous API functions)" .sp توابع API زیر یک آرگومان \fBuv_handle_t\fP دریافت می‌کنند اما فقط برای برخی از انواع هندل کار می‌کنند. .INDENT 0.0 .TP .B int uv_send_buffer_size(uv_handle_t \%<#\:c\:.uv_handle_t> *handle, int *value) اندازه بافر ارسالی که سیستم‌عامل برای سوکت استفاده می‌کند را دریافت یا تنظیم می‌کند. .sp اگر \fI*value\fP == 0 باشد، مقدار \fI*value\fP را روی اندازه فعلی بافر ارسال تنظیم می‌کند. اگر \fI*value\fP > 0 باشد، از \fI*value\fP برای تنظیم اندازه جدید بافر ارسال استفاده می‌کند. .sp در صورت موفقیت صفر و در صورت بروز خطا یک مقدار منفی برمی‌گرداند. .sp این تابع برای هندل‌های TCP، پایپ و UDP در یونیکس و برای هندل‌های TCP و UDP در ویندوز کار می‌کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 لینوکس دو برابر اندازه را تنظیم می‌کند و دو برابر مقدار تنظیم‌شده اصلی را برمی‌گرداند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_recv_buffer_size(uv_handle_t \%<#\:c\:.uv_handle_t> *handle, int *value) اندازه بافر دریافتی که سیستم‌عامل برای سوکت استفاده می‌کند را دریافت یا تنظیم می‌کند. .sp اگر \fI*value\fP == 0 باشد، مقدار \fI*value\fP را روی اندازه فعلی بافر دریافت تنظیم می‌کند. اگر \fI*value\fP > 0 باشد، از \fI*value\fP برای تنظیم اندازه جدید بافر دریافت استفاده می‌کند. .sp در صورت موفقیت صفر و در صورت بروز خطا یک مقدار منفی برمی‌گرداند. .sp این تابع برای هندل‌های TCP، پایپ و UDP در یونیکس و برای هندل‌های TCP و UDP در ویندوز کار می‌کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 لینوکس دو برابر اندازه را تنظیم می‌کند و دو برابر مقدار تنظیم‌شده اصلی را برمی‌گرداند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fileno(const uv_handle_t \%<#\:c\:.uv_handle_t> *handle, uv_os_fd_t \%<#\:c\:.uv_os_fd_t> *fd) معادل توصیف‌کننده فایل وابسته به پلتفرم را دریافت می‌کند. .sp هندل‌های زیر پشتیبانی می‌شوند: TCP، پایپ‌ها، TTY، UDP و poll. ارسال هر نوع هندل دیگر با خطای \fIUV_EINVAL\fP شکست خواهد خورد. .sp اگر هندلی هنوز توصیف‌کننده فایل متصل نداشته باشد یا خود هندل بسته شده باشد، این تابع \fIUV_EBADF\fP را برمی‌گرداند. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 هنگام استفاده از این تابع بسیار مراقب باشید. libuv فرض می‌کند کنترل توصیف‌کننده فایل در اختیار خودش است، بنابراین هرگونه تغییر در آن ممکن است منجر به اختلال در عملکرد شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B uv_loop_t \%<#\:c\:.uv_loop_t> *uv_handle_get_loop(const uv_handle_t \%<#\:c\:.uv_handle_t> *handle) مقدار \fIhandle\->loop\fP را برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B void *uv_handle_get_data(const uv_handle_t \%<#\:c\:.uv_handle_t> *handle) مقدار \fIhandle\->data\fP را برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B void uv_handle_set_data(uv_handle_t \%<#\:c\:.uv_handle_t> *handle, void *data) مقدار \fIhandle\->data\fP را روی \fIdata\fP تنظیم می‌کند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B uv_handle_type \%<#\:c\:.uv_handle_type> uv_handle_get_type(const uv_handle_t \%<#\:c\:.uv_handle_t> *handle) مقدار \fIhandle\->type\fP را برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B const char *uv_handle_type_name(uv_handle_type \%<#\:c\:.uv_handle_type> type) نام ساختار معادل را برای یک نوع هندل داده‌شده برمی‌گرداند، مثلاً \fI\(dqpipe\(dq\fP (همانند \fBuv_pipe_t\fP \%<#\:c\:.uv_pipe_t>) برای \fIUV_NAMED_PIPE\fP\&. .sp اگر چنین نوع هندلی وجود نداشته باشد، مقدار \fINULL\fP برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .SS "شمارش ارجاع (Reference counting)" .sp حلقه رویداد libuv (اگر در حالت پیش‌فرض اجرا شود) تا زمانی اجرا می‌شود که هیچ هندل فعال \fIو\fP دارای ارجاعی باقی نمانده باشد. کاربر می‌تواند با حذف ارجاع از هندل‌های فعال، حلقه را وادار به خروج زودهنگام کند؛ برای مثال با فراخوانی \fBuv_unref()\fP پس از فراخوانی \fBuv_timer_start()\fP \%<#\:c\:.uv_timer_start>\&. .sp یک هندل می‌تواند ارجاع‌دار یا بدون‌ارجاع باشد، طرح شمارش ارجاع از یک شمارنده استفاده نمی‌کند، بنابراین هر دو عملیات خودتوان (idempotent) هستند. .sp تمام هندل‌ها هنگام فعال بودن به طور پیش‌فرض ارجاع دارند؛ برای توضیح دقیق‌تر درباره اینکه \fIفعال\fP بودن شامل چه مواردی است به \fBuv_is_active()\fP مراجعه کنید. .SS \fBuv_req_t\fP \-\-\- درخواست پایه (Base request) .sp ساختار \fIuv_req_t\fP نوع پایه برای تمامی انواع درخواست‌ها در libuv است. .sp ساختارها به گونه‌ای تراز شده‌اند که هر درخواست libuv را می‌توان به \fIuv_req_t\fP تبدیل (cast) کرد. تمامی توابع API تعریف‌شده در اینجا با هر نوع درخواستی کار می‌کنند. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_req_t ساختار پایه درخواست libuv. .UNINDENT .INDENT 0.0 .TP .B type uv_any_req اجتماع (Union) تمام انواع درخواست‌ها. .UNINDENT .INDENT 0.0 .TP .B enum uv_req_type نوع درخواست libuv. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_UNKNOWN_REQ = 0, UV_REQ, UV_CONNECT, UV_WRITE, UV_SHUTDOWN, UV_UDP_SEND, UV_FS, UV_WORK, UV_GETADDRINFO, UV_GETNAMEINFO, UV_REQ_TYPE_MAX, } uv_req_type; .EE .UNINDENT .UNINDENT .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B void *uv_req_t \%<#\:c\:.uv_req_t>\&.data فضایی برای نگهداری داده‌های دلخواه تعریف‌شده توسط کاربر. libuv از این فیلد استفاده نمی‌کند. .UNINDENT .INDENT 0.0 .TP .B uv_req_type \%<#\:c\:.uv_req_type> uv_req_t \%<#\:c\:.uv_req_t>\&.type مقدار \fBuv_req_type\fP که نوع درخواست را مشخص می‌کند. فقط‌خواندنی. .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B UV_REQ_TYPE_MAP(iter_macro) ماکرویی که به مجموعه‌ای از فراخوانی‌های \fIiter_macro\fP برای هر یک از انواع درخواست باز می‌شود. ماکروی \fIiter_macro\fP با دو آرگومان فراخوانی می‌شود: نام عنصر \fIuv_req_type\fP بدون پیشوند \fIUV_\fP، و نام نوع ساختار متناظر بدون پیشوند \fIuv_\fP و پسوند \fI_t\fP. .UNINDENT .INDENT 0.0 .TP .B int uv_cancel(uv_req_t \%<#\:c\:.uv_req_t> *req) لغو یک درخواست معلق. اگر درخواست در حال اجرا باشد یا اجرای آن به پایان رسیده باشد با شکست مواجه می‌شود. .sp در صورت موفقیت مقدار 0 و در صورت شکست کد خطای < 0 برمی‌گرداند. .sp در حال حاضر فقط لغو درخواست‌های \fBuv_fs_t\fP \%<#\:c\:.uv_fs_t>، \fBuv_getaddrinfo_t\fP \%<#\:c\:.uv_getaddrinfo_t>، \fBuv_getnameinfo_t\fP \%<#\:c\:.uv_getnameinfo_t>، \fBuv_random_t\fP \%<#\:c\:.uv_random_t> و \fBuv_work_t\fP \%<#\:c\:.uv_work_t> پشتیبانی می‌شود. .sp توابع بازخوانی درخواست‌های لغوشده در زمانی در آینده فراخوانی خواهند شد. آزادسازی حافظه مرتبط با درخواست تا قبل از فراخوانی تابع بازخوانی امن \fBنیست\fP. .sp نحوه گزارش لغو به تابع بازخوانی به شرح زیر است: .INDENT 7.0 .IP \(bu 2 فیلد req\->result در یک درخواست \fBuv_fs_t\fP \%<#\:c\:.uv_fs_t> روی \fIUV_ECANCELED\fP تنظیم می‌شود. .IP \(bu 2 تابع بازخوانی یک درخواست \fBuv_work_t\fP \%<#\:c\:.uv_work_t>، \fBuv_getaddrinfo_t\fP \%<#\:c\:.uv_getaddrinfo_t>، \fBuv_getnameinfo_t\fP \%<#\:c\:.uv_getnameinfo_t> یا \fBuv_random_t\fP \%<#\:c\:.uv_random_t> با مقدار status == \fIUV_ECANCELED\fP فراخوانی می‌شود. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B size_t uv_req_size(uv_req_type \%<#\:c\:.uv_req_type> type) اندازه نوع درخواست داده‌شده را برمی‌گرداند. برای نویسندگان بایندرهای FFI که مایل به دانستن ساختار درونی نیستند مفید است. .UNINDENT .INDENT 0.0 .TP .B void *uv_req_get_data(const uv_req_t \%<#\:c\:.uv_req_t> *req) مقدار \fIreq\->data\fP را برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B void uv_req_set_data(uv_req_t \%<#\:c\:.uv_req_t> *req, void *data) مقدار \fIreq\->data\fP را روی \fIdata\fP تنظیم می‌کند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B uv_req_type \%<#\:c\:.uv_req_type> uv_req_get_type(const uv_req_t \%<#\:c\:.uv_req_t> *req) مقدار \fIreq\->type\fP را برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B const char *uv_req_type_name(uv_req_type \%<#\:c\:.uv_req_type> type) نام ساختار معادل را برای یک نوع درخواست داده‌شده برمی‌گرداند، مثلاً \fI\(dqconnect\(dq\fP (همانند \fBuv_connect_t\fP \%<#\:c\:.uv_connect_t>) برای \fIUV_CONNECT\fP\&. .sp اگر چنین نوع درخواستی وجود نداشته باشد، مقدار \fINULL\fP برمی‌گرداند. .sp اضافه‌شده در نسخه 1.19.0. .UNINDENT .SS \fBuv_timer_t\fP \-\-\- هندل تایمر (Timer handle) .sp هندل‌های تایمر برای زمان‌بندی فراخوانی توابع بازخوانی در آینده استفاده می‌شوند. .sp تایمرها یا تک‌باره (single-shot) هستند یا تکرارشونده. تایمرهای تکرارشونده سربار زمانی را تنظیم نمی‌کنند بلکه نسبت به مفهوم «اکنون» در حلقه رویداد مجدداً آماده‌باش (rearm) می‌شوند. .sp Libuv مفهوم «اکنون» خود را درست پیش از اجرای بازخوانی‌های تایمر و بلافاصله پس از بیدار شدن از انتظار برای ورودی/خروجی به‌روزرسانی می‌کند. همچنین ببینید: \fBuv_update_time()\fP \%<#\:c\:.uv_update_time>\&. .sp مثال: یک تایمر تکرارشونده با بازه 50 میلی‌ثانیه‌ای که اجرای بازخوانی آن 17 میلی‌ثانیه طول می‌کشد، 33 میلی‌ثانیه بعد دوباره اجرا می‌شود. اگر کارهای دیگر بیشتر از 33 میلی‌ثانیه طول بکشند، بازخوانی تایمر در سریع‌ترین زمان ممکن اجرا خواهد شد. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_timer_t نوع هندل تایمر. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_timer_cb)(uv_timer_t \%<#\:c\:.uv_timer_t> *handle) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_timer_start()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .sp موردی وجود ندارد (N/A) .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_timer_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_timer_t \%<#\:c\:.uv_timer_t> *handle) مقداردهی اولیه هندل. .UNINDENT .INDENT 0.0 .TP .B int uv_timer_start(uv_timer_t \%<#\:c\:.uv_timer_t> *handle, uv_timer_cb \%<#\:c\:.uv_timer_cb> cb, uint64_t timeout, uint64_t repeat) راه‌اندازی تایمر. مقادیر \fItimeout\fP و \fIrepeat\fP به میلی‌ثانیه هستند. .sp اگر \fItimeout\fP صفر باشد، تابع بازخوانی در تکرار بعدی حلقه رویداد اجرا می‌شود. اگر \fIrepeat\fP غیرصفر باشد، بازخوانی ابتدا پس از \fItimeout\fP میلی‌ثانیه و سپس به صورت مکرر پس از هر \fIrepeat\fP میلی‌ثانیه اجرا می‌شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 مفهوم «اکنون» در حلقه رویداد را به‌روزرسانی نمی‌کند. برای اطلاعات بیشتر به \fBuv_update_time()\fP \%<#\:c\:.uv_update_time> مراجعه کنید. .sp اگر تایمر از قبل فعال باشد، صرفاً به‌روزرسانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_timer_stop(uv_timer_t \%<#\:c\:.uv_timer_t> *handle) متوقف کردن تایمر، تابع بازخوانی دیگر فراخوانی نخواهد شد. .UNINDENT .INDENT 0.0 .TP .B int uv_timer_again(uv_timer_t \%<#\:c\:.uv_timer_t> *handle) تایمر را متوقف می‌کند، و اگر تکرارشونده باشد آن را با استفاده از مقدار repeat به عنوان مهلت زمانی (timeout) مجدداً راه‌اندازی می‌کند. اگر تایمر قبلاً هرگز شروع نشده باشد مقدار UV_EINVAL برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B void uv_timer_set_repeat(uv_timer_t \%<#\:c\:.uv_timer_t> *handle, uint64_t repeat) مقدار بازه تکرار را به میلی‌ثانیه تنظیم می‌کند. تایمر برای اجرا در بازه زمانی داده‌شده زمان‌بندی خواهد شد، صرف‌نظر از مدت زمان اجرای تابع بازخوانی، و در صورت عبور از برهه زمانی (time-slice overrun) از معناشناسی عادی تایمر پیروی خواهد کرد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 اگر مقدار تکرار از درون بازخوانی تایمر تنظیم شود، بلافاصله اعمال نمی‌شود. اگر تایمر قبلاً غیرتکرارشونده بوده باشد، متوقف خواهد شد. اگر تکرارشونده بوده باشد، مقدار تکرار قدیمی برای زمان‌بندی مهلت بعدی استفاده خواهد شد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_timer_get_repeat(const uv_timer_t \%<#\:c\:.uv_timer_t> *handle) دریافت مقدار تکرار تایمر. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_timer_get_due_in(const uv_timer_t \%<#\:c\:.uv_timer_t> *handle) زمان باقی‌مانده تا سررسید تایمر یا 0 را در صورت منقضی شدن برمی‌گرداند. زمان نسبت به \fBuv_now()\fP \%<#\:c\:.uv_now> است. .sp اضافه‌شده در نسخه 1.40.0. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API ساختار \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_prepare_t\fP \-\-\- هندل آماده‌سازی (Prepare handle) .sp هندل‌های آماده‌سازی (Prepare) تابع بازخوانی داده‌شده را یک بار در هر تکرار حلقه، درست قبل از سرکشی (poll) برای ورودی/خروجی اجرا می‌کنند. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_prepare_t نوع هندل آماده‌سازی (Prepare). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_prepare_cb)(uv_prepare_t \%<#\:c\:.uv_prepare_t> *handle) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_prepare_start()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .sp موردی وجود ندارد (N/A) .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_prepare_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_prepare_t \%<#\:c\:.uv_prepare_t> *prepare) مقداردهی اولیه هندل. این تابع همیشه با موفقیت انجام می‌شود. .INDENT 7.0 .TP .B بازگشتی‌ها 0 .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_prepare_start(uv_prepare_t \%<#\:c\:.uv_prepare_t> *prepare, uv_prepare_cb \%<#\:c\:.uv_prepare_cb> cb) راه‌اندازی هندل با تابع بازخوانی داده‌شده. این تابع همیشه با موفقیت انجام می‌شود، مگر زمانی که \fIcb\fP مقدار \fINULL\fP باشد. .INDENT 7.0 .TP .B بازگشتی‌ها 0 در صورت موفقیت، یا \fIUV_EINVAL\fP زمانی که \fIcb == NULL\fP باشد. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_prepare_stop(uv_prepare_t \%<#\:c\:.uv_prepare_t> *prepare) متوقف کردن هندل، تابع بازخوانی دیگر فراخوانی نخواهد شد. این تابع همیشه با موفقیت انجام می‌شود. .INDENT 7.0 .TP .B بازگشتی‌ها 0 .UNINDENT .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API ساختار \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_check_t\fP \-\-\- هندل بررسی (Check handle) .sp هندل‌های بررسی (Check) تابع بازخوانی داده‌شده را یک بار در هر تکرار حلقه، درست بعد از سرکشی برای ورودی/خروجی اجرا می‌کنند. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_check_t نوع هندل بررسی (Check). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_check_cb)(uv_check_t \%<#\:c\:.uv_check_t> *handle) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_check_start()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .sp موردی وجود ندارد (N/A) .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_check_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_check_t \%<#\:c\:.uv_check_t> *check) مقداردهی اولیه هندل. این تابع همیشه با موفقیت انجام می‌شود. .INDENT 7.0 .TP .B بازگشتی‌ها 0 .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_check_start(uv_check_t \%<#\:c\:.uv_check_t> *check, uv_check_cb \%<#\:c\:.uv_check_cb> cb) راه‌اندازی هندل با تابع بازخوانی داده‌شده. این تابع همیشه با موفقیت انجام می‌شود، مگر زمانی که \fIcb\fP مقدار \fINULL\fP باشد. .INDENT 7.0 .TP .B بازگشتی‌ها 0 در صورت موفقیت، یا \fIUV_EINVAL\fP زمانی که \fIcb == NULL\fP باشد. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_check_stop(uv_check_t \%<#\:c\:.uv_check_t> *check) متوقف کردن هندل، تابع بازخوانی دیگر فراخوانی نخواهد شد. این تابع همیشه با موفقیت انجام می‌شود. .INDENT 7.0 .TP .B بازگشتی‌ها 0 .UNINDENT .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API ساختار \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_idle_t\fP \-\-\- هندل بی‌کار (Idle handle) .sp هندل‌های بی‌کار (Idle) تابع بازخوانی داده‌شده را یک بار در هر تکرار حلقه، درست قبل از هندل‌های \fBuv_prepare_t\fP \%<#\:c\:.uv_prepare_t> اجرا می‌کنند. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 تفاوت قابل توجه با هندل‌های آماده‌سازی این است که وقتی هندل‌های بی‌کار فعالی وجود دارند، حلقه به جای مسدود شدن برای ورودی/خروجی، یک سرکشی بدون مهلت زمانی (zero timeout poll) انجام می‌دهد. .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 علیرغم نام آن، هندل‌های بی‌کار بازخوانی‌های خود را در هر تکرار حلقه دریافت می‌کنند، نه زمانی که حلقه واقعاً «بی‌کار» (idle) است. .UNINDENT .UNINDENT .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_idle_t نوع هندل بی‌کار (Idle). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_idle_cb)(uv_idle_t \%<#\:c\:.uv_idle_t> *handle) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_idle_start()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .sp موردی وجود ندارد (N/A) .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_idle_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_idle_t \%<#\:c\:.uv_idle_t> *idle) مقداردهی اولیه هندل. این تابع همیشه با موفقیت انجام می‌شود. .INDENT 7.0 .TP .B بازگشتی‌ها 0 .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_idle_start(uv_idle_t \%<#\:c\:.uv_idle_t> *idle, uv_idle_cb \%<#\:c\:.uv_idle_cb> cb) راه‌اندازی هندل با تابع بازخوانی داده‌شده. این تابع همیشه با موفقیت انجام می‌شود، مگر زمانی که \fIcb\fP مقدار \fINULL\fP باشد. .INDENT 7.0 .TP .B بازگشتی‌ها 0 در صورت موفقیت، یا \fIUV_EINVAL\fP زمانی که \fIcb == NULL\fP باشد. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_idle_stop(uv_idle_t \%<#\:c\:.uv_idle_t> *idle) متوقف کردن هندل، تابع بازخوانی دیگر فراخوانی نخواهد شد. این تابع همیشه با موفقیت انجام می‌شود. .INDENT 7.0 .TP .B بازگشتی‌ها 0 .UNINDENT .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API ساختار \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_async_t\fP \-\-\- هندل ناهمگام (Async handle) .sp هندل‌های ناهمگام (Async) به کاربر اجازه می‌دهند حلقه رویداد را «بیدار» (wakeup) کنند و بازخوانی فراخوانی‌شده‌ای از ریسه دیگر دریافت کنند. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_async_t نوع هندل ناهمگام (Async). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_async_cb)(uv_async_t \%<#\:c\:.uv_async_t> *handle) تعریف نوع تابع بازخوانی ارسال‌شده به \fBuv_async_init()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .sp موردی وجود ندارد (N/A) .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_async_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_async_t \%<#\:c\:.uv_async_t> *async, uv_async_cb \%<#\:c\:.uv_async_cb> async_cb) مقداردهی اولیه هندل. ارسال تابع بازخوانی NULL مجاز است. .INDENT 7.0 .TP .B بازگشتی‌ها 0 در صورت موفقیت، یا کد خطای < 0 در صورت شکست. .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 برخلاف سایر توابع مقداردهی اولیه هندل، این تابع هندل را بلافاصله راه‌اندازی می‌کند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_async_send(uv_async_t \%<#\:c\:.uv_async_t> *async) بیدار کردن حلقه رویداد و فراخوانی تابع بازخوانی هندل ناهمگام. .INDENT 7.0 .TP .B بازگشتی‌ها 0 در صورت موفقیت، یا کد خطای < 0 در صورت شکست. .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 فراخوانی این تابع از هر ریسه‌ای امن است. تابع بازخوانی روی ریسه حلقه رویداد فراخوانی خواهد شد. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 تابع \fBuv_async_send()\fP از نظر سیگنال‌های ناهمگام ایمن است (async\-signal\-safe) \%\&. فراخوانی این تابع از درون یک گرداننده سیگنال (signal handler) ایمن است. .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 کتابخانه libuv فراخوانی‌های \fBuv_async_send()\fP را ادغام (coalesce) می‌کند، به این معنی که هر فراخوانی از آن لزوماً منجر به یک بار اجرای تابع بازخوانی نخواهد شد. به عنوان مثال: اگر \fBuv_async_send()\fP 5 بار متوالی قبل از فراخوانی بازخوانی صدا زده شود، بازخوانی تنها یک بار اجرا خواهد شد. اگر پس از اجرای بازخوانی، \fBuv_async_send()\fP دوباره فراخوانی شود، بازخوانی مجدداً صدا زده خواهد شد. .UNINDENT .UNINDENT .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API ساختار \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_poll_t\fP \-\-\- قلاب نظرسنجی (Poll handle) .sp قلاب‌های نظرسنجی (Poll handles) برای پایش توصیف‌کننده‌های فایل از نظر قابلیت خواندن، قابلیت نوشتن و قطع اتصال، مشابه با هدف تابع poll(2) \% استفاده می‌شوند. .sp هدف از قلاب‌های نظرسنجی، امکان یکپارچه‌سازی کتابخانه‌های خارجی است که برای آگاه‌سازی از تغییرات وضعیت سوکت به حلقه رویداد وابسته‌اند، مانند c\-ares یا libssh2. استفاده از uv_poll_t برای هر هدف دیگری توصیه نمی‌شود؛ \fBuv_tcp_t\fP \%<#\:c\:.uv_tcp_t>، \fBuv_udp_t\fP \%<#\:c\:.uv_udp_t> و غیره پیاده‌سازی سریع‌تر و مقیاس‌پذیرتری را نسبت به آنچه با \fBuv_poll_t\fP به دست می‌آید ارائه می‌دهند، به‌ویژه در ویندوز. .sp این احتمال وجود دارد که قلاب‌های نظرسنجی گاهی سیگنال خوانایی یا نوشتنی بودن توصیف‌کننده فایل را ارسال کنند، حتی اگر در واقعیت چنین نباشد. بنابراین کاربر باید همیشه آمادگی مدیریت خطای EAGAIN یا معادل آن را هنگام تلاش برای خواندن از یا نوشتن در توصیف‌کننده فایل داشته باشد. .sp داشتن چند قلاب نظرسنجی فعال برای یک سوکت واحد مجاز نیست؛ این امر می‌تواند باعث ایجاد حلقه بی‌نهایت (busyloop) در libuv یا اختلال در عملکرد آن شود. .sp کاربر نباید یک توصیف‌کننده فایل را زمانی که توسط یک قلاب نظرسنجی فعال پایش می‌شود ببندد. این کار می‌تواند باعث گزارش خطا توسط قلاب شود، اما همچنین ممکن است پایش سوکت دیگری را آغاز کند. با این حال، بستن توصیف‌کننده فایل بلافاصله پس از فراخوانی \fBuv_poll_stop()\fP یا \fBuv_close()\fP \%<#\:c\:.uv_close> کاملاً ایمن است. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در ویندوز تنها سوکت‌ها را می‌توان با قلاب‌های نظرسنجی پایش کرد. در یونیکس هر توصیف‌کننده فایلی که توسط poll(2) \% پذیرفته شود قابل استفاده است. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در سیستم‌عامل AIX، پایش برای قطع اتصال (disconnection) پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_poll_t نوع داده قلاب نظرسنجی (Poll handle). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_poll_cb)(uv_poll_t \%<#\:c\:.uv_poll_t> *handle, int status, int events) تعریف نوع برای تابع بازخوانی ارسال‌شده به \fBuv_poll_start()\fP\&. .UNINDENT .INDENT 0.0 .TP .B enum uv_poll_event انواع رویدادهای نظرسنجی (Poll event types) .INDENT 7.0 .INDENT 3.5 .sp .EX enum uv_poll_event { UV_READABLE = 1, UV_WRITABLE = 2, UV_DISCONNECT = 4, UV_PRIORITIZED = 8 }; .EE .UNINDENT .UNINDENT .UNINDENT .SS "اعضای عمومی (Public members)" .sp موردی وجود ندارد (N/A) .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_poll_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_poll_t \%<#\:c\:.uv_poll_t> *handle, int fd) راه‌اندازی اولیه قلاب با استفاده از یک توصیف‌کننده فایل (file descriptor). .sp تغییریافته در نسخه 1.2.2: توصیف‌کننده فایل روی حالت غیرمسدودکننده (non\-blocking) تنظیم می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_poll_init_socket(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_poll_t \%<#\:c\:.uv_poll_t> *handle, uv_os_sock_t \%<#\:c\:.uv_os_sock_t> socket) راه‌اندازی اولیه قلاب با استفاده از یک توصیف‌کننده سوکت. در یونیکس این تابع کاملاً معادل \fBuv_poll_init()\fP است. در ویندوز یک قلاب SOCKET دریافت می‌کند. .sp تغییریافته در نسخه 1.2.2: سوکت روی حالت غیرمسدودکننده (non\-blocking) تنظیم می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_poll_start(uv_poll_t \%<#\:c\:.uv_poll_t> *handle, int events, uv_poll_cb \%<#\:c\:.uv_poll_cb> cb) آغاز نظرسنجی توصیف‌کننده فایل. پارامتر \fIevents\fP یک ماسک بیتی متشکل از \fIUV_READABLE\fP، \fIUV_WRITABLE\fP، \fIUV_PRIORITIZED\fP و \fIUV_DISCONNECT\fP است. به محض تشخیص یک رویداد، تابع بازخوانی با مقدار 0 برای \fIstatus\fP فراخوانی می‌شود و رویدادهای دریافت‌شده در فیلد \fIevents\fP تنظیم می‌گردند. .sp رویداد \fIUV_PRIORITIZED\fP برای پایش وقفه‌های sysfs یا پیام‌های خارج از باند (out\-of\-band) پروتکل TCP استفاده می‌شود. .sp رویداد \fIUV_DISCONNECT\fP از این نظر اختیاری است که ممکن است گزارش نشود و کاربر آزاد است آن را نادیده بگیرد، اما می‌تواند به بهینه‌سازی مسیر خاموش‌سازی کمک کند زیرا ممکن است از یک فراخوانی اضافی خواندن یا نوشتن جلوگیری نماید. .sp در صورت بروز خطا هنگام نظرسنجی، مقدار \fIstatus\fP کمتر از 0 خواهد بود و با یکی از کدهای خطای \fIUV_E*\fP مطابقت دارد (به مدیریت خطاها \%<#\:errors> مراجعه کنید). کاربر نباید سوکت را در زمانی که قلاب فعال است ببندد. اگر کاربر با این حال چنین کاری انجام دهد، تابع بازخوانی \fIممکن است\fP برای گزارش وضعیت خطا فراخوانی شود، اما این امر تضمین‌شده \fBنیست\fP. اگر \fIstatus == UV_EBADF\fP باشد، نظرسنجی برای قلاب فایل متوقف می‌شود و هیچ رویداد دیگری گزارش نخواهد شد. کاربر در این حالت باید \fBuv_close()\fP \%<#\:c\:.uv_close> را روی قلاب فراخوانی کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 فراخوانی \fBuv_poll_start()\fP روی قلابی که از قبل فعال است اشکالی ندارد. انجام این کار ماسک رویدادهایی را که پایش می‌شوند به‌روزرسانی می‌کند. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 اگرچه \fIUV_DISCONNECT\fP را می‌توان تنظیم کرد، اما این قابلیت در AIX پشتیبانی نمی‌شود و بنابراین در فیلد \fIevents\fP در تابع بازخوانی تنظیم نخواهد شد. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 اگر یکی از رویدادهای \fIUV_READABLE\fP یا \fIUV_WRITABLE\fP تنظیم شده باشند، تا زمانی که توصیف‌کننده/سوکت مربوطه همچنان به ترتیب خواندنی یا نوشتنی باقی بماند، تابع بازخوانی مجدداً فراخوانی خواهد شد؛ به‌ویژه در هر یک از سناریوهای زیر: .INDENT 0.0 .IP \(bu 2 تابع بازخوانی به دلیل خواندنی/نوشتنی شدن سوکت فراخوانی شده است و اصلاً عملیات خواندن/نوشتن روی این سوکت انجام نداده است. .IP \(bu 2 تابع بازخوانی عملیات خواندن را روی سوکت انجام داده، اما همه داده‌های موجود را نخوانده است (زمانی که \fIUV_READABLE\fP تنظیم شده است). .IP \(bu 2 تابع بازخوانی عملیات نوشتن را روی سوکت انجام داده، اما سوکت پس از آن نیز همچنان قابل نوشتن باقی مانده است (زمانی که \fIUV_WRITABLE\fP تنظیم شده است). .IP \(bu 2 سوکت پیش از فراخوانی \fBuv_poll_start()\fP روی قلاب نظرسنجی مرتبط با آن، از قبل خواندنی/نوشتنی شده و از آن زمان وضعیت سوکت تغییر نکرده است. .UNINDENT .sp در تمامی سناریوهای فوق، سوکت خواندنی یا نوشتنی باقی می‌ماند و بنابراین تابع بازخوانی مجدداً فراخوانی خواهد شد (بسته به رویدادهای تنظیم‌شده در ماسک بیتی). این رفتار به عنوان تحریک سطحی (level triggering) شناخته می‌شود. .UNINDENT .UNINDENT .sp تغییریافته در نسخه 1.9.0: رویداد \fIUV_DISCONNECT\fP اضافه شد. .sp تغییریافته در نسخه 1.14.0: رویداد \fIUV_PRIORITIZED\fP اضافه شد. .UNINDENT .INDENT 0.0 .TP .B int uv_poll_stop(uv_poll_t \%<#\:c\:.uv_poll_t> *poll) توقف نظرسنجی توصیف‌کننده فایل؛ تابع بازخوانی دیگر فراخوانی نخواهد شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 فراخوانی \fBuv_poll_stop()\fP بلافاصله اثر می‌کند: هرگونه تابع بازخوانی در انتظار نیز لغو می‌شود، حتی اگر اعلان تغییر وضعیت سوکت پیش‌تر آماده شده باشد. .UNINDENT .UNINDENT .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع رابط برنامه‌نویسی \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_signal_t\fP \-\-\- قلاب سیگنال (Signal handle) .sp قلاب‌های سیگنال، مدیریت سیگنال به سبک یونیکس را بر پایه هر حلقه رویداد پیاده‌سازی می‌کنند. .SS "نکات ویندوز (Windows notes)" .sp دریافت برخی سیگنال‌ها شبیه‌سازی شده است: .INDENT 0.0 .IP \(bu 2 سیگنال SIGINT معمولاً زمانی تحویل داده می‌شود که کاربر کلیدهای CTRL+C را فشار دهد. با این حال، مانند یونیکس، در صورت فعال بودن حالت خام ترمینال (terminal raw mode) این سیگنال تولید نمی‌شود. .IP \(bu 2 سیگنال SIGBREAK هنگامی که کاربر کلیدهای CTRL + BREAK را فشار دهد تحویل داده می‌شود. .IP \(bu 2 سیگنال SIGHUP زمانی تولید می‌شود که کاربر پنجره کنسول را ببندد. در زمان SIGHUP به برنامه تقریباً ۱۰ ثانیه فرصت داده می‌شود تا پاک‌سازی را انجام دهد. پس از آن ویندوز بدون قید و شرط آن را خاتمه می‌دهد. .IP \(bu 2 سیگنال SIGWINCH هر زمان که libuv تغییر اندازه کنسول را تشخیص دهد برانگیخته می‌شود. هنگامی که یک برنامه libuv درون یک شبیه‌ساز کنسول اجرا می‌شود، یا هنگامی که یک برنامه ۳۲ بیتی libuv روی یک سیستم ۶۴ بیتی در حال اجراست، SIGWINCH شبیه‌سازی خواهد شد. در چنین مواردی سیگنال‌های SIGWINCH ممکن است همیشه به موقع تحویل داده نشوند. برای یک قلاب \fBuv_tty_t\fP \%<#\:c\:.uv_tty_t> قابل نوشتن، libuv تنها زمانی تغییرات اندازه را تشخیص می‌دهد که مکان‌نما حرکت کند. هنگامی که از یک قلاب \fBuv_tty_t\fP \%<#\:c\:.uv_tty_t> قابل خواندن استفاده می‌شود، تغییر اندازه بافر کنسول تنها در صورتی تشخیص داده می‌شود که قلاب در حالت خام (raw mode) باشد و در حال خواندن باشد. .IP \(bu 2 دیده‌بان‌ها (watchers) برای سایر سیگنال‌ها با موفقیت ایجاد می‌شوند، اما این سیگنال‌ها هرگز دریافت نمی‌شوند. این سیگنال‌ها عبارتند از: \fISIGILL\fP، \fISIGABRT\fP، \fISIGFPE\fP، \fISIGSEGV\fP، \fISIGTERM\fP و \fISIGKILL.\fP .IP \(bu 2 فراخوانی‌های raise() یا abort() برای برانگیختن برنامه‌نویسی‌شده سیگنال توسط libuv تشخیص داده نمی‌شوند؛ این فراخوانی‌ها دیده‌بان سیگنال را تحریک نخواهند کرد. .UNINDENT .sp تغییریافته در نسخه 1.15.0: پشتیبانی از SIGWINCH در ویندوز بهبود یافت. .sp تغییریافته در نسخه 1.31.0: پشتیبانی libuv نسخه ۳۲ بیتی از SIGWINCH در ویندوز ۶۴ بیتی به پیاده‌سازی قدیمی بازگردانده شد. .SS "نکات یونیکس (Unix notes)" .INDENT 0.0 .IP \(bu 2 گرفتن سیگنال‌های SIGKILL و SIGSTOP غیرممکن است. .IP \(bu 2 مدیریت SIGBUS، SIGFPE، SIGILL یا SIGSEGV از طریق libuv منجر به رفتار تعریف‌نشده می‌شود. .IP \(bu 2 سیگنال SIGABRT در صورتی که توسط \fIabort()\fP تولید شود (مثلاً از طریق \fIassert()\fP)، توسط libuv گرفته نخواهد شد. .IP \(bu 2 در لینوکس، سیگنال‌های SIGRT0 و SIGRT1 (سیگنال‌های ۳۲ و ۳۳) توسط کتابخانه NPTL pthreads برای مدیریت نخ‌ها استفاده می‌شوند. نصب دیده‌بان برای این سیگنال‌ها منجر به رفتار غیرقابل پیش‌بینی می‌شود و اکیداً منع شده است. نسخه‌های آینده libuv ممکن است به سادگی آن‌ها را رد کنند. .UNINDENT .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_signal_t نوع داده قلاب سیگنال (Signal handle). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_signal_cb)(uv_signal_t \%<#\:c\:.uv_signal_t> *handle, int signum) تعریف نوع برای تابع بازخوانی ارسال‌شده به \fBuv_signal_start()\fP\&. .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B int uv_signal_t \%<#\:c\:.uv_signal_t>\&.signum سیگنالی که توسط این قلاب پایش می‌شود. فقط‌خواندنی. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_signal_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_signal_t \%<#\:c\:.uv_signal_t> *signal) راه‌اندازی اولیه قلاب. .UNINDENT .INDENT 0.0 .TP .B int uv_signal_start(uv_signal_t \%<#\:c\:.uv_signal_t> *signal, uv_signal_cb \%<#\:c\:.uv_signal_cb> cb, int signum) شروع کار قلاب با تابع بازخوانی مشخص‌شده، در حال پایش سیگنال داده‌شده. .UNINDENT .INDENT 0.0 .TP .B int uv_signal_start_oneshot(uv_signal_t \%<#\:c\:.uv_signal_t> *signal, uv_signal_cb \%<#\:c\:.uv_signal_cb> cb, int signum) افزوده‌شده در نسخه 1.12.0. .sp عملکرد مشابه با \fBuv_signal_start()\fP دارد اما کنترل‌کننده سیگنال به محض دریافت سیگنال بازنشانی می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_signal_stop(uv_signal_t \%<#\:c\:.uv_signal_t> *signal) توقف قلاب؛ تابع بازخوانی دیگر فراخوانی نخواهد شد. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع رابط برنامه‌نویسی \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_process_t\fP \-\-\- قلاب فرایند (Process handle) .sp قلاب‌های فرایند یک فرایند جدید را اجرا (spawn) می‌کنند و به کاربر اجازه می‌دهند آن را کنترل کرده و با استفاده از جریان‌ها (streams) کانال‌های ارتباطی با آن برقرار کند. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_process_t نوع داده قلاب فرایند (Process handle). .UNINDENT .INDENT 0.0 .TP .B type uv_process_options_t گزینه‌ها برای اجرای فرایند (ارسال‌شده به \fBuv_spawn()\fP). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_process_options_s { uv_exit_cb exit_cb; const char* file; char** args; char** env; const char* cwd; unsigned int flags; int stdio_count; uv_stdio_container_t* stdio; uv_uid_t uid; uv_gid_t gid; } uv_process_options_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_exit_cb)(uv_process_t \%<#\:c\:.uv_process_t>*, int64_t exit_status, int term_signal) تعریف نوع برای تابع بازخوانی ارسال‌شده در \fBuv_process_options_t\fP که وضعیت خروج و سیگنالی را که در صورت وجود باعث خاتمه فرایند شده است، نشان می‌دهد. .UNINDENT .INDENT 0.0 .TP .B enum uv_process_flags فلگ‌هایی که روی فیلد flags از \fBuv_process_options_t\fP تنظیم می‌شوند. .INDENT 7.0 .INDENT 3.5 .sp .EX enum uv_process_flags { /* * Set the child process\(aq user id. */ UV_PROCESS_SETUID = (1 << 0), /* * Set the child process\(aq group id. */ UV_PROCESS_SETGID = (1 << 1), /* * Do not wrap any arguments in quotes, or perform any other escaping, when * converting the argument list into a command line string. This option is * only meaningful on Windows systems. On Unix it is silently ignored. */ UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2), /* * Spawn the child process in a detached state \- this will make it a process * group leader, and will effectively enable the child to keep running after * the parent exits. Note that the child process will still keep the * parent\(aqs event loop alive unless the parent process calls uv_unref() on * the child\(aqs process handle. */ UV_PROCESS_DETACHED = (1 << 3), /* * Hide the subprocess window that would normally be created. This option is * only meaningful on Windows systems. On Unix it is silently ignored. */ UV_PROCESS_WINDOWS_HIDE = (1 << 4), /* * Hide the subprocess console window that would normally be created. This * option is only meaningful on Windows systems. On Unix it is silently * ignored. */ UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5), /* * Hide the subprocess GUI window that would normally be created. This * option is only meaningful on Windows systems. On Unix it is silently * ignored. */ UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6), /* * On Windows, if the path to the program to execute, specified in * uv_process_options_t\(aqs file field, has a directory component, * search for the exact file name before trying variants with * extensions like \(aq.exe\(aq or \(aq.cmd\(aq. */ UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME = (1 << 7) }; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_stdio_container_t ظرف نگه‌دارنده برای هر قلاب stdio یا توصیف‌کننده فایل ارسالی به فرایند فرزند. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_stdio_container_s { uv_stdio_flags flags; union { uv_stream_t* stream; int fd; } data; } uv_stdio_container_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_stdio_flags فلگ‌هایی که نحوه انتقال stdio به فرایند فرزند را مشخص می‌کنند. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { /* * The following four options are mutually\-exclusive, and define * the operation to perform for the corresponding file descriptor * in the child process: */ /* * No file descriptor will be provided (or redirected to * \(ga/dev/null\(ga if it is fd 0, 1 or 2). */ UV_IGNORE = 0x00, /* * Open a new pipe into \(gadata.stream\(ga, per the flags below. The * \(gadata.stream\(ga field must point to a uv_pipe_t object that has * been initialized with \(gauv_pipe_init(loop, data.stream, ipc);\(ga, * but not yet opened or connected. /* UV_CREATE_PIPE = 0x01, /* * The child process will be given a duplicate of the parent\(aqs * file descriptor given by \(gadata.fd\(ga. */ UV_INHERIT_FD = 0x02, /* * The child process will be given a duplicate of the parent\(aqs * file descriptor being used by the stream handle given by * \(gadata.stream\(ga. */ UV_INHERIT_STREAM = 0x04, /* * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE * determine the direction of flow, from the child process\(aq perspective. Both * flags may be specified to create a duplex data stream. */ UV_READABLE_PIPE = 0x10, UV_WRITABLE_PIPE = 0x20, /* * When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the * handle in non\-blocking mode in the child. This may cause loss of data, * if the child is not designed to handle to encounter this mode, * but can also be significantly more efficient. */ UV_NONBLOCK_PIPE = 0x40 } uv_stdio_flags; .EE .UNINDENT .UNINDENT .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B int uv_process_t \%<#\:c\:.uv_process_t>\&.pid شناسه فرایند (PID) فرایند اجراشده. پس از فراخوانی \fBuv_spawn()\fP تنظیم می‌شود. .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B uv_exit_cb \%<#\:c\:.uv_exit_cb> uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.exit_cb تابع بازخوانی که پس از خروج فرایند فراخوانی می‌شود. .UNINDENT .INDENT 0.0 .TP .B const char *uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.file مسیری که به برنامه اجرایی اشاره می‌کند. .UNINDENT .INDENT 0.0 .TP .B char **uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.args آرگومان‌های خط فرمان. آرگومان args[0] باید مسیر برنامه باشد. در ویندوز از \fICreateProcess\fP استفاده می‌شود که آرگومان‌ها را درون یک رشته الحاق می‌کند و این امر می‌تواند خطاهای عجیبی ایجاد کند. به فلگ \fBUV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS\fP در \fBuv_process_flags\fP مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B char **uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.env متغیرهای محیطی برای فرایند جدید. اگر NULL باشد از محیط فرایند والد استفاده می‌شود. .UNINDENT .INDENT 0.0 .TP .B const char *uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.cwd دایرکتوری کاری جاری برای زیرفرایند. .UNINDENT .INDENT 0.0 .TP .B unsigned int uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.flags فلگ‌های گوناگونی که نحوه رفتار \fBuv_spawn()\fP را کنترل می‌کنند. به \fBuv_process_flags\fP مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B int uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.stdio_count .UNINDENT .INDENT 0.0 .TP .B uv_stdio_container_t \%<#\:c\:.uv_stdio_container_t> *uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.stdio فیلد \fIstdio\fP به آرایه‌ای از ساختارهای \fBuv_stdio_container_t\fP اشاره می‌کند که توصیف‌کننده‌های فایل قابل دسترسی برای فرایند فرزند را توصیف می‌کنند. قرارداد استاندارد این است که stdio[0] به ورودی استاندارد (stdin)، توصیف‌کننده 1 به خروجی استاندارد (stdout) و توصیف‌کننده 2 به خطای استاندارد (stderr) اختصاص دارد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز، توصیف‌کننده‌های فایل بزرگتر از ۲ تنها در صورتی برای فرایند فرزند در دسترس هستند که فرایند فرزند از زمان اجرای MSVCRT استفاده کند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B uv_uid_t uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.uid .UNINDENT .INDENT 0.0 .TP .B uv_gid_t uv_process_options_t \%<#\:c\:.uv_process_options_t>\&.gid کتابخانه libuv می‌تواند شناسه کاربر/گروه فرایند فرزند را تغییر دهد. این تغییر تنها زمانی رخ می‌دهد که بیت‌های مناسب در فیلدهای flags تنظیم شده باشند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این ویژگی در ویندوز پشتیبانی نمی‌شود و \fBuv_spawn()\fP با شکست مواجه شده و خطا را روی \fBUV_ENOTSUP\fP تنظیم می‌کند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B uv_stdio_flags \%<#\:c\:.uv_stdio_flags> uv_stdio_container_t \%<#\:c\:.uv_stdio_container_t>\&.flags فلگ‌هایی که نحوه ارسال ظرف stdio به فرایند فرزند را مشخص می‌کنند. .UNINDENT .INDENT 0.0 .TP .B union [anonymous] uv_stdio_container_t \%<#\:c\:.uv_stdio_container_t>\&.data اجتماعی (Union) شامل \fIstream\fP یا \fIfd\fP برای ارسال به فرایند فرزند. .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B void uv_disable_stdio_inheritance(void) وراثت توصیف‌کننده‌های فایل / قلاب‌هایی را که این فرایند از والد خود به ارث برده است غیرفعال می‌کند. اثر این کار این است که فرایندهای فرزندی که توسط این فرایند اجرا می‌شوند به طور تصادفی این قلاب‌ها را به ارث نمی‌برند. .sp توصیه می‌شود این تابع را در ابتدای برنامه در سریع‌ترین زمان ممکن فراخوانی کنید، پیش از آنکه توصیف‌کننده‌های فایل به ارث رسیده بتوانند بسته یا تکثیر شوند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این تابع بر مبنای حداکثر تلاش عمل می‌کند: هیچ تضمینی وجود ندارد که libuv بتواند تمام توصیف‌کننده‌های فایل به ارث رسیده را کشف کند. به طور کلی عملکرد آن در ویندوز بهتر از یونیکس است. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_spawn(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_process_t \%<#\:c\:.uv_process_t> *handle, const uv_process_options_t \%<#\:c\:.uv_process_options_t> *options) قلاب فرایند را راه‌اندازی اولیه کرده و فرایند را اجرا می‌کند. اگر فرایند با موفقیت اجرا شود، این تابع مقدار 0 را برمی‌گرداند. در غیر این صورت، کد خطای منفی متناظر با دلیل عدم اجرای فرایند بازگردانده می‌شود. .sp دلایل احتمالی برای عدم موفقیت در اجرا شامل مواردی مانند (اما نه محدود به) عدم وجود فایل اجرایی، نداشتن مجوزهای لازم برای استفاده از setuid یا setgid مشخص‌شده، یا عدم وجود حافظه کافی برای تخصیص به فرایند جدید است. .sp تغییریافته در نسخه 1.24.0: فلگ‌های \fIUV_PROCESS_WINDOWS_HIDE_CONSOLE\fP و \fIUV_PROCESS_WINDOWS_HIDE_GUI\fP اضافه شدند. .sp تغییریافته در نسخه 1.48.0: فلگ \fIUV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME\fP اضافه شد. .UNINDENT .INDENT 0.0 .TP .B int uv_process_kill(uv_process_t \%<#\:c\:.uv_process_t> *handle, int signum) سیگنال مشخص‌شده را به قلاب فرایند داده‌شده ارسال می‌کند. برای بررسی پشتیبانی از سیگنال‌ها، به‌ویژه در ویندوز، به مستندات uv_signal_t \-\-\- Signal handle \%<#\:signal> مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B int uv_kill(int pid, int signum) سیگنال مشخص‌شده را به شناسه فرایند (PID) داده‌شده ارسال می‌کند. برای بررسی پشتیبانی از سیگنال‌ها، به‌ویژه در ویندوز، به مستندات uv_signal_t \-\-\- Signal handle \%<#\:signal> مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B uv_pid_t \%<#\:c\:.uv_pid_t> uv_process_get_pid(const uv_process_t \%<#\:c\:.uv_process_t> *handle) مقدار \fIhandle\->pid\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.19.0. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع رابط برنامه‌نویسی \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_stream_t\fP \-\-\- قلاب جریان (Stream handle) .sp قلاب‌های جریان انتزاعی از یک کانال ارتباطی دوطرفه (duplex) را فراهم می‌کنند. \fBuv_stream_t\fP یک نوع انتزاعی است؛ کتابخانه libuv سه پیاده‌سازی مختلف از جریان را در قالب‌های \fBuv_tcp_t\fP \%<#\:c\:.uv_tcp_t>، \fBuv_pipe_t\fP \%<#\:c\:.uv_pipe_t> و \fBuv_tty_t\fP \%<#\:c\:.uv_tty_t> ارائه می‌دهد. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_stream_t نوع داده قلاب جریان (Stream handle). .UNINDENT .INDENT 0.0 .TP .B type uv_connect_t نوع درخواست اتصال (Connect request). .UNINDENT .INDENT 0.0 .TP .B type uv_shutdown_t نوع درخواست خاموش‌سازی/بستن اتصال (Shutdown request). .UNINDENT .INDENT 0.0 .TP .B type uv_write_t نوع درخواست نوشتن (Write request). هنگام استفاده مجدد از اشیاء متعلق به این نوع، باید دقت فراوان داشت. زمانی که یک جریان در حالت غیرمسدودکننده (non\-blocking) قرار دارد، درخواست‌های نوشتن ارسال‌شده با \fBuv_write\fP در صف قرار می‌گیرند. استفاده مجدد از اشیاء در این مقطع زمانی رفتاری تعریف‌نشده به همراه دارد. استفاده مجدد از شیء \fBuv_write_t\fP تنها پس از برانگیخته شدن تابع بازخوانی ارسال‌شده به \fBuv_write\fP ایمن است. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_read_cb)(uv_stream_t \%<#\:c\:.uv_stream_t> *stream, ssize_t nread, const uv_buf_t \%<#\:c\:.uv_buf_t> *buf) تابع بازخوانی هنگام خوانده شدن داده‌ها روی یک جریان. .sp اگر داده‌ای در دسترس باشد، مقدار \fInread\fP بزرگتر از 0 و در صورت بروز خطا کوچکتر از 0 خواهد بود. هنگام رسیدن به پایان فایل (EOF)، مقدار \fInread\fP برابر با \fBUV_EOF\fP خواهد بود. زمانی که \fInread\fP کوچکتر از 0 باشد، پارامتر \fIbuf\fP ممکن است به بافر معتبری اشاره نکند؛ در این حالت \fIbuf.len\fP و \fIbuf.base\fP هر دو برابر با 0 تنظیم می‌شوند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 مقدار \fInread\fP ممکن است 0 باشد، که به معنی خطا یا پایان فایل \fBنیست\fP. این معادل با \fBEAGAIN\fP یا \fBEWOULDBLOCK\fP در فراخوانی \fBread(2)\fP است. .UNINDENT .UNINDENT .sp فراخواننده مسئول توقف/بستن جریان هنگام بروز خطا از طریق فراخوانی \fBuv_read_stop()\fP یا \fBuv_close()\fP \%<#\:c\:.uv_close> است. تلاش برای خواندن مجدد از جریان رفتاری تعریف‌نشده دارد. .sp فراخواننده مسئول آزادسازی بافر است، libuv از آن مجدداً استفاده نمی‌کند. بافر ممکن است در زمان بروز خطا یک بافر تهی (که در آن \fIbuf\->base\fP == NULL و \fIbuf\->len\fP == 0 باشد) باشد. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_write_cb)(uv_write_t \%<#\:c\:.uv_write_t> *req, int status) تابع بازخوانی پس از نوشته شدن داده‌ها روی جریان. در صورت موفقیت مقدار \fIstatus\fP برابر با 0 و در غیر این صورت کوچکتر از 0 خواهد بود. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_connect_cb)(uv_connect_t \%<#\:c\:.uv_connect_t> *req, int status) تابع بازخوانی پس از اتمام اتصالی که توسط \fBuv_connect()\fP آغاز شده است. در صورت موفقیت مقدار \fIstatus\fP برابر با 0 و در غیر این صورت کوچکتر از 0 خواهد بود. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_shutdown_cb)(uv_shutdown_t \%<#\:c\:.uv_shutdown_t> *req, int status) تابع بازخوانی پس از تکمیل یک درخواست خاموش‌سازی (shutdown). در صورت موفقیت مقدار \fIstatus\fP برابر با 0 و در غیر این صورت کوچکتر از 0 خواهد بود. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_connection_cb)(uv_stream_t \%<#\:c\:.uv_stream_t> *server, int status) تابع بازخوانی هنگامی که یک سرور جریان، اتصال ورودی جدیدی را دریافت می‌کند. کاربر می‌تواند با فراخوانی \fBuv_accept()\fP اتصال را بپذیرد. در صورت موفقیت مقدار \fIstatus\fP برابر با 0 و در غیر این صورت کوچکتر از 0 خواهد بود. .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B size_t uv_stream_t \%<#\:c\:.uv_stream_t>\&.write_queue_size شامل حجم بایت‌های در صف انتظار برای ارسال. فقط‌خواندنی. .UNINDENT .INDENT 0.0 .TP .B uv_stream_t \%<#\:c\:.uv_stream_t> *uv_connect_t \%<#\:c\:.uv_connect_t>\&.handle اشاره‌گر به جریانی که این درخواست اتصال روی آن در حال اجراست. .UNINDENT .INDENT 0.0 .TP .B uv_stream_t \%<#\:c\:.uv_stream_t> *uv_shutdown_t \%<#\:c\:.uv_shutdown_t>\&.handle اشاره‌گر به جریانی که این درخواست خاموش‌سازی روی آن در حال اجراست. .UNINDENT .INDENT 0.0 .TP .B uv_stream_t \%<#\:c\:.uv_stream_t> *uv_write_t \%<#\:c\:.uv_write_t>\&.handle اشاره‌گر به جریانی که این درخواست نوشتن روی آن در حال اجراست. .UNINDENT .INDENT 0.0 .TP .B uv_stream_t \%<#\:c\:.uv_stream_t> *uv_write_t \%<#\:c\:.uv_write_t>\&.send_handle اشاره‌گر به جریانی که با استفاده از این درخواست نوشتن ارسال می‌شود. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_shutdown(uv_shutdown_t \%<#\:c\:.uv_shutdown_t> *req, uv_stream_t \%<#\:c\:.uv_stream_t> *handle, uv_shutdown_cb \%<#\:c\:.uv_shutdown_cb> cb) خاموش‌سازی سمت خروجی (نوشتن) یک جریان دوطرفه (duplex). این تابع منتظر تکمیل درخواست‌های نوشتن معلق می‌ماند. پارامتر \fIhandle\fP باید به یک جریان راه‌اندازی‌شده اشاره کند. پارامتر \fIreq\fP باید یک ساختار درخواست خاموش‌سازی راه‌اندازی‌نشده باشد. پس از اتمام خاموش‌سازی، تابع \fIcb\fP فراخوانی می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_listen(uv_stream_t \%<#\:c\:.uv_stream_t> *stream, int backlog, uv_connection_cb \%<#\:c\:.uv_connection_cb> cb) آغاز گوش دادن به اتصالات ورودی. پارامتر \fIbacklog\fP تعداد اتصالات قابل قرارگیری در صف توسط هسته سیستم‌عامل را مشخص می‌کند، مشابه با listen(2) \%\&. هنگامی که یک اتصال ورودی جدید دریافت شود، تابع بازخوانی \fBuv_connection_cb\fP فراخوانی می‌گردد. .UNINDENT .INDENT 0.0 .TP .B int uv_accept(uv_stream_t \%<#\:c\:.uv_stream_t> *server, uv_stream_t \%<#\:c\:.uv_stream_t> *client) این فراخوانی همراه با \fBuv_listen()\fP برای پذیرش اتصالات ورودی استفاده می‌شود. این تابع را پس از دریافت \fBuv_connection_cb\fP جهت پذیرش اتصال فراخوانی کنید. قبل از فراخوانی این تابع، قلاب کلاینت باید راه‌اندازی اولیه شده باشد. مقدار بازگشتی کمتر از 0 نشان‌دهنده خطاست. .sp هنگامی که تابع بازخوانی \fBuv_connection_cb\fP فراخوانی می‌شود، تضمین می‌گردد که این تابع برای بار اول با موفقیت به پایان برسد. اگر بیش از یک بار تلاش به استفاده از آن کنید، ممکن است شکست بخورد. پیشنهاد می‌شود این تابع را فقط یک بار به ازای هر فراخوانی \fBuv_connection_cb\fP اجرا کنید. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 پارامترهای \fIserver\fP و \fIclient\fP باید قلاب‌هایی باشند که روی یک حلقه رویداد یکسان اجرا می‌شوند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_read_start(uv_stream_t \%<#\:c\:.uv_stream_t> *stream, uv_alloc_cb \%<#\:c\:.uv_alloc_cb> alloc_cb, uv_read_cb \%<#\:c\:.uv_read_cb> read_cb) خواندن داده‌ها از یک جریان ورودی. تابع بازخوانی \fBuv_read_cb\fP چندین بار فراخوانی خواهد شد تا زمانی که داده دیگری برای خواندن نماند یا \fBuv_read_stop()\fP فراخوانی شود. .sp تغییریافته در نسخه 1.38.0: اکنون تابع \fBuv_read_start()\fP در صورت فراخوانی دوباره همواره \fIUV_EALREADY\fP و در صورت بسته شدن جریان مقدار \fIUV_EINVAL\fP را برمی‌گرداند. در نسخه‌های قدیمی‌تر libuv، مقدار \fIUV_EALREADY\fP روی ویندوز برمی‌گشت اما روی یونیکس خیر، و \fIUV_EINVAL\fP روی یونیکس برمی‌گشت اما روی ویندوز خیر. .UNINDENT .INDENT 0.0 .TP .B int uv_read_stop(uv_stream_t \%<#\:c\:.uv_stream_t>*) توقف خواندن داده‌ها از جریان. تابع بازخوانی \fBuv_read_cb\fP دیگر فراخوانی نخواهد شد. .sp این تابع خودتوان (idempotent) است و فراخوانی آن روی جریانی که قبلاً متوقف شده ایمن است. .sp این تابع همواره با موفقیت انجام می‌شود؛ از این رو بررسی مقدار بازگشتی آن ضرورتی ندارد. مقدار بازگشتی غیرصفر نشان می‌دهد که اتمام آزادسازی منابع ممکن است به رویداد ورودی بعدی روی آن TTY در ویندوز موکول شود و به معنای شکست عملیات نیست. .UNINDENT .INDENT 0.0 .TP .B int uv_write(uv_write_t \%<#\:c\:.uv_write_t> *req, uv_stream_t \%<#\:c\:.uv_stream_t> *handle, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs, uv_write_cb \%<#\:c\:.uv_write_cb> cb) نوشتن داده‌ها روی جریان. بافرها به ترتیب نوشته می‌شوند. مثال: .INDENT 7.0 .INDENT 3.5 .sp .EX void cb(uv_write_t* req, int status) { /* Logic which handles the write result */ } uv_buf_t a[] = { { .base = \(dq1\(dq, .len = 1 }, { .base = \(dq2\(dq, .len = 1 } }; uv_buf_t b[] = { { .base = \(dq3\(dq, .len = 1 }, { .base = \(dq4\(dq, .len = 1 } }; uv_write_t req1; uv_write_t req2; /* writes \(dq1234\(dq */ uv_write(&req1, stream, a, 2, cb); uv_write(&req2, stream, b, 2, cb); .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 حافظه‌ای که بافرها به آن اشاره می‌کنند باید تا زمان فراخوانی تابع بازخوانی معتبر باقی بماند. این قاعده برای \fBuv_write2()\fP نیز صادق است. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_write2(uv_write_t \%<#\:c\:.uv_write_t> *req, uv_stream_t \%<#\:c\:.uv_stream_t> *handle, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs, uv_stream_t \%<#\:c\:.uv_stream_t> *send_handle, uv_write_cb \%<#\:c\:.uv_write_cb> cb) تابع نوشتن پیشرفته برای ارسال قلاب‌ها از طریق یک لوله (pipe). لوله باید با \fIipc\fP == 1 راه‌اندازی شده باشد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 پارامتر \fIsend_handle\fP باید یک قلاب TCP، لوله (pipe) و UDP در یونیکس، یا یک قلاب TCP در ویندوز باشد که به عنوان سرور یا یک اتصال (در وضعیت گوش دادن یا متصل) عمل کند. سوکت‌ها یا لوله‌های مقیدشده (bound) به عنوان سرور در نظر گرفته می‌شوند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_try_write(uv_stream_t \%<#\:c\:.uv_stream_t> *handle, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs) همانند \fBuv_write()\fP عمل می‌کند، اما اگر نوشتن بلافاصله تکمیل نشود، درخواست نوشتن را در صف قرار نمی‌دهد. .sp یکی از مقادیر زیر را برمی‌گرداند: .INDENT 7.0 .IP \(bu 2 بزرگتر از 0: تعداد بایت‌های نوشته‌شده (می‌تواند کمتر از اندازه بافر ارائه‌شده باشد). .IP \(bu 2 کوچکتر از 0: کد خطای منفی (در صورتی که هیچ داده‌ای نتواند بلافاصله ارسال شود، \fBUV_EAGAIN\fP بازگردانده می‌شود). .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_try_write2(uv_stream_t \%<#\:c\:.uv_stream_t> *handle, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs, uv_stream_t \%<#\:c\:.uv_stream_t> *send_handle) مشابه \fBuv_try_write()\fP و تابع نوشتن گسترش‌یافته برای ارسال قلاب‌ها از طریق یک لوله همانند c:func:\fIuv_write2\fP است. .sp تلاش برای ارسال یک قلاب در ویندوز پشتیبانی نمی‌شود و در آنجا مقدار \fBUV_EAGAIN\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.42.0. .UNINDENT .INDENT 0.0 .TP .B int uv_is_readable(const uv_stream_t \%<#\:c\:.uv_stream_t> *handle) اگر جریان قابل خواندن باشد مقدار 1 و در غیر این صورت 0 را برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B int uv_is_writable(const uv_stream_t \%<#\:c\:.uv_stream_t> *handle) اگر جریان قابل نوشتن باشد مقدار 1 و در غیر این صورت 0 را برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B int uv_stream_set_blocking(uv_stream_t \%<#\:c\:.uv_stream_t> *handle, int blocking) فعال یا غیرفعال کردن حالت مسدودکننده (blocking mode) برای یک جریان. .sp هنگامی که حالت مسدودکننده فعال باشد، تمام عملیات نوشتن به صورت همگام تکمیل می‌شوند. با این حال رابط کاربری بدون تغییر باقی می‌ماند، مثلاً تکمیل یا عدم موفقیت در عملیات همچنان از طریق تابع بازخوانی که به صورت ناهمگام فراخوانی می‌شود گزارش خواهد شد. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 اتکای بیش از حد به این رابط برنامه‌نویسی توصیه نمی‌شود؛ احتمال دارد در آینده تغییرات قابل توجهی در آن ایجاد شود. .sp در حال حاضر در ویندوز تنها برای قلاب‌های \fBuv_pipe_t\fP \%<#\:c\:.uv_pipe_t> کار می‌کند. در پلتفرم‌های یونیکس، تمام قلاب‌های \fBuv_stream_t\fP پشتیبانی می‌شوند. .sp همچنین libuv در حال حاضر هیچ تضمینی در مورد ترتیب اجرا هنگام تغییر حالت مسدودکننده پس از ارسال درخواست‌های نوشتن ارائه نمی‌دهد. بنابراین توصیه می‌شود حالت مسدودکننده بلافاصله پس از باز کردن یا ایجاد جریان تنظیم شود. .UNINDENT .UNINDENT .sp تغییریافته در نسخه 1.4.0: پیاده‌سازی یونیکس اضافه شد. .UNINDENT .INDENT 0.0 .TP .B size_t uv_stream_get_write_queue_size(const uv_stream_t \%<#\:c\:.uv_stream_t> *stream) مقدار \fIstream\->write_queue_size\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.19.0. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع رابط برنامه‌نویسی \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_tcp_t\fP \-\-\- قلاب تی‌سی‌پی (TCP handle) .sp قلاب‌های TCP برای نمایش هر دو مورد جریان‌ها و سرورهای TCP استفاده می‌شوند. .sp ساختار \fBuv_tcp_t\fP یک زیرکلاس از \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t> است. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_tcp_t نوع داده قلاب TCP (TCP handle). .UNINDENT .INDENT 0.0 .TP .B enum uv_tcp_flags فلگ‌های استفاده‌شده در \fBuv_tcp_bind()\fP\&. .INDENT 7.0 .INDENT 3.5 .sp .EX enum uv_tcp_flags { /* Used with uv_tcp_bind, when an IPv6 address is used. */ UV_TCP_IPV6ONLY = 1, /* Enable SO_REUSEPORT socket option when binding the handle. * This allows completely duplicate bindings by multiple processes * or threads if they all set SO_REUSEPORT before binding the port. * Incoming connections are distributed across the participating * listener sockets. * * This flag is available only on Linux 3.9+, DragonFlyBSD 3.6+, * FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ for now. */ UV_TCP_REUSEPORT = 2, }; .EE .UNINDENT .UNINDENT .UNINDENT .SS "اعضای عمومی (Public members)" .sp موردی وجود ندارد (N/A) .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_tcp_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle) راه‌اندازی اولیه قلاب. تا این لحظه هیچ سوکتی ایجاد نشده است. .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_init_ex(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, unsigned int flags) راه‌اندازی اولیه قلاب با فلگ‌های مشخص‌شده. در حال حاضر تنها ۸ بیت پایینی پارامتر \fIflags\fP به عنوان دامنه سوکت (socket domain) استفاده می‌شوند. یک سوکت برای دامنه مشخص‌شده ایجاد خواهد شد. اگر دامنه مشخص‌شده \fBAF_UNSPEC\fP باشد هیچ سوکتی ایجاد نمی‌شود، دقیقاً مانند \fBuv_tcp_init()\fP\&. .sp افزوده‌شده در نسخه 1.7.0. .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_open(uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, uv_os_sock_t \%<#\:c\:.uv_os_sock_t> sock) باز کردن یک توصیف‌کننده فایل یا SOCKET موجود به عنوان یک قلاب TCP. .sp تغییریافته در نسخه 1.2.1: توصیف‌کننده فایل روی حالت غیرمسدودکننده (non\-blocking) تنظیم می‌شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 توصیف‌کننده فایل یا SOCKET ارسال‌شده از نظر نوع بررسی نمی‌شود، اما لازم است که یک سوکت جریان (stream socket) معتبر را نشان دهد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_nodelay(uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, int enable) فعال کردن \fITCP_NODELAY\fP که الگوریتم Nagle را غیرفعال می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_keepalive(uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, int enable, unsigned int delay) فعال / غیرفعال کردن قابلیت TCP keep\-alive. پارامتر \fIdelay\fP تأخیر اولیه بر حسب ثانیه است و زمانی که \fIenable\fP برابر صفر باشد نادیده گرفته می‌شود. .sp پس از رسیدن به زمان \fIdelay\fP، ۱۰ کاوش پیاپی با فاصله ۱ ثانیه از یکدیگر انجام خواهد شد. اگر در پایان این روند اتصال همچنان برقرار نشود، قلاب با خطای \fBUV_ETIMEDOUT\fP ارسالی به تابع بازخوانی مربوطه نابود می‌شود. .sp اگر \fIdelay\fP کمتر از ۱ باشد، مقدار \fBUV_EINVAL\fP برگردانده می‌شود. .sp تغییریافته در نسخه 1.49.0: اگر \fIdelay\fP کمتر از ۱ باشد، مقدار \fBUV_EINVAL\(ga\fP بازگردانده می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_keepalive_ex(uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, int on, unsigned int idle, unsigned int intvl, unsigned int cnt) فعال / غیرفعال کردن TCP keep\-alive با تمام گزینه‌های سوکت: \fITCP_KEEPIDLE\fP، \fITCP_KEEPINTVL\fP و \fITCP_KEEPCNT\fP\&. پارامتر \fIidle\fP مقدار مربوط به \fITCP_KEEPIDLE\fP، پارامتر \fIintvl\fP مقدار مربوط به \fITCP_KEEPINTVL\fP و پارامتر \fIcnt\fP مقدار مربوط به \fITCP_KEEPCNT\fP است که در صورت صفر بودن \fIon\fP نادیده گرفته می‌شوند. .sp با فعال بودن TCP keep\-alive، پارامتر \fIidle\fP مدت زمانی است (به ثانیه) که اتصال باید پیش از شروع ارسال کاوش‌های keep\-alive توسط TCP بی‌کار بماند. پارامتر \fIintvl\fP زمان (به ثانیه) بین کاوش‌های متوالی است. در صورتی که پروتکل TCP تعداد \fIcnt\fP کاوش را بدون دریافت هیچ پاسخی از سوی طرف مقابل ارسال کند، اتصال را قطع کرده و سپس قلاب با ارسال خطای \fBUV_ETIMEDOUT\fP به تابع بازخوانی مربوطه از بین می‌رود. .sp اگر یکی از مقادیر \fIidle\fP، \fIintvl\fP یا \fIcnt\fP کمتر از ۱ باشد، مقدار \fBUV_EINVAL\fP بازگردانده می‌شود. .sp تغییریافته در نسخه 1.52.0: پشتیبانی از تنظیم گزینه‌های سوکت \fITCP_KEEPINTVL\fP و \fITCP_KEEPCNT\fP اضافه شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 اطمینان حاصل کنید که گزینه‌های سوکت توسط سیستم‌عامل زیربنایی پشتیبانی می‌شوند. پلتفرم‌های تحت پشتیبانی در حال حاضر: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 AIX .IP \(bu 2 DragonFlyBSD .IP \(bu 2 FreeBSD .IP \(bu 2 illumos .IP \(bu 2 Linux .IP \(bu 2 macOS .IP \(bu 2 NetBSD .IP \(bu 2 Solaris .IP \(bu 2 Windows .UNINDENT .UNINDENT .UNINDENT .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_simultaneous_accepts(uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, int enable) فعال / غیرفعال کردن درخواست‌های پذیرش همگام ناهمگام (simultaneous accepts) که توسط سیستم‌عامل هنگام گوش دادن به اتصالات جدید TCP در صف قرار می‌گیرند. .sp این تنظیم برای تنظیم کارایی سرور TCP به عملکرد مطلوب استفاده می‌شود. فعال بودن پذیرش همزمان می‌تواند سرعت پذیرش اتصالات را به طور قابل توجهی افزایش دهد (که به همین دلیل به طور پیش‌فرض فعال است)، اما ممکن است منجر به توزیع بار نامتوازن در محیط‌های چندفرایندی شود. .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_bind(uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, const struct sockaddr *addr, unsigned int flags) اتصال (bind) قلاب به یک آدرس و پورت. .sp هنگامی که پورت از قبل گرفته شده باشد، می‌توان انتظار مشاهده خطای \fBUV_EADDRINUSE\fP از \fBuv_listen()\fP \%<#\:c\:.uv_listen> یا \fBuv_tcp_connect()\fP را داشت، مگر اینکه \fBUV_TCP_REUSEPORT\fP را در \fIflags\fP برای تمام سوکت‌های در حال اتصال مشخص کنید. به عبارت دیگر، فراخوانی موفقیت‌آمیز این تابع تضمین نمی‌کند که فراخوانی \fBuv_listen()\fP \%<#\:c\:.uv_listen> یا \fBuv_tcp_connect()\fP نیز با موفقیت انجام شود. .INDENT 7.0 .TP .B پارامترها .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- قلاب TCP. باید با \fBuv_tcp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBaddr\fP \-\- آدرس جهت اتصال. باید به یک \fBstruct sockaddr_in\fP یا \fBstruct sockaddr_in6\fP راه‌اندازی‌شده اشاره کند. .IP \(bu 2 \fBflags\fP \-\- فلگ‌هایی که رفتار اتصال سوکت را کنترل می‌کنند. \fBUV_TCP_IPV6ONLY\fP می‌تواند در \fIflags\fP قرار گیرد تا پشتیبانی دوپشته‌ای (dual\-stack) غیرفعال شده و تنها از IPv6 استفاده شود. \fBUV_TCP_REUSEPORT\fP می‌تواند در \fIflags\fP گنجانده شود تا گزینه سوکت \fISO_REUSEPORT\fP با قابلیت توزیع بار فعال شود و اتصالات ورودی بین تمام سوکت‌های شنونده در چند فرایند یا نخ توزیع گردند. .UNINDENT .TP .B مقادیر بازگشتی 0 در صورت موفقیت، یا کد خطای کوچکتر از 0 در صورت شکست. .UNINDENT .sp تغییریافته در نسخه 1.49.0: فلگ \fBUV_TCP_REUSEPORT\fP اضافه شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 فلگ \fBUV_TCP_REUSEPORT\fP در حال حاضر فقط در Linux 3.9+، DragonFlyBSD 3.6+، FreeBSD 12.0+، Solaris 11.4 و AIX 7.2.5+ در دسترس است. در سایر پلتفرم‌ها این تابع خطای UV_ENOTSUP را برمی‌گرداند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_getsockname(const uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, struct sockaddr *name, int *namelen) دریافت آدرس جاری که قلاب به آن متصل است. پارامتر \fIname\fP باید به یک قطعه حافظه معتبر و به اندازه کافی بزرگ اشاره کند؛ ساختار \fBstruct sockaddr_storage\fP برای پشتیبانی از IPv4 و IPv6 توصیه می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_getpeername(const uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, struct sockaddr *name, int *namelen) دریافت آدرس طرف متصل به قلاب (peer). پارامتر \fIname\fP باید به یک قطعه حافظه معتبر و به اندازه کافی بزرگ اشاره کند؛ ساختار \fBstruct sockaddr_storage\fP برای پشتیبانی از IPv4 و IPv6 توصیه می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_connect(uv_connect_t \%<#\:c\:.uv_connect_t> *req, uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, const struct sockaddr *addr, uv_connect_cb \%<#\:c\:.uv_connect_cb> cb) برقراری یک اتصال TCP از نوع IPv4 یا IPv6. یک قلاب TCP راه‌اندازی‌شده و یک ساختار \fBuv_connect_t\fP \%<#\:c\:.uv_connect_t> راه‌اندازی‌نشده فراهم کنید. پارامتر \fIaddr\fP باید به یک \fBstruct sockaddr_in\fP یا \fBstruct sockaddr_in6\fP راه‌اندازی‌شده اشاره کند. .sp در ویندوز اگر \fIaddr\fP برای اشاره به یک آدرس نامشخص (\fB0.0.0.0\fP یا \fB::\fP) راه‌اندازی شده باشد، برای اشاره به \fBlocalhost\fP تغییر داده می‌شود. این کار برای هماهنگی با رفتار سیستم‌های لینوکس انجام شده است. .sp تابع بازخوانی زمانی که اتصال برقرار شد یا خطایی در برقراری ارتباط رخ داد، فراخوانی می‌شود. .sp تغییریافته در نسخه 1.19.0: نگاشت \fB0.0.0.0\fP و \fB::\fP به \fBlocalhost\fP اضافه شد. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع رابط برنامه‌نویسی \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_tcp_close_reset(uv_tcp_t \%<#\:c\:.uv_tcp_t> *handle, uv_close_cb \%<#\:c\:.uv_close_cb> close_cb) بازنشانی یک اتصال TCP با ارسال یک بسته RST. این کار با تنظیم گزینه سوکت \fISO_LINGER\fP با بازه ماندگاری (linger interval) صفر و سپس فراخوانی \fBuv_close()\fP \%<#\:c\:.uv_close> انجام می‌شود. به دلیل برخی ناهماهنگی‌های پلتفرم، ترکیب فراخوانی‌های \fBuv_shutdown()\fP \%<#\:c\:.uv_shutdown> و \fBuv_tcp_close_reset()\fP مجاز نیست. .sp افزوده‌شده در نسخه 1.32.0. .UNINDENT .INDENT 0.0 .TP .B int uv_socketpair(int type, int protocol, uv_os_sock_t \%<#\:c\:.uv_os_sock_t> socket_vector[2], int flags0, int flags1) ایجاد یک جفت سوکت متصل‌به‌هم با مشخصات تعیین‌شده. قلاب‌های حاصل را می‌توان به \fIuv_tcp_open\fP ارسال کرد، با \fIuv_spawn\fP استفاده نمود، یا برای هر منظور دیگری به کار برد. .sp مقادیر معتبر برای \fIflags0\fP و \fIflags1\fP عبارتند از: .INDENT 7.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 UV_NONBLOCK_PIPE: قلاب سوکت مشخص‌شده را برای کاربرد ورودی/خروجی \fIOVERLAPPED\fP یا \fIFIONBIO\fP/\fIO_NONBLOCK\fP باز می‌کند. این مورد برای قلاب‌هایی که توسط libuv استفاده خواهند شد توصیه می‌شود، و در موارد دیگر معمولاً پیشنهاد نمی‌گردد. .UNINDENT .UNINDENT .UNINDENT .sp معادل socketpair(2) \% با دامنه AF_UNIX. .sp افزوده‌شده در نسخه 1.41.0. .UNINDENT .SS \fBuv_pipe_t\fP \-\-\- هندل پایپ (Pipe handle) .sp هندل‌های پایپ یک لایه انتزاعی روی فایل‌های استریم در یونیکس (شامل سوکت‌های دامنه محلی، پایپ‌ها و FIFOها) و پایپ‌های نام‌گذاری‌شده در ویندوز فراهم می‌کنند. .sp \fBuv_pipe_t\fP یک «زیرکلاس» از \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t>\& است. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_pipe_t نوع هندل پایپ. .UNINDENT .SS اعضای عمومی (Public members) .INDENT 0.0 .TP .B int uv_pipe_t \%<#\:c\:.uv_pipe_t>\&.ipc مشخص می‌کند که آیا این پایپ برای انتقال هندل بین پردازه‌ها مناسب است یا خیر. تنها پایپ متصلی که قرار است هندل‌ها را انتقال دهد باید این فلگ را تنظیم داشته باشد، نه پایپ شنونده‌ای که \fBuv_accept\fP روی آن فراخوانی می‌شود. .UNINDENT .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B int uv_pipe_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, int ipc) راه‌اندازی یک هندل پایپ. آرگومان \fIipc\fP یک مقدار بولی است که نشان می‌دهد آیا این پایپ برای انتقال هندل بین پردازه‌ها استفاده خواهد شد یا خیر (که ممکن است بایت‌های ارسالی روی خط را تغییر دهد). تنها پایپ متصلی که قرار است هندل‌ها را انتقال دهد باید این فلگ را تنظیم داشته باشد، نه پایپ شنونده‌ای که \fBuv_accept\fP روی آن فراخوانی می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_open(uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, uv_file \%<#\:c\:.uv_file> file) باز کردن یک توصیف‌گر فایل یا HANDLE موجود به عنوان پایپ. .sp تغییریافته در نسخه 1.2.1: توصیف‌گر فایل روی حالت غیرمسدودکننده (non\-blocking) تنظیم می‌شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 نوع توصیف‌گر فایل یا HANDLE پاس‌داده‌شده بررسی نمی‌شود، اما لازم است که نمایانگر یک پایپ معتبر باشد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_bind(uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, const char *name) متصل کردن پایپ به یک مسیر فایل (در یونیکس) یا یک نام (در ویندوز). .sp برخلاف \fBuv_pipe_bind2()\fP\&، از سوکت‌های فضای نام انتزاعی (abstract namespace) لینوکس پشتیبانی نمی‌کند. .sp نام مستعار برای \fBuv_pipe_bind2(handle, name, strlen(name), 0)\fP\&. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 مسیرها در یونیکس به \fBsizeof(sockaddr_un.sun_path)\fP بایت کوتاه‌سازی (truncate) می‌شوند که معمولاً بین ۹۲ تا ۱۰۸ بایت است. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_bind2(uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, const char *name, size_t namelen, unsigned int flags) متصل کردن پایپ به یک مسیر فایل (در یونیکس) یا یک نام (در ویندوز). .sp \fBflags\fP باید صفر یا \fBUV_PIPE_NO_TRUNCATE\fP باشد. برای فلگ‌های پشتیبانی‌نشده بدون انجام عملیات bind مقدار \fBUV_EINVAL\fP برمی‌گرداند. .sp از سوکت‌های فضای نام انتزاعی لینوکس پشتیبانی می‌کند. \fBnamelen\fP باید بایت nul ابتدایی را شامل شود، اما بایت nul انتهایی را خیر. .sp افزوده شده در نسخه 1.46.0. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 مسیرها در یونیکس به \fBsizeof(sockaddr_un.sun_path)\fP بایت کوتاه‌سازی می‌شوند که معمولاً بین ۹۲ تا ۱۰۸ بایت است، مگر اینکه فلگ \fBUV_PIPE_NO_TRUNCATE\fP مشخص شده باشد که در این صورت خطای \fBUV_EINVAL\fP برگردانده می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B void uv_pipe_connect(uv_connect_t \%<#\:c\:.uv_connect_t> *req, uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, const char *name, uv_connect_cb \%<#\:c\:.uv_connect_cb> cb) اتصال به سوکت دامنه یونیکس یا پایپ نام‌گذاری‌شده در ویندوز. .sp برخلاف \fBuv_pipe_connect2()\fP\&، از سوکت‌های فضای نام انتزاعی لینوکس پشتیبانی نمی‌کند. .sp نام مستعار برای \fBuv_pipe_connect2(req, handle, name, strlen(name), 0, cb)\fP\&. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 مسیرها در یونیکس به \fBsizeof(sockaddr_un.sun_path)\fP بایت کوتاه‌سازی می‌شوند که معمولاً بین ۹۲ تا ۱۰۸ بایت است. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_connect2(uv_connect_t \%<#\:c\:.uv_connect_t> *req, uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, const char *name, size_t namelen, unsigned int flags, uv_connect_cb \%<#\:c\:.uv_connect_cb> cb) اتصال به سوکت دامنه یونیکس یا پایپ نام‌گذاری‌شده در ویندوز. .sp \fBflags\fP باید صفر یا \fBUV_PIPE_NO_TRUNCATE\fP باشد. برای فلگ‌های پشتیبانی‌نشده بدون انجام عملیات اتصال مقدار \fBUV_EINVAL\fP برمی‌گرداند. .sp از سوکت‌های فضای نام انتزاعی لینوکس پشتیبانی می‌کند. \fBnamelen\fP باید بایت nul ابتدایی را شامل شود، اما بایت nul انتهایی را خیر. .sp افزوده شده در نسخه 1.46.0. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 مسیرها در یونیکس به \fBsizeof(sockaddr_un.sun_path)\fP بایت کوتاه‌سازی می‌شوند که معمولاً بین ۹۲ تا ۱۰۸ بایت است، مگر اینکه فلگ \fBUV_PIPE_NO_TRUNCATE\fP مشخص شده باشد که در این صورت خطای \fBUV_EINVAL\fP برگردانده می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_getsockname(const uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, char *buffer, size_t *size) دریافت نام سوکت دامنه یونیکس یا پایپ نام‌گذاری‌شده. .sp باید یک بافر از پیش تخصیص‌یافته فراهم شود. پارامتر size طول بافر را نگه می‌دارد و در خروجی روی تعداد بایت‌های نوشته‌شده در بافر تنظیم می‌شود. اگر بافر به اندازه کافی بزرگ نباشد \fBUV_ENOBUFS\fP برگردانده می‌شود و len حاوی اندازه مورد نیاز خواهد بود. .sp تغییریافته در نسخه 1.3.0: طول برگردانده‌شده دیگر شامل بایت تهی (null) پایانی نیست و بافر با null خاتمه نمی‌یابد. .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_getpeername(const uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, char *buffer, size_t *size) دریافت نام سوکت دامنه یونیکس یا پایپ نام‌گذاری‌شده که هندل به آن متصل است. .sp باید یک بافر از پیش تخصیص‌یافته فراهم شود. پارامتر size طول بافر را نگه می‌دارد و در خروجی روی تعداد بایت‌های نوشته‌شده در بافر تنظیم می‌شود. اگر بافر به اندازه کافی بزرگ نباشد \fBUV_ENOBUFS\fP برگردانده می‌شود و len حاوی اندازه مورد نیاز خواهد بود. .sp افزوده شده در نسخه 1.3.0. .UNINDENT .INDENT 0.0 .TP .B void uv_pipe_pending_instances(uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, int count) تنظیم تعداد هندل‌های وهله پایپ معلق زمانی که سرور پایپ منتظر اتصالات است. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این تنظیم فقط در ویندوز اعمال می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_pending_count(uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle) .UNINDENT .INDENT 0.0 .TP .B uv_handle_type \%<#\:c\:.uv_handle_type> uv_pipe_pending_type(uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle) برای دریافت هندل‌ها روی پایپ‌های IPC استفاده می‌شود. .sp ابتدا \fBuv_pipe_pending_count()\fP را فراخوانی کنید؛ اگر مقدار آن بزرگتر از ۰ بود، یک هندل از نوع (\fItype\fP) داده‌شده که توسط \fBuv_pipe_pending_type()\fP برگردانده می‌شود را راه‌اندازی کرده و \fBuv_accept(pipe, handle)\fP\& را فراخوانی کنید. .UNINDENT .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 توابع API مربوط به \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_pipe_chmod(uv_pipe_t \%<#\:c\:.uv_pipe_t> *handle, int flags) مجوزهای پایپ را تغییر می‌دهد و اجازه می‌دهد پردازه‌های اجراشده توسط کاربران مختلف به آن دسترسی داشته باشند. پایپ را برای همه کاربران قابل نوشتن یا قابل خواندن می‌کند. حالت می‌تواند \fBUV_WRITABLE\fP، \fBUV_READABLE\fP یا \fBUV_WRITABLE | UV_READABLE\fP\& باشد. این تابع مسدودکننده (blocking) است. .sp افزوده شده در نسخه 1.16.0. .UNINDENT .INDENT 0.0 .TP .B int uv_pipe(uv_file \%<#\:c\:.uv_file> fds[2], int read_flags, int write_flags) ایجاد یک جفت هندل پایپ متصل به هم. داده‌ها می‌توانند در \fIfds[1]\fP نوشته شده و از \fIfds[0]\fP\& خوانده شوند. هندل‌های حاصل را می‌توان به \fIuv_pipe_open\fP منتقل کرد، با \fIuv_spawn\fP استفاده نمود، یا برای هر منظور دیگری به کار برد. .sp مقادیر معتبر برای \fIflags\fP عبارتند از: .INDENT 7.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 UV_NONBLOCK_PIPE: هندل سوکت مشخص‌شده را برای استفاده ورودی/خروجی \fIOVERLAPPED\fP یا \fIFIONBIO\fP/\fIO_NONBLOCK\fP باز می‌کند. این فلگ برای هندل‌هایی که قرار است توسط libuv استفاده شوند توصیه می‌شود و در غیر این صورت معمولاً توصیه نمی‌گردد. .UNINDENT .UNINDENT .UNINDENT .sp معادل pipe(2) \% با فلگ تنظیم‌شده \fIO_CLOEXEC\fP\&. .sp افزوده شده در نسخه 1.41.0. .UNINDENT .SS \fBuv_tty_t\fP \-\-\- هندل TTY (TTY handle) .sp هندل‌های TTY یک استریم برای کنسول فراهم می‌کنند. .sp \fBuv_tty_t\fP یک «زیرکلاس» از \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t>\& است. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_tty_t نوع هندل TTY. .UNINDENT .INDENT 0.0 .TP .B enum uv_tty_mode_t افزوده شده در نسخه 1.2.0. .sp نوع حالت TTY: .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { /* حالت اولیه/عادی ترمینال */ UV_TTY_MODE_NORMAL, /* * حالت ورودی خام (در ویندوز، ENABLE_WINDOW_INPUT نیز فعال می‌شود). * ممکن است در نسخه‌های آینده libuv معادل UV_TTY_MODE_RAW_VT شود. */ UV_TTY_MODE_RAW, /* حالت ورودی/خروجی دودویی ایمن برای IPC (فقط یونیکس) */ UV_TTY_MODE_IO, /* حالت ورودی خام. در ویندوز ENABLE_VIRTUAL_TERMINAL_INPUT نیز تنظیم می‌شود. */ UV_TTY_MODE_RAW_VT } uv_tty_mode_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_tty_vtermstate_t نوع حالت ترمینال مجازی کنسول: .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { /* * کنسول از پردازش توالی‌های ترمینال مجازی پشتیبانی می‌کند * (کنسول جدید ویندوز ۱۰، ConEmu) */ UV_TTY_SUPPORTED, /* کنسول نمی‌تواند توالی‌های ترمینال مجازی را پردازش کند. (کنسول قدیمی) */ UV_TTY_UNSUPPORTED } uv_tty_vtermstate_t .EE .UNINDENT .UNINDENT .UNINDENT .SS اعضای عمومی (Public members) .sp ندارد (N/A) .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B int uv_tty_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_tty_t \%<#\:c\:.uv_tty_t> *handle, uv_file \%<#\:c\:.uv_file> fd, int unused) راه‌اندازی یک استریم TTY جدید با توصیف‌گر فایل داده‌شده. معمولاً توصیف‌گر فایل یکی از موارد زیر خواهد بود: .INDENT 7.0 .IP \(bu 2 0 = ورودی استاندارد (stdin) .IP \(bu 2 1 = خروجی استاندارد (stdout) .IP \(bu 2 2 = خطای استاندارد (stderr) .UNINDENT .sp در یونیکس این تابع مسیر fd ترمینال را با استفاده از ttyname_r(3) \% تعیین کرده، آن را باز می‌کند و در صورتی که توصیف‌گر فایل پاس‌داده‌شده به یک TTY اشاره کند، از آن استفاده می‌نماید. این کار به libuv اجازه می‌دهد TTY را بدون تأثیر بر سایر پردازه‌هایی که در TTY مشترک هستند در حالت غیرمسدودکننده قرار دهد. .sp این تابع در سیستم‌هایی که از ioctl TIOCGPTN یا TIOCPTYGNAME پشتیبانی نمی‌کنند (مانند OpenBSD و Solaris) در برابر چندنخی ایمن (thread\-safe) نیست. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 اگر بازگشایی مجدد TTY با شکست مواجه شود، libuv به عملیات نوشتن مسدودکننده (blocking) بازمی‌گردد. .UNINDENT .UNINDENT .sp تغییریافته در نسخه 1.23.1: پارامتر \fIreadable\fP اکنون استفاده‌نشده و نادیده گرفته می‌شود. مقدار صحیح اکنون به طور خودکار از هسته تشخیص داده می‌شود. .sp تغییریافته در نسخه 1.9.0: مسیر TTY توسط ttyname_r(3) \% تعیین می‌شود. در نسخه‌های قبلی، libuv به جای آن \fI/dev/tty\fP را باز می‌کرد. .sp تغییریافته در نسخه 1.5.0: تلاش برای راه‌اندازی استریم TTY با توصیف‌گر فایلی که به یک فایل معمولی اشاره دارد در یونیکس \fIUV_EINVAL\fP برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B int uv_tty_set_mode(uv_tty_t \%<#\:c\:.uv_tty_t> *handle, uv_tty_mode_t \%<#\:c\:.uv_tty_mode_t> mode) تغییریافته در نسخه 1.2.0: حالت به عنوان یک مقدار \fBuv_tty_mode_t\fP مشخص می‌شود. .sp تنظیم TTY با استفاده از حالت ترمینال مشخص‌شده. .UNINDENT .INDENT 0.0 .TP .B int uv_tty_reset_mode(void) هنگام خروج برنامه فراخوانی می‌شود. تنظیمات TTY را برای پردازه بعدی که کنترل را در دست می‌گیرد، به مقادیر پیش‌فرض بازمی‌گرداند. .sp این تابع در پلتفرم‌های یونیکس async signal\-safe است، اما اگر در حین اجرای درون \fBuv_tty_set_mode()\fP\& فراخوانی شود، می‌تواند با کد خطای \fBUV_EBUSY\fP با شکست مواجه شود. .UNINDENT .INDENT 0.0 .TP .B int uv_tty_get_winsize(uv_tty_t \%<#\:c\:.uv_tty_t> *handle, int *width, int *height) دریافت اندازه فعلی پنجره. در صورت موفقیت ۰ برمی‌گرداند. .UNINDENT .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 توابع API مربوط به \fBuv_stream_t\fP \%<#\:c\:.uv_stream_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B void uv_tty_set_vterm_state(uv_tty_vtermstate_t \%<#\:c\:.uv_tty_vtermstate_t> state) کنترل می‌کند که آیا توالی‌های ترمینال مجازی کنسول توسط libuv پردازش شوند یا کنسول. به‌ویژه برای فعال‌سازی پشتیبانی ConEmu از ANSI X3.64 و رنگ‌های ۲۵۶تایی Xterm مفید است. در غیر این صورت کنسول‌های ویندوز ۱۰ معمولاً به طور خودکار شناسایی می‌شوند. .sp این تابع فقط در سیستم‌های ویندوز معنادار است. در یونیکس بدون هیچ خطایی نادیده گرفته می‌شود. .sp افزوده شده در نسخه 1.33.0. .UNINDENT .INDENT 0.0 .TP .B int uv_tty_get_vterm_state(uv_tty_vtermstate_t \%<#\:c\:.uv_tty_vtermstate_t> *state) دریافت وضعیت فعلی پردازش توالی‌های ترمینال مجازی کنسول توسط libuv یا کنسول. .sp این تابع در یونیکس پیاده‌سازی نشده است و مقدار \fBUV_ENOTSUP\fP\& را برمی‌گرداند. .sp افزوده شده در نسخه 1.33.0. .UNINDENT .SS \fBuv_udp_t\fP \-\-\- هندل UDP (UDP handle) .sp هندل‌های UDP ارتباطات UDP را برای کلاینت‌ها و سرورها کپسوله‌سازی می‌کنند. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_udp_t نوع هندل UDP. .UNINDENT .INDENT 0.0 .TP .B type uv_udp_send_t نوع درخواست ارسال UDP. .UNINDENT .INDENT 0.0 .TP .B enum uv_udp_flags فلگ‌های مورداستفاده در \fBuv_udp_bind()\fP و \fBuv_udp_recv_cb\fP\&.. .INDENT 7.0 .INDENT 3.5 .sp .EX enum uv_udp_flags { /* غیرفعال‌سازی حالت dual stack */ UV_UDP_IPV6ONLY = 1, /* * نشان می‌دهد پیام به دلیل کوچک بودن بافر خواندن کوتاه‌سازی شده است. * بخش باقیمانده توسط سیستم‌عامل دور ریخته شده است. در uv_udp_recv_cb استفاده می‌شود. */ UV_UDP_PARTIAL = 2, /* * نشان می‌دهد که آیا هنگام bind کردن هندل SO_REUSEADDR تنظیم شود یا خیر. * این فلگ در BSDها (به جز DragonFlyBSD)، OS X و پلتفرم‌های دیگری که SO_REUSEPORT * در آن‌ها قابلیت توزیع بار را ندارد، فلگ سوکت SO_REUSEPORT را تنظیم می‌کند * (برعکس عملکرد UV_UDP_REUSEPORT). در سایر پلتفرم‌های یونیکس، فلگ SO_REUSEADDR * را تنظیم می‌کند. بدین معنا که چندین نخ یا پردازه می‌توانند بدون خطا به یک * آدرس متصل شوند (به شرطی که همگی فلگ را تنظیم کنند) اما فقط آخرین متصل‌شونده * ترافیک را دریافت خواهد کرد و در عمل پورت را از شنونده قبلی «می‌رباید». */ UV_UDP_REUSEADDR = 4, /* * نشان می‌دهد که پیام توسط recvmmsg دریافت شده است، بنابراین بافر ارائه‌شده * نباید توسط کالبک recv_cb آزاد شود. */ UV_UDP_MMSG_CHUNK = 8, /* * نشان می‌دهد بافر ارائه‌شده به طور کامل توسط recvmmsg استفاده شده است و * اکنون باید توسط کالبک recv_cb آزاد شود. هنگامی که این فلگ در uv_udp_recv_cb * تنظیم شده باشد، nread همیشه 0 و addr همیشه NULL خواهد بود. */ UV_UDP_MMSG_FREE = 16, /* * نشان می‌دهد که آیا هنگام bind کردن هندل IP_RECVERR/IPV6_RECVERR تنظیم شود یا خیر. * این فلگ IP_RECVERR را برای سوکت‌های IPv4 و IPV6_RECVERR را برای سوکت‌های IPv6 در * لینوکس تنظیم می‌کند. این کار مانع از سرکوب برخی خطاهای ICMP توسط هسته لینوکس شده * و گزارش کامل خطای ICMP را برای بازیابی سریع‌تر فعال می‌کند. * این فلگ در پلتفرم‌های غیرلینوکسی بی‌اثر (no-op) است. */ UV_UDP_LINUX_RECVERR = 32, /* * نشان می‌دهد که آیا هنگام bind کردن هندل SO_REUSEPORT تنظیم شود یا خیر. * این گزینه سوکت SO_REUSEPORT را در پلتفرم‌های پشتیبانی‌شده تنظیم می‌کند. * برخلاف UV_UDP_REUSEADDR، این فلگ باعث می‌شود چندین نخ یا پردازه که به همان آدرس * و پورت متصل می‌شوند، پورت را «به اشتراک بگذارند»، یعنی دیتاگرام‌های ورودی بین * سوکت‌های گیرنده میان نخ‌ها یا پردازه‌ها توزیع شوند. * * این فلگ در حال حاضر فقط در لینوکس +3.9، دراگون‌فلای‌بی‌اس‌دی +3.6، * فری‌بی‌اس‌دی +12.0، سولاریس 11.4 و AIX +7.2.5 در دسترس است. */ UV_UDP_REUSEPORT = 64, /* * نشان می‌دهد در صورت در دسترس بودن، باید از recvmmsg استفاده شود. */ UV_UDP_RECVMMSG = 256 }; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_udp_send_cb)(uv_udp_send_t \%<#\:c\:.uv_udp_send_t> *req, int status) تعریف نوع برای کالبک پاس‌داده‌شده به \fBuv_udp_send()\fP که پس از ارسال داده فراخوانی می‌شود. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_udp_recv_cb)(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, ssize_t nread, const uv_buf_t \%<#\:c\:.uv_buf_t> *buf, const struct sockaddr *addr, unsigned flags) تعریف نوع برای کالبک پاس‌داده‌شده به \fBuv_udp_recv_start()\fP که هنگام دریافت داده توسط نقطه پایانی فراخوانی می‌شود. .INDENT 7.0 .IP \(bu 2 \fIhandle\fP: هندل UDP .IP \(bu 2 \fInread\fP: تعداد بایت‌های دریافت‌شده. اگر داده دیگری برای خواندن وجود نداشته باشد، ۰ است. توجه داشته باشید که ۰ ممکن است به این معنا نیز باشد که یک دیتاگرام خالی دریافت شده است (در این حالت \fIaddr\fP برابر NULL نیست). اگر خطای انتقال شناسایی شده باشد، کوچکتر از ۰ است؛ در صورت استفاده از recvmmsg(2) \% قطعه داده دیگری دریافت نخواهد شد و بافر را می‌توان با اطمینان آزاد کرد. .IP \(bu 2 \fIbuf\fP: ساختار \fBuv_buf_t\fP \%<#\:c\:.uv_buf_t> حاوی داده‌های دریافت‌شده. .IP \(bu 2 \fIaddr\fP: ساختار \fBstruct sockaddr*\fP حاوی آدرس فرستنده. می‌تواند NULL باشد. فقط در طول مدت فراخوانی کالبک معتبر است. .IP \(bu 2 \fIflags\fP: یک یا چند ثابت UV_UDP_* که با عملگر OR ترکیب شده‌اند. .UNINDENT .sp کالبک‌گیرنده مسئول آزادسازی بافر است، libuv از آن مجدداً استفاده نمی‌کند. در صورت بروز خطا، بافر ممکن است یک بافر تهی باشد (جایی که \fIbuf\->base\fP == NULL و \fIbuf\->len\fP == 0 است). .sp هنگام استفاده از recvmmsg(2) \%، قطعات داده دارای فلگ \fIUV_UDP_MMSG_CHUNK\fP خواهند بود که نباید آزاد شوند. در صورت عدم بروز خطا، یک فراخوانی نهایی کالبک با \fInread\fP برابر با ۰، \fIaddr\fP برابر با NULL و بافر اشاره‌کننده به داده‌های اولیه با فلگ \fIUV_UDP_MMSG_CHUNK\fP پاک‌شده و فلگ \fIUV_UDP_MMSG_FREE\fP تنظیم‌شده وجود خواهد داشت. در صورت بروز خطای سوکت UDP، مقدار \fInread\fP کمتر از ۰ خواهد بود. در هر دو حالت، کالبک‌گیرنده اکنون می‌تواند با خیال راحت بافر ارائه‌شده را آزاد کند. .sp تغییریافته در نسخه 1.40.0: فلگ \fIUV_UDP_MMSG_FREE\fP اضافه شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 کالبک دریافت هنگامی که چیزی برای خواندن وجود ندارد با \fInread\fP == 0 و \fIaddr\fP == NULL، و هنگامی که یک بسته UDP خالی دریافت می‌شود با \fInread\fP == 0 و \fIaddr\fP != NULL فراخوانی خواهد شد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_membership نوع عضویت برای یک آدرس چندپخشی (multicast). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_LEAVE_GROUP = 0, UV_JOIN_GROUP } uv_membership; .EE .UNINDENT .UNINDENT .UNINDENT .SS اعضای عمومی (Public members) .INDENT 0.0 .TP .B size_t uv_udp_t \%<#\:c\:.uv_udp_t>\&.send_queue_size تعداد بایت‌های در صف برای ارسال. این فیلد مشخصاً نشان می‌دهد چه مقدار اطلاعات در حال حاضر در صف قرار دارد. .UNINDENT .INDENT 0.0 .TP .B size_t uv_udp_t \%<#\:c\:.uv_udp_t>\&.send_queue_count تعداد درخواست‌های ارسال فعلی در صف که در انتظار پردازش هستند. .UNINDENT .INDENT 0.0 .TP .B uv_udp_t \%<#\:c\:.uv_udp_t> *uv_udp_send_t \%<#\:c\:.uv_udp_send_t>\&.handle هندل UDP که این درخواست ارسال روی آن در حال انجام است. .UNINDENT .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B int uv_udp_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_udp_t \%<#\:c\:.uv_udp_t> *handle) راه‌اندازی یک هندل UDP جدید. سوکت واقعی به صورت تنبلانه (lazily) ایجاد می‌شود. در صورت موفقیت ۰ برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_init_ex(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_udp_t \%<#\:c\:.uv_udp_t> *handle, unsigned int flags) راه‌اندازی هندل با فلگ‌های مشخص‌شده. ۸ بیت پایینی پارامتر \fIflags\fP به عنوان دامنه (domain) سوکت استفاده می‌شوند. یک سوکت برای دامنه داده‌شده ایجاد خواهد شد. اگر دامنه مشخص‌شده \fBAF_UNSPEC\fP باشد، همانند \fBuv_udp_init()\fP هیچ سوکتی ایجاد نمی‌شود. .sp بیت‌های باقیمانده می‌توانند برای تنظیم یکی از این فلگ‌ها استفاده شوند: .INDENT 7.0 .IP \(bu 2 \fIUV_UDP_RECVMMSG\fP: در صورت تنظیم و پشتیبانی پلتفرم، از recvmmsg(2) \% استفاده خواهد شد. .UNINDENT .sp افزوده شده در نسخه 1.7.0. .sp تغییریافته در نسخه 1.37.0: فلگ \fIUV_UDP_RECVMMSG\fP اضافه شد. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_open_ex(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, uv_os_sock_t \%<#\:c\:.uv_os_sock_t> sock, unsigned int flags) باز کردن یک توصیف‌گر فایل یا SOCKET ویندوز موجود به عنوان یک هندل UDP. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBsock\fP \-\- یک سوکت موجود برای اتصال به هندل. .IP \(bu 2 \fBflags\fP \-\- فلگ‌هایی که رفتار سوکت را کنترل می‌کنند؛ \fBUV_UDP_REUSEADDR\fP و \fBUV_UDP_REUSEPORT\fP پشتیبانی می‌شوند. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .sp افزوده شده در نسخه 1.52.0. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_open(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, uv_os_sock_t \%<#\:c\:.uv_os_sock_t> sock) باز کردن یک توصیف‌گر فایل یا SOCKET ویندوز موجود به عنوان یک هندل UDP. .sp فقط در یونیکس: تنها الزام آرگومان \fIsock\fP این است که از قرارداد دیتاگرام پیروی کند (در حالت بدون اتصال کار کند، از sendmsg()/recvmsg() پشتیبانی نماید و غیره). به عبارت دیگر، سایر سوکت‌های نوع دیتاگرام مانند raw sockets یا netlink sockets نیز می‌توانند به این تابع پاس داده شوند. .sp تغییریافته در نسخه 1.2.1: توصیف‌گر فایل روی حالت غیرمسدودکننده تنظیم می‌شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 نوع توصیف‌گر فایل یا SOCKET پاس‌داده‌شده بررسی نمی‌شود، اما لازم است که نمایانگر یک سوکت دیتاگرام معتبر باشد. .sp درون تابع، گزینه سوکت SO_REUSEADDR بدون قید و شرط تنظیم می‌شود. این بدان معناست که فلگ بازاستفاده بدون در نظر گرفتن قصد کاربر همیشه فعال است. برای کنترل بیشتر از \fBuv_udp_open_ex()\fP استفاده کنید. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_bind(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, const struct sockaddr *addr, unsigned int flags) متصل کردن هندل UDP به یک آدرس IP و پورت. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBaddr\fP \-\- ساختار \fIstruct sockaddr_in\fP یا \fIstruct sockaddr_in6\fP حاوی آدرس و پورت برای متصل شدن. .IP \(bu 2 \fBflags\fP \-\- نشان می‌دهد سوکت چگونه bind خواهد شد؛ \fBUV_UDP_IPV6ONLY\fP، \fBUV_UDP_REUSEADDR\fP، \fBUV_UDP_REUSEPORT\fP و \fBUV_UDP_RECVERR\fP پشتیبانی می‌شوند. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .sp تغییریافته در نسخه 1.49.0: فلگ \fBUV_UDP_REUSEPORT\fP اضافه شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 فلگ \fBUV_UDP_REUSEPORT\fP در حال حاضر فقط در لینوکس +3.9، دراگون‌فلای‌بی‌اس‌دی +3.6، فری‌بی‌اس‌دی +12.0، سولاریس 11.4 و AIX +7.2.5 در دسترس است. در پلتفرم‌های دیگر این تابع خطای UV_ENOTSUP برمی‌گرداند. برای پلتفرم‌هایی که در آن‌ها \fISO_REUSEPORT\fP دارای قابلیت توزیع بار است، مشخص کردن همزمان \fBUV_UDP_REUSEADDR\fP و \fBUV_UDP_REUSEPORT\fP در flags مجاز بوده و \fISO_REUSEPORT\fP همیشه رفتار \fISO_REUSEADDR\fP را بازنویسی (override) می‌کند. برای پلتفرم‌هایی که در آن‌ها \fISO_REUSEPORT\fP قابلیت توزیع بار را ندارد، مشخص کردن همزمان \fBUV_UDP_REUSEADDR\fP و \fBUV_UDP_REUSEPORT\fP با شکست مواجه شده و خطای UV_ENOTSUP برمی‌گرداند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_connect(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, const struct sockaddr *addr) مرتبط کردن هندل UDP با یک آدرس و پورت دوردست، به طوری که هر پیامی که توسط این هندل ارسال می‌شود به طور خودکار به آن مقصد فرستاده شود. فراخوانی این تابع با \fIaddr\fP برابر \fINULL\fP اتصال هندل را قطع می‌کند. تلاش برای فراخوانی \fIuv_udp_connect()\fP روی یک هندل از پیش متصل‌شده منجر به خطای \fIUV_EISCONN\fP می‌شود. تلاش برای قطع اتصال هندلی که متصل نیست خطای \fIUV_ENOTCONN\fP را برمی‌گرداند. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBaddr\fP \-\- ساختار \fIstruct sockaddr_in\fP یا \fIstruct sockaddr_in6\fP حاوی آدرس و پورت مقصد. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .sp افزوده شده در نسخه 1.27.0. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_getpeername(const uv_udp_t \%<#\:c\:.uv_udp_t> *handle, struct sockaddr *name, int *namelen) دریافت IP و پورت دوردست در هندل‌های متصل UDP. در هندل‌های غیرمتصل، مقدار \fIUV_ENOTCONN\fP را برمی‌گرداند. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی و bind شده باشد. .IP \(bu 2 \fBname\fP \-\- اشاره‌گر به ساختاری که با داده‌های آدرس پر می‌شود. برای پشتیبانی از IPv4 و IPv6 باید از \fIstruct sockaddr_storage\fP استفاده شود. .IP \(bu 2 \fBnamelen\fP \-\- در ورودی نشان‌دهنده اندازه بافر \fIname\fP است. در خروجی نشان می‌دهد چه مقدار از آن پر شده است. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .sp افزوده شده در نسخه 1.27.0. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_getsockname(const uv_udp_t \%<#\:c\:.uv_udp_t> *handle, struct sockaddr *name, int *namelen) دریافت IP و پورت محلی هندل UDP. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی و bind شده باشد. .IP \(bu 2 \fBname\fP \-\- اشاره‌گر به ساختاری که با داده‌های آدرس پر می‌شود. برای پشتیبانی از IPv4 و IPv6 باید از \fIstruct sockaddr_storage\fP استفاده شود. .IP \(bu 2 \fBnamelen\fP \-\- در ورودی نشان‌دهنده اندازه بافر \fIname\fP است. در خروجی نشان می‌دهد چه مقدار از آن پر شده است. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_set_membership(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, const char *multicast_addr, const char *interface_addr, uv_membership \%<#\:c\:.uv_membership> membership) تنظیم وضعیت عضویت برای یک آدرس چندپخشی (multicast). .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBmulticast_addr\fP \-\- آدرس چندپخشی برای تنظیم عضویت. .IP \(bu 2 \fBinterface_addr\fP \-\- آدرس رابط شبکه (interface). .IP \(bu 2 \fBmembership\fP \-\- باید \fBUV_JOIN_GROUP\fP یا \fBUV_LEAVE_GROUP\fP باشد. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_set_source_membership(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, const char *multicast_addr, const char *interface_addr, const char *source_addr, uv_membership \%<#\:c\:.uv_membership> membership) تنظیم عضویت برای یک گروه چندپخشی مبتنی بر منبع خاص (source\-specific multicast). .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBmulticast_addr\fP \-\- آدرس چندپخشی برای تنظیم عضویت. .IP \(bu 2 \fBinterface_addr\fP \-\- آدرس رابط شبکه. .IP \(bu 2 \fBsource_addr\fP \-\- آدرس منبع. .IP \(bu 2 \fBmembership\fP \-\- باید \fBUV_JOIN_GROUP\fP یا \fBUV_LEAVE_GROUP\fP باشد. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .sp افزوده شده در نسخه 1.32.0. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_set_multicast_loop(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, int on) تنظیم فلگ حلقه چندپخشی IP (multicast loop). باعث بازگشت بسته‌های چندپخشی به سوکت‌های محلی می‌شود. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init_ex()\fP به صورت \fBAF_INET\fP یا \fBAF_INET6\fP راه‌اندازی شده باشد، یا به صراحت با \fBuv_udp_bind()\fP یا به طور ضمنی با \fBuv_udp_send()\fP یا \fBuv_udp_recv_start()\fP به یک آدرس متصل شده باشد. .IP \(bu 2 \fBon\fP \-\- مقدار ۱ برای روشن، ۰ برای خاموش. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_set_multicast_ttl(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, int ttl) تنظیم TTL چندپخشی. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init_ex()\fP به صورت \fBAF_INET\fP یا \fBAF_INET6\fP راه‌اندازی شده باشد، یا به صراحت با \fBuv_udp_bind()\fP یا به طور ضمنی با \fBuv_udp_send()\fP یا \fBuv_udp_recv_start()\fP به یک آدرس متصل شده باشد. .IP \(bu 2 \fBttl\fP \-\- مقدار بین ۱ تا ۲۵۵. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_set_multicast_interface(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, const char *interface_addr) تنظیم رابط چندپخشی برای ارسال یا دریافت داده. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init_ex()\fP به صورت \fBAF_INET\fP یا \fBAF_INET6\fP راه‌اندازی شده باشد، یا به صراحت با \fBuv_udp_bind()\fP یا به طور ضمنی با \fBuv_udp_send()\fP یا \fBuv_udp_recv_start()\fP به یک آدرس متصل شده باشد. .IP \(bu 2 \fBinterface_addr\fP \-\- آدرس رابط شبکه. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_set_broadcast(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, int on) روشن یا خاموش کردن پخش همگانی (broadcast). .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init_ex()\fP به صورت \fBAF_INET\fP یا \fBAF_INET6\fP راه‌اندازی شده باشد، یا به صراحت با \fBuv_udp_bind()\fP یا به طور ضمنی با \fBuv_udp_send()\fP یا \fBuv_udp_recv_start()\fP به یک آدرس متصل شده باشد. .IP \(bu 2 \fBon\fP \-\- مقدار ۱ برای روشن، ۰ برای خاموش. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_set_ttl(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, int ttl) تنظیم طول عمر بسته (Time To Live / TTL). .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init_ex()\fP به صورت \fBAF_INET\fP یا \fBAF_INET6\fP راه‌اندازی شده باشد، یا به صراحت با \fBuv_udp_bind()\fP یا به طور ضمنی با \fBuv_udp_send()\fP یا \fBuv_udp_recv_start()\fP به یک آدرس متصل شده باشد. .IP \(bu 2 \fBttl\fP \-\- مقدار بین ۱ تا ۲۵۵. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_udp_send(uv_udp_send_t \%<#\:c\:.uv_udp_send_t> *req, uv_udp_t \%<#\:c\:.uv_udp_t> *handle, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs, const struct sockaddr *addr, uv_udp_send_cb \%<#\:c\:.uv_udp_send_cb> send_cb) ارسال داده روی سوکت UDP. اگر سوکت قبلاً با \fBuv_udp_bind()\fP متصل نشده باشد، به آدرس 0.0.0.0 (آدرس IPv4 «تمامی رابط‌ها») و یک شماره پورت تصادفی متصل خواهد شد. .sp در ویندوز اگر \fIaddr\fP برای اشاره به یک آدرس نامشخص (\fB0.0.0.0\fP یا \fB::\fP) مقداردهی شده باشد، برای تطابق با رفتار سیستم‌های لینوکس به \fBlocalhost\fP تغییر داده می‌شود. .sp برای هندل‌های متصل UDP، مقدار \fIaddr\fP باید برابر با \fINULL\fP باشد، در غیر این صورت خطای \fIUV_EISCONN\fP برگردانده خواهد شد. .sp برای هندل‌های UDP بدون اتصال، مقدار \fIaddr\fP نمی‌تواند \fINULL\fP باشد، در غیر این صورت خطای \fIUV_EDESTADDRREQ\fP برگردانده خواهد شد. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBreq\fP \-\- هندل درخواست UDP. نیازی به راه‌اندازی اولیه ندارد. .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBbufs\fP \-\- لیستی از بافرها برای ارسال. .IP \(bu 2 \fBnbufs\fP \-\- تعداد بافرها در \fIbufs\fP\&. .IP \(bu 2 \fBaddr\fP \-\- ساختار \fIstruct sockaddr_in\fP یا \fIstruct sockaddr_in6\fP حاوی آدرس و پورت مقصد دوردست. .IP \(bu 2 \fBsend_cb\fP \-\- کالبکی که پس از ارسال داده فراخوانی می‌شود. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .sp تغییریافته در نسخه 1.19.0: نگاشت \fB0.0.0.0\fP و \fB::\fP به \fBlocalhost\fP اضافه شد. .sp تغییریافته در نسخه 1.27.0: پشتیبانی از سوکت‌های متصل اضافه شد. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_try_send(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs, const struct sockaddr *addr) همانند \fBuv_udp_send()\fP عمل می‌کند، اما اگر ارسال نتواند بلافاصله تکمیل شود، درخواست ارسالی را در صف قرار نمی‌دهد. .sp برای هندل‌های متصل UDP، مقدار \fIaddr\fP باید برابر با \fINULL\fP باشد، در غیر این صورت خطای \fIUV_EISCONN\fP برمی‌گرداند. .sp برای هندل‌های UDP بدون اتصال، مقدار \fIaddr\fP نمی‌تواند \fINULL\fP باشد، در غیر این صورت خطای \fIUV_EDESTADDRREQ\fP برمی‌گرداند. .INDENT 7.0 .TP .B بازگشتی (Returns) >= 0: تعداد بایت‌های ارسال‌شده (با اندازه بافر داده‌شده مطابقت دارد). < 0: کد خطای منفی (هنگامی که پیام نتواند بلافاصله ارسال شود، \fBUV_EAGAIN\fP برگردانده می‌شود). .UNINDENT .sp تغییریافته در نسخه 1.27.0: پشتیبانی از سوکت‌های متصل اضافه شد. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_try_send2(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, unsigned int count, uv_buf_t \%<#\:c\:.uv_buf_t> *bufs[\fB/*count*/\fP], unsigned int nbufs[\fB/*count*/\fP], struct sockaddr *addrs[\fB/*count*/\fP], unsigned int flags) مشابه \fBuv_udp_try_send()\fP، اما می‌تواند چندین دیتاگرام ارسال کند. یک انتزاع سبک پیرامون sendmmsg(2) \%، همراه با یک حلقه بازگشتی به sendmsg(2) \% برای پلتفرم‌هایی که از حالت اول پشتیبانی نمی‌کنند. هندل باید به طور کامل راه‌اندازی شده باشد؛ ابتدا \fIuv_udp_bind\fP را فراخوانی کنید. .INDENT 7.0 .TP .B بازگشتی (Returns) >= 0: تعداد دیتاگرام‌های ارسال‌شده. تنها در صورتی ۰ است که \fIcount\fP برابر صفر باشد. < 0: کد خطای منفی. تنها در صورتی که ارسال اولین دیتاگرام با شکست مواجه شود، در غیر این صورت تعداد مثبت ارسال‌ها را برمی‌گرداند. مقدار \fBUV_EAGAIN\fP زمانی بازگردانده می‌شود که دیتاگرام‌ها هم‌اکنون قابل ارسال نباشند؛ در این حالت به \fBuv_udp_send()\fP\& رجوع کنید. .UNINDENT .sp افزوده شده در نسخه 1.50.0. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_recv_start(uv_udp_t \%<#\:c\:.uv_udp_t> *handle, uv_alloc_cb \%<#\:c\:.uv_alloc_cb> alloc_cb, uv_udp_recv_cb \%<#\:c\:.uv_udp_recv_cb> recv_cb) آماده‌سازی برای دریافت داده. اگر سوکت قبلاً با \fBuv_udp_bind()\fP متصل نشده باشد، به 0.0.0.0 (آدرس IPv4 «تمامی رابط‌ها») و یک پورت تصادفی متصل می‌شود. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .IP \(bu 2 \fBalloc_cb\fP \-\- کالبکی که هنگام نیاز به فضای ذخیره‌سازی موقت فراخوانی می‌شود. .IP \(bu 2 \fBrecv_cb\fP \-\- کالبکی که با داده‌های دریافتی فراخوانی می‌شود. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 هنگام استفاده از recvmmsg(2) \%، تعداد پیام‌های دریافتی در هر نوبت به حداکثر تعداد دیتاگرام‌هایی با بیشینه اندازه که در بافر تخصیص‌یافته در \fIalloc_cb\fP جای می‌گیرند محدود می‌شود، و \fIsuggested_size\fP در \fIalloc_cb\fP برای udp_recv همیشه برابر با اندازه ۱ دیتاگرام با بیشینه اندازه تنظیم می‌شود. .UNINDENT .UNINDENT .sp تغییریافته در نسخه 1.35.0: پشتیبانی از recvmmsg(2) \% در پلتفرم‌های پشتیبانی‌شده اضافه شد. استفاده از این ویژگی نیازمند ارسال بافری بزرگتر از 2 * 64KB به \fIalloc_cb\fP\& است. .sp تغییریافته در نسخه 1.37.0: پشتیبانی از recvmmsg(2) \% دیگر به صورت ضمنی فعال نیست و باید به صراحت با ارسال فلگ \fIUV_UDP_RECVMMSG\fP به \fBuv_udp_init_ex()\fP\& درخواست شود. .sp تغییریافته در نسخه 1.39.0: تابع \fBuv_udp_using_recvmmsg()\fP را می‌توان در \fIalloc_cb\fP استفاده کرد تا تعیین شود آیا باید بافری با اندازه متناسب برای استفاده با recvmmsg(2) \% برای هندل/پلتفرم جاری تخصیص یابد یا خیر. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_using_recvmmsg(uv_udp_t \%<#\:c\:.uv_udp_t> *handle) اگر هندل UDP با فلگ \fIUV_UDP_RECVMMSG\fP ایجاد شده باشد و پلتفرم از recvmmsg(2) \% پشتیبانی کند ۱، و در غیر این صورت ۰ برمی‌گرداند. .sp افزوده شده در نسخه 1.39.0. .UNINDENT .INDENT 0.0 .TP .B int uv_udp_recv_stop(uv_udp_t \%<#\:c\:.uv_udp_t> *handle) توقف شنود برای دیتاگرام‌های ورودی. .INDENT 7.0 .TP .B پارامترها (Parameters) .INDENT 7.0 .IP \(bu 2 \fBhandle\fP \-\- هندل UDP. باید با \fBuv_udp_init()\fP راه‌اندازی شده باشد. .UNINDENT .TP .B بازگشتی (Returns) ۰ در صورت موفقیت، یا کد خطای کوچکتر از ۰ در صورت شکست. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B size_t uv_udp_get_send_queue_size(const uv_udp_t \%<#\:c\:.uv_udp_t> *handle) مقدار \fIhandle\->send_queue_size\fP\& را برمی‌گرداند. .sp افزوده شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B size_t uv_udp_get_send_queue_count(const uv_udp_t \%<#\:c\:.uv_udp_t> *handle) مقدار \fIhandle\->send_queue_count\fP\& را برمی‌گرداند. .sp افزوده شده در نسخه 1.19.0. .UNINDENT .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 توابع API مربوط به \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_fs_event_t\fP \-\-\- هندل رویداد سیستم‌فایل (FS Event handle) .sp هندل‌های FS Event به کاربر اجازه می‌دهند یک مسیر مشخص را برای تغییرات زیر نظر بگیرد؛ به عنوان مثال، اگر نام فایل تغییر کند یا تغییری عمومی در آن رخ دهد. این هندل از بهترین بک‌اند موجود برای این کار در هر پلتفرم استفاده می‌کند. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 برای AIX، بسته غیرپیش‌فرض IBM bos.ahafs باید نصب شده باشد. سیستم‌فایل زیرساخت رویداد AIX (ahafs) دارای محدودیت‌هایی است: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 سیستم ahafs مانیتورینگ را به ازای هر پردازه پیگیری می‌کند و در برابر چندنخی ایمن (thread\-safe) نیست. برای هر مانیتور روی رویدادی یکسان، باید یک پردازه جداگانه اجرا شود. .IP \(bu 2 اگر تنها پوشه والد تحت نظر باشد، رویدادهای مربوط به تغییر فایل (نوشتن درون فایل) دریافت نمی‌شوند. .UNINDENT .UNINDENT .UNINDENT .sp برای جزئیات بیشتر به مستندات \% مراجعه کنید. .sp زیرساخت نظارت بر رویدادهای سیستم‌فایل z/OS در صورت ایجاد یا حذف فایل درون پوشه‌ای که تحت نظر است، اعلانی ارسال نمی‌کند. برای جزئیات بیشتر به مرکز دانش آی‌بی‌ام \% مراجعه کنید. .UNINDENT .UNINDENT .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_fs_event_t نوع هندل FS Event. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_fs_event_cb)(uv_fs_event_t \%<#\:c\:.uv_fs_event_t> *handle, const char *filename, int events, int status) کالبک پاس‌داده‌شده به \fBuv_fs_event_start()\fP که پس از شروع هندل، به صورت مکرر فراخوانی خواهد شد. .sp اگر هندل با یک پوشه راه‌اندازی شده باشد، پارامتر \fIfilename\fP یک مسیر نسبی به یک فایل درون آن پوشه خواهد بود، یا در صورتی که نام فایل قابل تشخیص نباشد، مقدار \fINULL\fP خواهد بود. .sp پارامتر \fIevents\fP یک ماسک ترکیب‌شده با عملگر OR از عناصر \fBuv_fs_event\fP است. .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در FreeBSD ممکن است به دلیل یک باگ در هسته، مسیر گاهی اوقات \fINULL\fP باشد. .INDENT 0.0 .INDENT 3.5 .UNINDENT .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_fs_event انواع رویدادهایی که هندل‌های \fBuv_fs_event_t\fP نظارت می‌کنند. .INDENT 7.0 .INDENT 3.5 .sp .EX enum uv_fs_event { UV_RENAME = 1, UV_CHANGE = 2 }; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_fs_event_flags فلگ‌هایی که می‌توانند به \fBuv_fs_event_start()\fP برای کنترل رفتار آن ارسال شوند. .INDENT 7.0 .INDENT 3.5 .sp .EX enum uv_fs_event_flags { /* * به طور پیش‌فرض، اگر به ناظر رویداد سیستم‌فایل یک نام پوشه داده شود، تمام * رویدادهای درون آن پوشه را زیر نظر می‌گیرد. این فلگ رفتار مذکور را بازنویسی * کرده و باعث می‌شود fs_event تنها تغییرات خود مدخل پوشه را گزارش کند. این * فلگ بر فایل‌های منفردِ تحت نظارت تأثیری ندارد. * این فلگ در حال حاضر هنوز روی هیچ بک‌اندی پیاده‌سازی نشده است. */ UV_FS_EVENT_WATCH_ENTRY = 1, /* * به طور پیش‌فرض uv_fs_event تلاش می‌کند از یک رابط هسته مانند inotify یا * kqueue برای تشخیص رویدادها استفاده کند. این قابلیت ممکن است در سیستم‌فایل‌های * راه دور مانند مانت‌های NFS کار نکند. این فلگ باعث می‌شود fs_event به فراخوانی * stat() در فواصل زمانی منظم بازگردد. * این فلگ در حال حاضر هنوز روی هیچ بک‌اندی پیاده‌سازی نشده است. */ UV_FS_EVENT_STAT = 2, /* * به طور پیش‌فرض، ناظر رویداد هنگام نظارت بر یک پوشه، تغییرات در زیرپوشه‌های * آن را ثبت نکرده (نادیده می‌گیرد). * این فلگ این رفتار را در پلتفرم‌های پشتیبانی‌شده بازنویسی می‌کند. */ UV_FS_EVENT_RECURSIVE = 4 }; .EE .UNINDENT .UNINDENT .UNINDENT .SS اعضای عمومی (Public members) .sp ندارد (N/A) .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B int uv_fs_event_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_event_t \%<#\:c\:.uv_fs_event_t> *handle) راه‌اندازی اولیه هندل. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_event_start(uv_fs_event_t \%<#\:c\:.uv_fs_event_t> *handle, uv_fs_event_cb \%<#\:c\:.uv_fs_event_cb> cb, const char *path, unsigned int flags) شروع هندل با کالبک داده‌شده، که \fIpath\fP مشخص‌شده را برای تغییرات زیر نظر خواهد گرفت. \fIflags\fP می‌تواند یک ماسک OR شده از \fBuv_fs_event_flags\fP\& باشد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در حال حاضر تنها فلگ پشتیبانی‌شده \fBUV_FS_EVENT_RECURSIVE\fP و تنها در macOS و ویندوز است. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در macOS، رویدادهایی که بلافاصله قبل از فراخوانی \fBuv_fs_event_start\fP توسط سیستم‌عامل جمع‌آوری شده‌اند ممکن است به کالبک \fIuv_fs_event_cb\fP گزارش شوند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_event_stop(uv_fs_event_t \%<#\:c\:.uv_fs_event_t> *handle) متوقف کردن هندل؛ پس از این کالبک دیگر فراخوانی نخواهد شد. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_event_getpath(uv_fs_event_t \%<#\:c\:.uv_fs_event_t> *handle, char *buffer, size_t *size) دریافت مسیری که توسط هندل تحت نظر قرار دارد. بافر باید توسط کاربر از پیش تخصیص یافته باشد. در صورت موفقیت ۰ یا در صورت شکست کد خطای کوچکتر از ۰ برمی‌گرداند. در صورت موفقیت، \fIbuffer\fP حاوی مسیر و \fIsize\fP حاوی طول آن خواهد بود. اگر بافر به اندازه کافی بزرگ نباشد، \fIUV_ENOBUFS\fP برگردانده شده و \fIsize\fP روی اندازه مورد نیاز شامل خاتمه‌دهنده null تنظیم خواهد شد. .sp تغییریافته در نسخه 1.3.0: طول برگردانده‌شده دیگر شامل بایت تهی (null) پایانی نیست و بافر با null خاتمه نمی‌یابد. .sp تغییریافته در نسخه 1.9.0: طول برگردانده‌شده در صورت بروز \fIUV_ENOBUFS\fP شامل بایت تهی پایانی است، و در صورت موفقیت بافر با null خاتمه می‌یابد. .UNINDENT .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 توابع API مربوط به \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS \fBuv_fs_poll_t\fP \-\-\- هندل پایش سیستم‌فایل (FS Poll handle) .sp هندل‌های FS Poll به کاربر اجازه می‌دهند یک مسیر مشخص را برای تغییرات زیر نظر بگیرد. بر خلاف \fBuv_fs_event_t\fP \%<#\:c\:.uv_fs_event_t>، هندل‌های fs poll از \fIstat\fP برای تشخیص تغییر یک فایل استفاده می‌کنند، بنابراین می‌توانند در سیستم‌فایل‌هایی که هندل‌های fs event کارایی ندارند کار کنند. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_fs_poll_t نوع هندل FS Poll. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_fs_poll_cb)(uv_fs_poll_t \%<#\:c\:.uv_fs_poll_t> *handle, int status, const uv_stat_t \%<#\:c\:.uv_stat_t> *prev, const uv_stat_t \%<#\:c\:.uv_stat_t> *curr) کالبک پاس‌داده‌شده به \fBuv_fs_poll_start()\fP که پس از شروع به کار هندل، هنگام وقوع هر تغییری در مسیر تحت نظارت، به طور مکرر فراخوانی خواهد شد. .sp اگر \fIpath\fP وجود نداشته باشد یا غیرقابل دسترس باشد، کالبک با \fIstatus < 0\fP فراخوانی می‌شود. ناظر متوقف \fIنمی‌شود\fP، اما کالبک شما تا زمانی که تغییری رخ ندهد (مثلاً هنگامی که فایل ایجاد شود یا دلیل خطا تغییر کند) مجدداً فراخوانی نخواهد شد. .sp هنگامی که \fIstatus == 0\fP باشد، کالبک اشاره‌گرهایی به ساختارهای قدیمی و جدید \fBuv_stat_t\fP \%<#\:c\:.uv_stat_t> دریافت می‌کند. این ساختارها فقط در طول مدت فراخوانی کالبک معتبر هستند. .UNINDENT .SS اعضای عمومی (Public members) .sp ندارد (N/A) .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B int uv_fs_poll_init(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_poll_t \%<#\:c\:.uv_fs_poll_t> *handle) راه‌اندازی اولیه هندل. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_poll_start(uv_fs_poll_t \%<#\:c\:.uv_fs_poll_t> *handle, uv_fs_poll_cb \%<#\:c\:.uv_fs_poll_cb> poll_cb, const char *path, unsigned int interval) بررسی فایل در مسیر \fIpath\fP برای تغییرات در هر بازه زمانی \fIinterval\fP میلی‌ثانیه. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 برای بیشترین قابلیت حمل‌پذیری، از بازه‌های چند ثانیه‌ای استفاده کنید. بازه‌های زمانی زیر یک ثانیه در بسیاری از سیستم‌فایل‌ها همه تغییرات را تشخیص نخواهند داد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_poll_stop(uv_fs_poll_t \%<#\:c\:.uv_fs_poll_t> *handle) متوقف کردن هندل؛ کالبک دیگر فراخوانی نخواهد شد. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_poll_getpath(uv_fs_poll_t \%<#\:c\:.uv_fs_poll_t> *handle, char *buffer, size_t *size) دریافت مسیری که توسط هندل تحت نظر است. بافر باید توسط کاربر از پیش تخصیص یافته باشد. در صورت موفقیت ۰ یا در صورت بروز شکست کد خطای کوچکتر از ۰ برمی‌گرداند. در صورت موفقیت، \fIbuffer\fP حاوی مسیر و \fIsize\fP حاوی طول آن خواهد بود. اگر بافر به اندازه کافی بزرگ نباشد، \fIUV_ENOBUFS\fP برگردانده شده و \fIsize\fP روی اندازه مورد نیاز تنظیم خواهد شد. .sp تغییریافته در نسخه 1.3.0: طول برگردانده‌شده دیگر شامل بایت تهی (null) پایانی نیست و بافر با null خاتمه نمی‌یابد. .sp تغییریافته در نسخه 1.9.0: طول برگردانده‌شده در صورت بروز \fIUV_ENOBUFS\fP شامل بایت تهی پایانی است، و در صورت موفقیت بافر با null خاتمه می‌یابد. .UNINDENT .sp \fBهمچنین ببینید (See also):\fP .INDENT 0.0 .INDENT 3.5 توابع API مربوط به \fBuv_handle_t\fP \%<#\:c\:.uv_handle_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "عملیات سیستم فایل (File system operations)" .sp کتابخانه libuv طیف گسترده‌ای از عملیات همگام (sync) و ناهمگام (async) سیستم فایل چندسکویی را فراهم می‌کند. تمامی توابع تعریف‌شده در این سند یک کالبک (callback) دریافت می‌کنند که می‌تواند NULL باشد. اگر کالبک NULL باشد درخواست به‌صورت همگام کامل می‌شود، در غیر این صورت به‌صورت ناهمگام انجام خواهد شد. .sp تمامی عملیات فایل روی استخر ریسه‌ها اجرا می‌شوند. برای اطلاعات در مورد اندازه استخر ریسه‌ها، بخش زمان‌بندی کار استخر ریسه \%<#\:threadpool> را ببینید. .sp از نسخه libuv v1.45.0 به بعد، برخی از عملیات فایل در لینوکس در صورت امکان به \fIio_uring \fP واگذار می‌شوند. به جز افزایش (گاهی چشمگیر) نرخ ارسال/دریافت داده (throughput)، هیچ تغییری در رفتار قابل مشاهده نباید وجود داشته باشد. در صورتی که قابلیت‌های لازم هسته در دسترس یا مناسب نباشند، Libuv به استفاده از استخر ریسه خود بازمی‌گردد. از نسخه libuv v1.49.0 این رفتار بازگردانده شد و Libuv در لینوکس به‌طور پیش‌فرض مجدداً از استخر ریسه استفاده می‌کند. برای فعال‌سازی io_uring، نمونه \fBuv_loop_t\fP \%<#\:c\:.uv_loop_t> باید با گزینه \fBUV_LOOP_USE_IO_URING_SQPOLL\fP پیکربندی شود. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در ویندوز، توابع \fIuv_fs_*\fP از کدگذاری utf\-8 استفاده می‌کنند. .UNINDENT .UNINDENT .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_fs_t نوع درخواست سیستم فایل. .UNINDENT .INDENT 0.0 .TP .B type uv_timespec_t نوع داده ناامن در برابر مسئله سال ۲۰۳۸ (Y2K38\-unsafe) برای ذخیره زمان با دقت نانوثانیه. در libuv v2.0 با \fBuv_timespec64_t\fP \%<#\:c\:.uv_timespec64_t> جایگزین خواهد شد. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct { long tv_sec; long tv_nsec; } uv_timespec_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_stat_t معادل چندسکویی و قابل حمل \fBstruct stat\fP\&. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct { uint64_t st_dev; uint64_t st_mode; uint64_t st_nlink; uint64_t st_uid; uint64_t st_gid; uint64_t st_rdev; uint64_t st_ino; uint64_t st_size; uint64_t st_blksize; uint64_t st_blocks; uint64_t st_flags; uint64_t st_gen; uv_timespec_t st_atim; uv_timespec_t st_mtim; uv_timespec_t st_ctim; uv_timespec_t st_birthtim; } uv_stat_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_fs_type نوع درخواست سیستم فایل. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_FS_UNKNOWN = \-1, UV_FS_CUSTOM, UV_FS_OPEN, UV_FS_CLOSE, UV_FS_READ, UV_FS_WRITE, UV_FS_SENDFILE, UV_FS_STAT, UV_FS_LSTAT, UV_FS_FSTAT, UV_FS_FTRUNCATE, UV_FS_UTIME, UV_FS_FUTIME, UV_FS_ACCESS, UV_FS_CHMOD, UV_FS_FCHMOD, UV_FS_FSYNC, UV_FS_FDATASYNC, UV_FS_UNLINK, UV_FS_RMDIR, UV_FS_MKDIR, UV_FS_MKDTEMP, UV_FS_RENAME, UV_FS_SCANDIR, UV_FS_LINK, UV_FS_SYMLINK, UV_FS_READLINK, UV_FS_CHOWN, UV_FS_FCHOWN, UV_FS_REALPATH, UV_FS_COPYFILE, UV_FS_LCHOWN, UV_FS_OPENDIR, UV_FS_READDIR, UV_FS_CLOSEDIR, UV_FS_MKSTEMP, UV_FS_LUTIME } uv_fs_type; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_statfs_t معادل خلاصه‌شده و چندسکویی \fBstruct statfs\fP\&. در \fBuv_fs_statfs()\fP استفاده می‌شود. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_statfs_s { uint64_t f_type; uint64_t f_bsize; uint64_t f_blocks; uint64_t f_bfree; uint64_t f_bavail; uint64_t f_files; uint64_t f_ffree; uint64_t f_frsize; uint64_t f_spare[3]; } uv_statfs_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_dirent_type_t نوع مدخل دایرکتوری (dirent). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_DIRENT_UNKNOWN, UV_DIRENT_FILE, UV_DIRENT_DIR, UV_DIRENT_LINK, UV_DIRENT_FIFO, UV_DIRENT_SOCKET, UV_DIRENT_CHAR, UV_DIRENT_BLOCK } uv_dirent_type_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_dirent_t معادل چندسکویی (خلاصه‌شده) \fBstruct dirent\fP\&. در \fBuv_fs_scandir_next()\fP استفاده می‌شود. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_dirent_s { const char* name; uv_dirent_type_t type; } uv_dirent_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_dir_t نوع داده استفاده‌شده برای پیمایش جریانی دایرکتوری. توسط \fBuv_fs_opendir()\fP، \fBuv_fs_readdir()\fP و \fBuv_fs_closedir()\fP استفاده می‌شود. \fIdirents\fP نشان‌دهنده آرایه‌ای از \fIuv_dirent_t\(gas ارائه‌شده توسط کاربر است که برای نگهداری نتایج استفاده می‌شود. \(ganentries\fP حداکثر اندازه آرایه \fIdirents\fP ارائه‌شده توسط کاربر است. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_dir_s { uv_dirent_t* dirents; size_t nentries; } uv_dir_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_fs_cb)(uv_fs_t \%<#\:c\:.uv_fs_t> *req) کالبکی که هنگام تکمیل ناهمگام یک درخواست فراخوانی می‌شود. .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B uv_loop_t \%<#\:c\:.uv_loop_t> *uv_fs_t \%<#\:c\:.uv_fs_t>\&.loop حلقه‌ای که این درخواست را آغاز کرده و تکمیل درخواست در آن گزارش خواهد شد. فقط‌خواندنی. .UNINDENT .INDENT 0.0 .TP .B uv_fs_type \%<#\:c\:.uv_fs_type> uv_fs_t \%<#\:c\:.uv_fs_t>\&.fs_type نوع درخواست FS. .UNINDENT .INDENT 0.0 .TP .B const char *uv_fs_t \%<#\:c\:.uv_fs_t>\&.path مسیری که درخواست را تحت تأثیر قرار می‌دهد. .UNINDENT .INDENT 0.0 .TP .B ssize_t uv_fs_t \%<#\:c\:.uv_fs_t>\&.result نتیجه درخواست. مقدار کوچکتر از ۰ به معنای خطا و در غیر این صورت نشان‌دهنده موفقیت است. در درخواست‌هایی مانند \fBuv_fs_read()\fP یا \fBuv_fs_write()\fP مقدار داده خوانده‌شده یا نوشته‌شده را نشان می‌دهد. .UNINDENT .INDENT 0.0 .TP .B uv_stat_t \%<#\:c\:.uv_stat_t> uv_fs_t \%<#\:c\:.uv_fs_t>\&.statbuf نتیجه \fBuv_fs_stat()\fP و سایر درخواست‌های stat را ذخیره می‌کند. .UNINDENT .INDENT 0.0 .TP .B void *uv_fs_t \%<#\:c\:.uv_fs_t>\&.ptr نتیجه \fBuv_fs_readlink()\fP و \fBuv_fs_realpath()\fP را ذخیره می‌کند و به‌عنوان نام مستعار (alias) برای \fIstatbuf\fP عمل می‌کند. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_req_t\fP \%<#\:c\:.uv_req_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B void uv_fs_req_cleanup(uv_fs_t \%<#\:c\:.uv_fs_t> *req) پاک‌سازی درخواست. باید پس از پایان درخواست برای آزادسازی هرگونه حافظه‌ای که ممکن است libuv تخصیص داده باشد فراخوانی شود. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_close(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل close(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_open(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, int flags, int mode, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل open(2) \%\&. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز libuv از \fICreateFileW\fP استفاده می‌کند و بنابراین فایل همیشه در حالت دودویی (binary) باز می‌شود. به همین دلیل فلگ‌های O_BINARY و O_TEXT پشتیبانی نمی‌شوند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_read(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل preadv(2) \%\&. اگر شناسه \fIoffset\fP برابر با \fI\-1\fP باشد، مکان آفست فعلی فایل استفاده و به‌روزرسانی می‌شود. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز، تحت محیط‌های غیر MSVC (مثلاً هنگامی که از GCC یا Clang برای ساخت libuv استفاده می‌شود)، فایل‌های بازشده با \fBUV_FS_O_FILEMAP\fP در صورت شکست عملیات خواندن با نگاشت حافظه ممکن است موجب کرش مهلک شوند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_unlink(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل unlink(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_write(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, const uv_buf_t \%<#\:c\:.uv_buf_t> bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل pwritev(2) \%\&. اگر شناسه \fIoffset\fP برابر با \fI\-1\fP باشد، مکان آفست فعلی فایل استفاده و به‌روزرسانی می‌شود. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز، تحت محیط‌های غیر MSVC (مثلاً هنگامی که از GCC یا Clang برای ساخت libuv استفاده می‌شود)، فایل‌های بازشده با \fBUV_FS_O_FILEMAP\fP در صورت شکست عملیات نوشتن با نگاشت حافظه ممکن است موجب کرش مهلک شوند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_mkdir(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, int mode, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل mkdir(2) \%\&. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در حال حاضر \fImode\fP در ویندوز پیاده‌سازی نشده است. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_mkdtemp(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *tpl, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل mkdtemp(3) \%\&. نتیجه را می‌توان به‌صورت یک رشته خاتمه‌یافته با null در \fIreq\->path\fP یافت. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_mkstemp(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *tpl, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل mkstemp(3) \%\&. مسیر فایل ایجادشده را می‌توان به‌صورت یک رشته خاتمه‌یافته با null در \fIreq\->path\fP یافت. توصیف‌کننده فایل (file descriptor) را می‌توان به‌صورت یک عدد صحیح در \fIreq\->result\fP یافت. .sp افزوده‌شده در نسخه 1.34.0. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_rmdir(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل rmdir(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_opendir(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) مسیر \fIpath\fP را به‌عنوان یک جریان دایرکتوری باز می‌کند. در صورت موفقیت، یک \fIuv_dir_t\fP تخصیص یافته و از طریق \fIreq\->ptr\fP برگردانده می‌شود. این حافظه توسط \fIuv_fs_req_cleanup()\fP آزاد نمی‌شود، هرچند \fIreq\->ptr\fP روی \fINULL\fP تنظیم می‌گردد. حافظه تخصیص‌یافته باید با فراخوانی \fIuv_fs_closedir()\fP آزاد شود. در صورت شکست، هیچ حافظه‌ای تخصیص نمی‌یابد. .sp می‌توان با ارسال \fIuv_dir_t\fP حاصل به \fIuv_fs_readdir()\fP روی محتویات دایرکتوری پیمایش کرد. .sp افزوده‌شده در نسخه 1.28.0. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_closedir(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_dir_t \%<#\:c\:.uv_dir_t> *dir, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) جریان دایرکتوری مشخص‌شده با \fIdir\fP را می‌بندد و حافظه تخصیص‌یافته توسط \fIuv_fs_opendir()\fP را آزاد می‌کند. .sp افزوده‌شده در نسخه 1.28.0. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_readdir(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_dir_t \%<#\:c\:.uv_dir_t> *dir, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) روی جریان دایرکتوری \fIdir\fP که از یک فراخوانی موفق \fIuv_fs_opendir()\fP بازگردانده شده، پیمایش می‌کند. پیش از فراخوانی \fIuv_fs_readdir()\fP، فراخواننده باید \fIdir\->dirents\fP و \fIdir\->nentries\fP را تنظیم کند که نشان‌دهنده آرایه‌ای از عناصر \fBuv_dirent_t\fP مورد استفاده برای نگهداری مدخل‌های خوانده‌شده دایرکتوری و اندازه آن است. .sp در صورت موفقیت، نتیجه یک عدد صحیح >= 0 است که تعداد مدخل‌های خوانده‌شده از جریان را نشان می‌دهد. .sp افزوده‌شده در نسخه 1.28.0. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 تابع \fIuv_fs_readdir()\fP از نظر ریسه ایمن نیست (thread safe نمی‌باشد). .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این تابع مدخل‌های \(dq.\(dq و \(dq..\(dq را برنمی‌گرداند. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در صورت موفقیت، این تابع حافظه‌ای تخصیص می‌دهد که باید با استفاده از \fIuv_fs_req_cleanup()\fP آزاد شود. \fIuv_fs_req_cleanup()\fP باید قبل از بستن دایرکتوری با \fIuv_fs_closedir()\fP فراخوانی شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_scandir(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, int flags, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_scandir_next(uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_dirent_t \%<#\:c\:.uv_dirent_t> *ent) معادل scandir(3) \%، با یک API کمی متفاوت. پس از فراخوانی کالبک برای درخواست، کاربر می‌تواند از \fBuv_fs_scandir_next()\fP برای پر کردن \fIent\fP با داده‌های مدخل بعدی دایرکتوری استفاده کند. هنگامی که مدخل دیگری وجود نداشته باشد، \fBUV_EOF\fP بازگردانده خواهد شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 برخلاف \fIscandir(3)\fP، این تابع مدخل‌های \(dq.\(dq و \(dq..\(dq را برنمی‌گرداند. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در لینوکس، دریافت نوع یک مدخل تنها توسط برخی از سیستم‌های فایل پشتیبانی می‌شود (btrfs، ext2، ext3 و ext4 در زمان نگارش این متن)؛ صفحه راهنمای getdents(2) \% را بررسی کنید. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_stat(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_fstat(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_lstat(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) به‌ترتیب معادل stat(2) \%، fstat(2) \% و lstat(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_statfs(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل statfs(2) \%\&. در صورت موفقیت، یک \fIuv_statfs_t\fP تخصیص یافته و از طریق \fIreq\->ptr\fP برگردانده می‌شود. این حافظه توسط \fIuv_fs_req_cleanup()\fP آزاد می‌شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 هر فیلدی در \fIuv_statfs_t\fP حاصل که توسط سیستم‌عامل زیربنایی پشتیبانی نشود، روی صفر تنظیم می‌گردد. .UNINDENT .UNINDENT .sp افزوده‌شده در نسخه 1.31.0. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_rename(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, const char *new_path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل rename(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_fsync(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل fsync(2) \%\&. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 برای AIX، تابع \fIuv_fs_fsync\fP روی توصیف‌کننده‌های فایلی که به فایل‌های عادی اشاره نمی‌کنند، \fIUV_EBADF\fP را برمی‌گرداند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_fdatasync(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل fdatasync(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_ftruncate(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, int64_t offset, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل ftruncate(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_copyfile(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, const char *new_path, int flags, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) فایلی را از \fIpath\fP به \fInew_path\fP کپی می‌کند. \fIflags\fP پشتیبانی‌شده در زیر شرح داده شده‌اند. .INDENT 7.0 .IP \(bu 2 \fIUV_FS_COPYFILE_EXCL\fP: در صورت وجود، اگر مسیر مقصد از قبل وجود داشته باشد، \fIuv_fs_copyfile()\fP با خطای \fIUV_EEXIST\fP شکست می‌خورد. رفتار پیش‌فرض بازنویسی روی مقصد در صورت وجود آن است. .IP \(bu 2 \fIUV_FS_COPYFILE_FICLONE\fP: در صورت وجود، \fIuv_fs_copyfile()\fP تلاش می‌کند یک پیوند مجدد کپی هنگام نوشتن (copy\-on\-write reflink) ایجاد کند. اگر پلتفرم زیربنایی از copy\-on\-write پشتیبانی نکند یا هنگام تلاش برای استفاده از آن خطایی رخ دهد، یک مکانیزم کپی جایگزین بر پایه \fBuv_fs_sendfile()\fP استفاده می‌شود. .IP \(bu 2 \fIUV_FS_COPYFILE_FICLONE_FORCE\fP: در صورت وجود، \fIuv_fs_copyfile()\fP تلاش می‌کند یک پیوند مجدد کپی هنگام نوشتن (copy\-on\-write reflink) ایجاد کند. اگر پلتفرم زیربنایی از copy\-on\-write پشتیبانی نکند یا هنگام تلاش برای استفاده از آن خطایی رخ دهد، یک خطا بازگردانده می‌شود. .UNINDENT .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 اگر مسیر مقصد ایجاد شود اما هنگام کپی کردن داده‌ها خطایی رخ دهد، مسیر مقصد حذف می‌گردد. بازه زمانی کوتاهی میان بستن و حذف فایل وجود دارد که در آن فرآیند دیگری می‌تواند به فایل دسترسی پیدا کند. .UNINDENT .UNINDENT .sp افزوده‌شده در نسخه 1.14.0. .sp تغییریافته در نسخه 1.20.0: \fIUV_FS_COPYFILE_FICLONE\fP و \fIUV_FS_COPYFILE_FICLONE_FORCE\fP پشتیبانی می‌شوند. .sp تغییریافته در نسخه 1.33.0: اگر هنگام استفاده از \fIUV_FS_COPYFILE_FICLONE_FORCE\fP خطایی رخ دهد، همان خطا بازگردانده می‌شود. پیش از این، تمام خطاها به \fIUV_ENOTSUP\fP نگاشت می‌شدند. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_sendfile(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> out_fd, uv_file \%<#\:c\:.uv_file> in_fd, int64_t in_offset, size_t length, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل محدود sendfile(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_access(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, int mode, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل access(2) \% در یونیکس. ویندوز از \fBGetFileAttributesW()\fP استفاده می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_chmod(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, int mode, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_fchmod(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, int mode, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) به‌ترتیب معادل chmod(2) \% و fchmod(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_utime(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, double atime, double mtime, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_futime(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, double atime, double mtime, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_lutime(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, double atime, double mtime, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) به‌ترتیب معادل utime(2) \%، futimes(3) \% و lutimes(3) \%\&. .sp ارسال \fIUV_FS_UTIME_NOW\fP به‌عنوان atime یا mtime، برچسب زمانی را روی زمان فعلی تنظیم می‌کند. .sp ارسال \fIUV_FS_UTIME_OMIT\fP به‌عنوان atime یا mtime، برچسب زمانی را دست‌نخورده باقی می‌گذارد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 سیستم‌عامل z/OS: تابع \fIuv_fs_lutime()\fP برای z/OS پیاده‌سازی نشده است. همچنان می‌توان آن را فراخوانی کرد اما \fBUV_ENOSYS\fP را برمی‌گرداند. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 سیستم‌عامل AIX: توابع \fIuv_fs_futime()\fP و \fIuv_fs_lutime()\fP تنها برای AIX 7.1 و جدیدتر کار می‌کنند. در نسخه‌های قدیمی‌تر همچنان می‌توان آنها را فراخوانی کرد اما \fBUV_ENOSYS\fP را برمی‌گردانند. .UNINDENT .UNINDENT .sp تغییریافته در نسخه 1.10.0: دقت زیر یک ثانیه (sub\-second precision) در ویندوز پشتیبانی می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_link(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, const char *new_path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل link(2) \%\&. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_symlink(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, const char *new_path, int flags, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل symlink(2) \%\&. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز می‌توان پارامتر \fIflags\fP را برای کنترل نحوه ایجاد پیوند نمادین (symlink) مشخص کرد: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 \fBUV_FS_SYMLINK_DIR\fP: نشان می‌دهد که \fIpath\fP به یک دایرکتوری اشاره می‌کند. .IP \(bu 2 \fBUV_FS_SYMLINK_JUNCTION\fP: درخواست می‌کند که پیوند نمادین با استفاده از نقاط اتصال (junction points) ایجاد شود. .UNINDENT .UNINDENT .UNINDENT .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_fs_readlink(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل readlink(2) \%\&. رشته حاصل در \fIreq\->ptr\fP ذخیره می‌شود. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_realpath(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) معادل realpath(3) \% در یونیکس. ویندوز از GetFinalPathNameByHandleW \% استفاده می‌کند. رشته حاصل در \fIreq\->ptr\fP ذخیره می‌شود. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع دارای هشدارهای خاص پلتفرم است که هنگام استفاده در Node کشف شدند. .INDENT 0.0 .IP \(bu 2 سیستم‌های macOS و سایر BSDها: اگر هنگام حل مسیر داده‌شده بیش از ۳۲ پیوند نمادین پیدا شود، این تابع با خطای UV_ELOOP شکست می‌خورد. این محدودیت به‌صورت سراسری و ثابت است و نمی‌توان آن را دور زد. .IP \(bu 2 ویندوز: در حالی که این تابع در حالت‌های معمول کار می‌کند، تعدادی حالت مرزی (corner case) وجود دارد که در آنها کار نمی‌کند: .INDENT 2.0 .IP \(bu 2 مسیرهای درون حجم‌های رم‌دیسک (ramdisk) ایجادشده توسط ابزارهایی که مدیر حجم (Volume Manager) را دور می‌زنند (مانند ImDisk) قابل حل نیستند. .IP \(bu 2 بزرگ و کوچک بودن ناهمخوان حروف در هنگام استفاده از حروف درایو (drive letters). .IP \(bu 2 مسیر حل‌شده درایوهای subst شده را دور می‌زند. .UNINDENT .UNINDENT .sp اگرچه همچنان می‌توان از این تابع استفاده کرد، اما در صورتی که نیاز به پشتیبانی از سناریوهایی مانند موارد بالا باشد، استفاده از آن توصیه نمی‌شود. .sp داستان پیش‌زمینه و جزئیات بیشتر در مورد این مشکلات را می‌توان در اینجا \% بررسی کرد. .UNINDENT .UNINDENT .sp افزوده‌شده در نسخه 1.8.0. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_chown(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_fchown(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, uv_file \%<#\:c\:.uv_file> file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) .UNINDENT .INDENT 0.0 .TP .B int uv_fs_lchown(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_fs_t \%<#\:c\:.uv_fs_t> *req, const char *path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb \%<#\:c\:.uv_fs_cb> cb) به‌ترتیب معادل chown(2) \%، fchown(2) \% و lchown(2) \%\&. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این توابع در ویندوز پیاده‌سازی نشده‌اند. .UNINDENT .UNINDENT .sp تغییریافته در نسخه 1.21.0: تابع uv_fs_lchown پیاده‌سازی شد. .UNINDENT .INDENT 0.0 .TP .B uv_fs_type \%<#\:c\:.uv_fs_type> uv_fs_get_type(const uv_fs_t \%<#\:c\:.uv_fs_t> *req) مقدار \fIreq\->fs_type\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B ssize_t uv_fs_get_result(const uv_fs_t \%<#\:c\:.uv_fs_t> *req) مقدار \fIreq\->result\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B int uv_fs_get_system_error(const uv_fs_t \%<#\:c\:.uv_fs_t> *req) کد خطای مخصوص پلتفرم را برمی‌گرداند \- مقدار \fIGetLastError()\fP در ویندوز و \fI\-(req\->result)\fP در سایر پلتفرم‌ها. .sp افزوده‌شده در نسخه 1.38.0. .UNINDENT .INDENT 0.0 .TP .B void *uv_fs_get_ptr(const uv_fs_t \%<#\:c\:.uv_fs_t> *req) مقدار \fIreq\->ptr\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B const char *uv_fs_get_path(const uv_fs_t \%<#\:c\:.uv_fs_t> *req) مقدار \fIreq\->path\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.19.0. .UNINDENT .INDENT 0.0 .TP .B uv_stat_t \%<#\:c\:.uv_stat_t> *uv_fs_get_statbuf(uv_fs_t \%<#\:c\:.uv_fs_t> *req) مقدار \fI&req\->statbuf\fP را برمی‌گرداند. .sp افزوده‌شده در نسخه 1.19.0. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API \fBuv_req_t\fP \%<#\:c\:.uv_req_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "توابع کمکی (Helper functions)" .INDENT 0.0 .TP .B uv_os_fd_t \%<#\:c\:.uv_os_fd_t> uv_get_osfhandle(int fd) برای یک توصیف‌کننده فایل در زمان اجرای C، هندل وابسته به سیستم‌عامل را دریافت می‌کند. در یونیکس، \fBfd\fP را دست‌نخورده برمی‌گرداند. در ویندوز، تابع _get_osfhandle \% را فراخوانی می‌کند. توجه داشته باشید که مقدار بازگردانده‌شده همچنان متعلق به زمان اجرای C است؛ هرگونه تلاش برای بستن آن یا استفاده از آن پس از بستن fd ممکن است منجر به عملکرد نادرست شود. .INDENT 7.0 .INDENT 3.5 افزوده‌شده در نسخه 1.12.0. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_open_osfhandle(uv_os_fd_t \%<#\:c\:.uv_os_fd_t> os_fd) برای یک هندل وابسته به سیستم‌عامل، توصیف‌کننده فایل را در زمان اجرای C دریافت می‌کند. در یونیکس، \fBos_fd\fP را دست‌نخورده برمی‌گرداند. در ویندوز، تابع _open_osfhandle \% را فراخوانی می‌کند. توجه داشته باشید که این تابع آرگومان را مصرف می‌کند؛ هرگونه تلاش برای بستن آن یا استفاده از آن پس از بستن مقدار بازگردانده‌شده ممکن است منجر به عملکرد نادرست شود. .INDENT 7.0 .INDENT 3.5 افزوده‌شده در نسخه 1.23.0. .UNINDENT .UNINDENT .UNINDENT .SS "ثابت‌های باز کردن فایل (File open constants)" .INDENT 0.0 .TP .B UV_FS_O_APPEND فایل در حالت الحاق (append) باز می‌شود. قبل از هر نوشتن، آفست فایل در انتهای فایل قرار می‌گیرد. .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_CREAT اگر فایل از قبل وجود نداشته باشد، ایجاد می‌شود. .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_DIRECT ورودی/خروجی (I/O) فایل به‌طور مستقیم از و به بافرهای فضای کاربر (user\-space) انجام می‌شود که باید تراز (aligned) شده باشند. اندازه و آدرس بافر باید مضربی از اندازه بخش فیزیکی دستگاه بلوکی باشد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_DIRECT\fP در لینوکس، و در ویندوز از طریق FILE_FLAG_NO_BUFFERING \% پشتیبانی می‌شود. ثابت \fIUV_FS_O_DIRECT\fP در macOS پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_DIRECTORY اگر مسیر یک دایرکتوری نباشد، باز کردن فایل شکست می‌خورد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_DIRECTORY\fP در ویندوز پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_DSYNC فایل برای I/O همگام باز می‌شود. عملیات نوشتن پس از انتقال تمام داده‌ها و حداقل فراداده‌ها (metadata) به دیسک کامل خواهد شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_DSYNC\fP در ویندوز از طریق FILE_FLAG_WRITE_THROUGH \% پشتیبانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_EXCL اگر فلگ \fIO_CREAT\fP تنظیم شده باشد و فایل از قبل وجود داشته باشد، باز کردن فایل شکست می‌خورد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 به‌طور کلی، رفتار \fIO_EXCL\fP در صورت استفاده بدون \fIO_CREAT\fP تعریف‌نشده است. یک استثنا وجود دارد: در لینوکس 2.6 و جدیدتر، در صورتی که نام مسیر به یک دستگاه بلوکی اشاره کند، \fIO_EXCL\fP می‌تواند بدون \fIO_CREAT\fP استفاده شود. اگر دستگاه بلوکی توسط سیستم در حال استفاده باشد (مثلاً سوار/mount شده باشد)، باز کردن با خطای \fIEBUSY\fP شکست خواهد خورد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_EXLOCK به‌صورت اتمیک یک قفل انحصاری (exclusive lock) دریافت می‌کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_EXLOCK\fP تنها در macOS و ویندوز پشتیبانی می‌شود. .UNINDENT .UNINDENT .sp تغییریافته در نسخه 1.17.0: پشتیبانی برای ویندوز اضافه شد. .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_FILEMAP از یک نگاشت حافظه فایل برای دسترسی به فایل استفاده می‌کند. هنگام استفاده از این فلگ، فایل نمی‌تواند چندین بار به‌طور همزمان باز شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_FILEMAP\fP تنها در ویندوز پشتیبانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_NOATIME هنگام خواندن فایل، زمان دسترسی به فایل را به‌روزرسانی نمی‌کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_NOATIME\fP در ویندوز پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_NOCTTY اگر مسیر یک دستگاه ترمینال را مشخص کند، باز کردن مسیر باعث نمی‌شود آن ترمینال به ترمینال کنترلی فرآیند تبدیل شود (در صورتی که فرآیند قبلاً ترمینال کنترلی نداشته باشد). .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_NOCTTY\fP در ویندوز پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_NOFOLLOW اگر مسیر یک پیوند نمادین باشد، باز کردن فایل شکست می‌خورد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_NOFOLLOW\fP در ویندوز پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_NONBLOCK در صورت امکان، فایل را در حالت غیرمسدودکننده (nonblocking) باز می‌کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_NONBLOCK\fP در ویندوز پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_RANDOM دسترسی به‌صورت تصادفی در نظر گرفته شده است. سیستم می‌تواند از این به‌عنوان یک راهنما (hint) برای بهینه‌سازی کش فایل استفاده کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_RANDOM\fP تنها در ویندوز از طریق FILE_FLAG_RANDOM_ACCESS \% پشتیبانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_RDONLY فایل را برای دسترسی فقط‌خواندنی باز می‌کند. .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_RDWR فایل را برای دسترسی خواندن و نوشتن باز می‌کند. .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_SEQUENTIAL دسترسی به‌صورت ترتیبی از ابتدا تا انتها در نظر گرفته شده است. سیستم می‌تواند از این به‌عنوان یک راهنما (hint) برای بهینه‌سازی کش فایل استفاده کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_SEQUENTIAL\fP تنها در ویندوز از طریق FILE_FLAG_SEQUENTIAL_SCAN \% پشتیبانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_SHORT_LIVED فایل موقت است و در صورت امکان نباید روی دیسک فلاش شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_SHORT_LIVED\fP تنها در ویندوز از طریق FILE_ATTRIBUTE_TEMPORARY \% پشتیبانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_SYMLINK به‌جای منبعی که پیوند نمادین به آن اشاره می‌کند، خود پیوند نمادین را باز می‌کند. .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_SYNC فایل برای I/O همگام باز می‌شود. عملیات نوشتن پس از انتقال تمام داده‌ها و تمام فراداده‌ها (metadata) به دیسک کامل خواهد شد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_SYNC\fP در ویندوز از طریق FILE_FLAG_WRITE_THROUGH \% پشتیبانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_TEMPORARY فایل موقت است و در صورت امکان نباید روی دیسک فلاش شود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 ثابت \fIUV_FS_O_TEMPORARY\fP تنها در ویندوز از طریق FILE_ATTRIBUTE_TEMPORARY \% پشتیبانی می‌شود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_TRUNC اگر فایل وجود داشته باشد و یک فایل عادی باشد، و فایل با موفقیت برای دسترسی نوشتن باز شود، طول آن به صفر کاهش می‌یابد (truncate می‌شود). .UNINDENT .INDENT 0.0 .TP .B UV_FS_O_WRONLY فایل را برای دسترسی فقط‌نوشتنی باز می‌کند. .UNINDENT .SS "زمان‌بندی کار استخر ریسه (Thread pool work scheduling)" .sp کتابخانه libuv یک استخر ریسه (threadpool) فراهم می‌کند که می‌تواند برای اجرای کد کاربر و مطلع شدن در ریسه حلقه (loop thread) استفاده شود. این استخر ریسه در داخل برای اجرای تمامی عملیات سیستم فایل، و همچنین درخواست‌های getaddrinfo و getnameinfo استفاده می‌شود. .sp اندازه پیش‌فرض آن ۴ است، اما می‌توان آن را در زمان راه‌اندازی با تنظیم متغیر محیطی \fBUV_THREADPOOL_SIZE\fP به هر مقداری تغییر داد (حداکثر مطلق ۱۰۲۴ است). .sp تغییریافته در نسخه 1.30.0: حداکثر UV_THREADPOOL_SIZE مجاز از ۱۲۸ به ۱۰۲۴ افزایش یافت. .sp تغییریافته در نسخه 1.45.0: ریسه‌ها اکنون به جای پیش‌فرض پلتفرم (که گاهی بسیار کم است)، دارای ۸ مگابایت پشته (stack) هستند. .sp تغییریافته در نسخه 1.50.0: ریسه‌ها اکنون نام پیش‌فرض libuv\-worker دارند. .sp استخر ریسه سراسری است و بین تمامی حلقه‌های رویداد به اشتراک گذاشته می‌شود. هنگامی که یک تابع خاص از استخر ریسه استفاده می‌کند (مثلاً هنگام استفاده از \fBuv_queue_work()\fP)، کتابخانه libuv حداکثر تعداد ریسه‌های مجاز توسط \fBUV_THREADPOOL_SIZE\fP را پیش‌تخصیص داده و مقداردهی اولیه می‌کند. ریسه‌های بیشتر معمولاً به معنای بازده کاری (throughput) بیشتر اما ردپای حافظه (memory footprint) بالاتر است. البته در بیشتر پلتفرم‌ها پشته‌های ریسه به‌صورت تنبل (lazily) رشد می‌کنند. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 توجه داشته باشید که اگرچه از یک استخر ریسه سراسری مشترک بین تمامی حلقه‌های رویداد استفاده می‌شود، توابع از نظر ریسه ایمن نیستند (thread safe نمی‌باشند). .UNINDENT .UNINDENT .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_work_t نوع درخواست کار (work request). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_work_cb)(uv_work_t \%<#\:c\:.uv_work_t> *req) کالبک ارسال‌شده به \fBuv_queue_work()\fP که روی استخر ریسه اجرا خواهد شد. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_after_work_cb)(uv_work_t \%<#\:c\:.uv_work_t> *req, int status) کالبک ارسال‌شده به \fBuv_queue_work()\fP که پس از اتمام کار روی استخر ریسه، روی ریسه حلقه فراخوانی خواهد شد. اگر کار با استفاده از \fBuv_cancel()\fP \%<#\:c\:.uv_cancel> لغو شده باشد، \fIstatus\fP برابر با \fBUV_ECANCELED\fP خواهد بود. .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B uv_loop_t \%<#\:c\:.uv_loop_t> *uv_work_t \%<#\:c\:.uv_work_t>\&.loop حلقه‌ای که این درخواست را آغاز کرده و تکمیل درخواست در آن گزارش خواهد شد. فقط‌خواندنی. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_req_t\fP \%<#\:c\:.uv_req_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_queue_work(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_work_t \%<#\:c\:.uv_work_t> *req, uv_work_cb \%<#\:c\:.uv_work_cb> work_cb, uv_after_work_cb \%<#\:c\:.uv_after_work_cb> after_work_cb) یک درخواست کار را مقداردهی اولیه می‌کند که \fIwork_cb\fP داده‌شده را در یک ریسه از استخر ریسه اجرا خواهد کرد. پس از تکمیل \fIwork_cb\fP، تابع \fIafter_work_cb\fP روی ریسه حلقه فراخوانی خواهد شد. .sp این درخواست را می‌توان با \fBuv_cancel()\fP \%<#\:c\:.uv_cancel> لغو کرد. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API \fBuv_req_t\fP \%<#\:c\:.uv_req_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "توابع کاربردی DNS (DNS utility functions)" .sp کتابخانه libuv گونه‌های ناهمگام \fIgetaddrinfo\fP و \fIgetnameinfo\fP را فراهم می‌کند. .SS "انواع داده (Data types)" .INDENT 0.0 .TP .B type uv_getaddrinfo_t نوع درخواست \fIgetaddrinfo\fP. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t \%<#\:c\:.uv_getaddrinfo_t> *req, int status, struct addrinfo *res) کالبکی که پس از تکمیل، با نتیجه درخواست getaddrinfo فراخوانی خواهد شد. در صورتی که لغو شده باشد، \fIstatus\fP مقداری برابر با \fBUV_ECANCELED\fP خواهد داشت. .UNINDENT .INDENT 0.0 .TP .B type uv_getnameinfo_t نوع درخواست \fIgetnameinfo\fP. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t \%<#\:c\:.uv_getnameinfo_t> *req, int status, const char *hostname, const char *service) کالبکی که پس از تکمیل، با نتیجه درخواست getnameinfo فراخوانی خواهد شد. در صورتی که لغو شده باشد، \fIstatus\fP مقداری برابر با \fBUV_ECANCELED\fP خواهد داشت. .UNINDENT .SS "اعضای عمومی (Public members)" .INDENT 0.0 .TP .B uv_loop_t \%<#\:c\:.uv_loop_t> *uv_getaddrinfo_t \%<#\:c\:.uv_getaddrinfo_t>\&.loop حلقه‌ای که این درخواست getaddrinfo را آغاز کرده و تکمیل درخواست در آن گزارش خواهد شد. فقط‌خواندنی. .UNINDENT .INDENT 0.0 .TP .B struct addrinfo \%<#\:c\:.uv_getaddrinfo_t\:.addrinfo> *uv_getaddrinfo_t \%<#\:c\:.uv_getaddrinfo_t>\&.addrinfo اشاره‌گر به یک \fIstruct addrinfo\fP حاوی نتیجه. باید توسط کاربر با \fBuv_freeaddrinfo()\fP آزاد شود. .sp تغییریافته در نسخه 1.3.0: این فیلد به‌صورت عمومی (public) اعلان شده است. .UNINDENT .INDENT 0.0 .TP .B uv_loop_t \%<#\:c\:.uv_loop_t> *uv_getnameinfo_t \%<#\:c\:.uv_getnameinfo_t>\&.loop حلقه‌ای که این درخواست getnameinfo را آغاز کرده و تکمیل درخواست در آن گزارش خواهد شد. فقط‌خواندنی. .UNINDENT .INDENT 0.0 .TP .B char[NI_MAXHOST] uv_getnameinfo_t.host آرایه کاراکتری حاوی میزبان حاصل. با null خاتمه یافته است. .sp تغییریافته در نسخه 1.3.0: این فیلد به‌صورت عمومی (public) اعلان شده است. .UNINDENT .INDENT 0.0 .TP .B char[NI_MAXSERV] uv_getnameinfo_t.service آرایه کاراکتری حاوی سرویس حاصل. با null خاتمه یافته است. .sp تغییریافته در نسخه 1.3.0: این فیلد به‌صورت عمومی (public) اعلان شده است. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 اعضای \fBuv_req_t\fP \%<#\:c\:.uv_req_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS "رابط برنامه‌نویسی (API)" .INDENT 0.0 .TP .B int uv_getaddrinfo(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_getaddrinfo_t \%<#\:c\:.uv_getaddrinfo_t> *req, uv_getaddrinfo_cb \%<#\:c\:.uv_getaddrinfo_cb> getaddrinfo_cb, const char *node, const char *service, const struct addrinfo *hints) معادل ناهمگام getaddrinfo(3) \%\&. .sp هر یک از node یا service می‌توانند NULL باشند اما نه هر دو به‌طور همزمان. .sp شناسه \fIhints\fP اشاره‌گری به یک struct addrinfo با محدودیت‌های نوع آدرس اضافی، یا NULL است. برای جزئیات بیشتر به \fIman \-s 3 getaddrinfo\fP مراجعه کنید. .sp در صورت موفقیت ۰ یا در صورت شکست یک کد خطای کوچکتر از ۰ برمی‌گرداند. در صورت موفقیت، کالبک در زمانی در آینده با نتیجه جستجو فراخوانی می‌شود که یکی از موارد زیر است: .INDENT 7.0 .IP \(bu 2 status == 0، شناسه res به یک \fIstruct addrinfo\fP معتبر اشاره می‌کند، یا .IP \(bu 2 status < 0، شناسه res برابر با NULL است. ثابت‌های UV_EAI_* را ببینید. .UNINDENT .sp برای آزادسازی ساختار addrinfo، تابع \fBuv_freeaddrinfo()\fP را فراخوانی کنید. .sp تغییریافته در نسخه 1.3.0: پارامتر کالبک اکنون مجاز است NULL باشد، که در این حالت درخواست به‌صورت \fBهمگام\fP اجرا خواهد شد. .UNINDENT .INDENT 0.0 .TP .B void uv_freeaddrinfo(struct addrinfo *ai) ساختار struct addrinfo را آزاد می‌کند. ارسال NULL مجاز است و عملیاتی انجام نمی‌دهد (no\-op). .UNINDENT .INDENT 0.0 .TP .B int uv_getnameinfo(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_getnameinfo_t \%<#\:c\:.uv_getnameinfo_t> *req, uv_getnameinfo_cb \%<#\:c\:.uv_getnameinfo_cb> getnameinfo_cb, const struct sockaddr *addr, int flags) معادل ناهمگام getnameinfo(3) \%\&. .sp در صورت موفقیت ۰ یا در صورت شکست یک کد خطای کوچکتر از ۰ برمی‌گرداند. در صورت موفقیت، کالبک در زمانی در آینده با نتیجه جستجو فراخوانی خواهد شد. برای جزئیات بیشتر به \fIman \-s 3 getnameinfo\fP مراجعه کنید. .sp تغییریافته در نسخه 1.3.0: پارامتر کالبک اکنون مجاز است NULL باشد، که در این حالت درخواست به‌صورت \fBهمگام\fP اجرا خواهد شد. .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 توابع API \fBuv_req_t\fP \%<#\:c\:.uv_req_t> نیز اعمال می‌شوند. .UNINDENT .UNINDENT .SS مدیریت کتابخانه‌های اشتراکی (Shared library handling) .sp کتابخانه libuv ابزارهایی مستقل از بستر برای بارگذاری کتابخانه‌های اشتراکی و استخراج نمادها از آن‌ها با استفاده از رابط برنامه‌نویسی زیر فراهم می‌کند. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_lib_t نوع داده کتابخانه اشتراکی. .UNINDENT .SS اعضای عمومی (Public members) .sp موردی وجود ندارد (N/A) .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B int uv_dlopen(const char *filename, uv_lib_t \%<#\:c\:.uv_lib_t> *lib) یک کتابخانه اشتراکی را باز می‌کند. نام فایل در قالب utf\-8 است. در صورت موفقیت مقدار 0 و در صورت خطا مقدار \-1 را برمی‌گرداند. برای دریافت پیام خطا تابع \fBuv_dlerror()\fP را فراخوانی کنید. .UNINDENT .INDENT 0.0 .TP .B void uv_dlclose(uv_lib_t \%<#\:c\:.uv_lib_t> *lib) کتابخانه اشتراکی را می‌بندد. .UNINDENT .INDENT 0.0 .TP .B int uv_dlsym(uv_lib_t \%<#\:c\:.uv_lib_t> *lib, const char *name, void **ptr) اشاره‌گر داده را از یک کتابخانه پویا بازیابی می‌کند. نگاشت یک نماد به NULL مجاز و معتبر است. در صورت موفقیت 0 و در صورتی که نماد یافت نشود \-1 برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B const char *uv_dlerror(const uv_lib_t \%<#\:c\:.uv_lib_t> *lib) آخرین پیام خطای uv_dlopen() یا uv_dlsym() را برمی‌گرداند. .UNINDENT .SS ابزارهای ریسه‌بندی و همگام‌سازی (Threading and synchronization utilities) .sp کتابخانه libuv پیاده‌سازی‌های چندسکویی برای چندین ساختار بنیادین ریسه‌بندی و همگام‌سازی ارائه می‌دهد. این رابط برنامه‌نویسی عمدتاً از API پتردز (pthreads) پیروی می‌کند. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_thread_t نوع داده ریسه (Thread). .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_thread_cb)(void *arg) تابع بازخوانی (Callback) که برای مقداردهی اولیه اجرای ریسه فراخوانی می‌شود. \fIarg\fP همان مقداری است که به \fBuv_thread_create()\fP ارسال شده بود. .UNINDENT .INDENT 0.0 .TP .B type uv_key_t نوع داده کلید محلی ریسه (Thread-local key). .UNINDENT .INDENT 0.0 .TP .B type uv_once_t نوع داده مقداردهی اولیه‌ساز تک‌باره (Once-only initializer). .UNINDENT .INDENT 0.0 .TP .B type uv_mutex_t نوع داده قفل انحصار متقابل (Mutex). .UNINDENT .INDENT 0.0 .TP .B type uv_rwlock_t نوع داده قفل خواندن\-نوشتن (Read-write lock). .UNINDENT .INDENT 0.0 .TP .B type uv_sem_t نوع داده سمافور (Semaphore). .UNINDENT .INDENT 0.0 .TP .B type uv_cond_t نوع داده شرط (Condition). .UNINDENT .INDENT 0.0 .TP .B type uv_barrier_t نوع داده مانع (Barrier). .UNINDENT .SS رابط برنامه‌نویسی (API) .SS ریسه‌ها (Threads) .INDENT 0.0 .TP .B type uv_thread_options_t گزینه‌های ایجاد ریسه جدید (ارسال‌شده به \fBuv_thread_create_ex()\fP). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_thread_options_s { enum { UV_THREAD_NO_FLAGS = 0x00, UV_THREAD_HAS_STACK_SIZE = 0x01 } flags; size_t stack_size; } uv_thread_options_t; .EE .UNINDENT .UNINDENT .sp ممکن است فیلدهای بیشتری در هر زمان به این ساختار اضافه شود، بنابراین نباید به چینش و اندازه دقیق آن اتکا کرد. .sp افزوده شده در نسخه 1.26.0. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_create(uv_thread_t \%<#\:c\:.uv_thread_t> *tid, uv_thread_cb \%<#\:c\:.uv_thread_cb> entry, void *arg) تغییر یافته در نسخه 1.4.1: در صورت شکست، کد خطای UV_E* را برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_detach(uv_thread_t \%<#\:c\:.uv_thread_t> *tid) ریسه را جدا (Detach) می‌کند. ریسه‌های جداشده پس از خاتمه به طور خودکار منابع خود را آزاد می‌کنند و نیاز برنامه به فراخوانی \fIuv_thread_join\fP را از بین می‌برند. .sp افزوده شده در نسخه 1.50.0. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_create_ex(uv_thread_t \%<#\:c\:.uv_thread_t> *tid, const uv_thread_options_t \%<#\:c\:.uv_thread_options_t> *params, uv_thread_cb \%<#\:c\:.uv_thread_cb> entry, void *arg) مشابه \fBuv_thread_create()\fP، اما علاوه بر آن گزینه‌هایی را برای ایجاد یک ریسه جدید مشخص می‌کند. .sp اگر \fIUV_THREAD_HAS_STACK_SIZE\fP تنظیم شده باشد، \fIstack_size\fP اندازه پشته را برای ریسه جدید مشخص می‌کند. مقدار \fI0\fP نشان می‌دهد که باید از مقدار پیش‌فرض استفاده شود (رفتاری مشابه زمانی که پرچم تنظیم نشده باشد). سایر مقادیر به نزدیک‌ترین مرز صفحه حافظه گرد می‌شوند. .sp افزوده شده در نسخه 1.26.0. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_setaffinity(uv_thread_t \%<#\:c\:.uv_thread_t> *tid, char *cpumask, char *oldmask, size_t mask_size) وابستگی پردازنده (Affinity) ریسه مشخص‌شده را به cpumask که بر حسب بایت مشخص شده است تنظیم می‌کند. در صورت تمایل، تنظیمات قبلی وابستگی را در oldmask برمی‌گرداند. در یونیکس، از pthread_getaffinity_np(3) \% برای دریافت تنظیمات وابستگی استفاده کرده و cpu_set_t را به بایت‌ها در oldmask نگاشت می‌کند. سپس بایت‌های cpumask را به یک cpu_set_t نگاشت کرده و از pthread_setaffinity_np(3) \% استفاده می‌کند. در ویندوز، بایت‌های cpumask را به یک ماسک بیتی نگاشت کرده و از SetThreadAffinityMask() استفاده می‌کند که تنظیمات وابستگی پیشین را برمی‌گرداند. .sp پارامتر mask_size تعداد درایه‌ها (بایت‌ها) را در cpumask / oldmask مشخص می‌کند، و باید بزرگ‌تر یا مساوی با \fBuv_cpumask_size()\fP \%<#\:c\:.uv_cpumask_size> باشد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 تنظیم وابستگی ریسه در ویندوز به صورت اتمیک نیست. در macOS پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_getaffinity(uv_thread_t \%<#\:c\:.uv_thread_t> *tid, char *cpumask, size_t mask_size) تنظیمات وابستگی پردازنده ریسه مشخص‌شده را دریافت می‌کند. در یونیکس، این تابع cpu_set_t بازگردانده شده توسط pthread_getaffinity_np(3) \% را به بایت‌ها در cpumask نگاشت می‌کند. .sp پارامتر mask_size تعداد درایه‌ها (بایت‌ها) را در cpumask مشخص می‌کند، و باید بزرگ‌تر یا مساوی با \fBuv_cpumask_size()\fP \%<#\:c\:.uv_cpumask_size> باشد. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 دریافت وابستگی ریسه در ویندوز به صورت اتمیک نیست. در macOS پشتیبانی نمی‌شود. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_getcpu(void) شماره پردازنده‌ای (CPU) را که ریسه فراخوان روی آن در حال اجراست دریافت می‌کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در حال حاضر فقط روی Windows، Linux و FreeBSD پیاده‌سازی شده است. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B uv_thread_t \%<#\:c\:.uv_thread_t> uv_thread_self(void) .UNINDENT .INDENT 0.0 .TP .B int uv_thread_join(uv_thread_t \%<#\:c\:.uv_thread_t> *tid) .UNINDENT .INDENT 0.0 .TP .B int uv_thread_equal(const uv_thread_t \%<#\:c\:.uv_thread_t> *t1, const uv_thread_t \%<#\:c\:.uv_thread_t> *t2) .UNINDENT .INDENT 0.0 .TP .B int uv_thread_setname(const char *name) نام ریسه جاری را تنظیم می‌کند. بسترهای مختلف محدودیت‌های متفاوتی روی حداکثر تعداد کاراکترهای نام ریسه تعریف می‌کنند: لینوکس و IBM i (۱۶ کاراکتر)، macOS (۶۴ کاراکتر)، ویندوز (۳۲۷۶۷ کاراکتر)، و NetBSD (۳۲ کاراکتر) و غیره. در صورتی که \fIname\fP بزرگ‌تر از محدودیت بستر باشد، \fIuv_thread_setname()\fP آن را کوتاه (truncate) می‌کند. .sp در Windows Server 2016 پشتیبانی نمی‌شود و \fIUV_ENOSYS\fP را برمی‌گرداند. .sp افزوده شده در نسخه 1.50.0. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_getname(uv_thread_t \%<#\:c\:.uv_thread_t> *tid, char *name, size_t *size) نام ریسه مشخص‌شده با \fItid\fP را دریافت می‌کند. نام ریسه به همراه بایت NUL انتهایی در بافر اشاره‌شده با \fIname\fP کپی می‌شود. پارامتر \fIsize\fP اندازه بافر اشاره‌شده با \fIname\fP را مشخص می‌کند. بافر باید به اندازه کافی بزرگ باشد تا نام ریسه به اضافه NUL انتهایی را در خود جای دهد، در غیر این صورت برای جا گرفتن همراه با NUL انتهایی کوتاه خواهد شد. .sp در Windows Server 2016 پشتیبانی نمی‌شود و \fIUV_ENOSYS\fP را برمی‌گرداند. .sp افزوده شده در نسخه 1.50.0. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_setpriority(uv_thread_t \%<#\:c\:.uv_thread_t> tid, int priority) اگر تابع با موفقیت اجرا شود، مقدار بازگشتی 0 است. در صورت شکست تابع، مقدار بازگشتی کمتر از صفر است. اولویت زمان‌بندی ریسه مشخص‌شده با tid را تنظیم می‌کند. در برخی بسترها تنظیم اولویت‌های خاص نیازمند دسترسی‌های ارشد (Elevated) است. اولویت را می‌توان روی ثابت‌های زیر تنظیم کرد: UV_THREAD_PRIORITY_HIGHEST، UV_THREAD_PRIORITY_ABOVE_NORMAL، UV_THREAD_PRIORITY_NORMAL، UV_THREAD_PRIORITY_BELOW_NORMAL، UV_THREAD_PRIORITY_LOWEST. .UNINDENT .INDENT 0.0 .TP .B int uv_thread_getpriority(uv_thread_t \%<#\:c\:.uv_thread_t> tid, int *priority) اگر تابع با موفقیت اجرا شود، مقدار بازگشتی 0 است. در صورت شکست تابع، مقدار بازگشتی کمتر از صفر است. اولویت زمان‌بندی ریسه مشخص‌شده با tid را بازیابی می‌کند. مقدار موجود در پارامتر خروجی priority وابسته به بستر است. در لینوکس، زمانی که سیاست زمان‌بندی SCHED_OTHER (پیش‌فرض) باشد، اولویت 0 است. .UNINDENT .SS حافظه محلی ریسه (Thread-local storage) .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 کل اندازه حافظه محلی ریسه ممکن است محدود باشد. به این معنی که ممکن است ایجاد کلیدهای TLS متعدد امکان‌پذیر نباشد. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_key_create(uv_key_t \%<#\:c\:.uv_key_t> *key) .UNINDENT .INDENT 0.0 .TP .B void uv_key_delete(uv_key_t \%<#\:c\:.uv_key_t> *key) .UNINDENT .INDENT 0.0 .TP .B void *uv_key_get(uv_key_t \%<#\:c\:.uv_key_t> *key) .UNINDENT .INDENT 0.0 .TP .B void uv_key_set(uv_key_t \%<#\:c\:.uv_key_t> *key, void *value) .UNINDENT .SS مقداردهی اولیه یک‌باره (Once-only initialization) .sp یک تابع را یک‌بار و فقط یک‌بار اجرا می‌کند. فراخوانی‌های همزمان \fBuv_once()\fP با یک گارد یکسان، تمام فراخوان‌ها به جز یکی را مسدود می‌کند (مشخص نیست کدام یک). گارد باید به صورت ایستا با ماکروی UV_ONCE_INIT مقداردهی اولیه شود. .INDENT 0.0 .TP .B void uv_once(uv_once_t \%<#\:c\:.uv_once_t> *guard, void (*callback)(void)) .UNINDENT .SS قفل‌های انحصار متقابل (Mutex locks) .sp توابع در صورت موفقیت مقدار 0 یا کد خطای کوچک‌تر از 0 را برمی‌گردانند (البته مگر اینکه نوع بازگشتی void باشد). .INDENT 0.0 .TP .B int uv_mutex_init(uv_mutex_t \%<#\:c\:.uv_mutex_t> *handle) .UNINDENT .INDENT 0.0 .TP .B int uv_mutex_init_recursive(uv_mutex_t \%<#\:c\:.uv_mutex_t> *handle) .UNINDENT .INDENT 0.0 .TP .B void uv_mutex_destroy(uv_mutex_t \%<#\:c\:.uv_mutex_t> *handle) .UNINDENT .INDENT 0.0 .TP .B void uv_mutex_lock(uv_mutex_t \%<#\:c\:.uv_mutex_t> *handle) .UNINDENT .INDENT 0.0 .TP .B int uv_mutex_trylock(uv_mutex_t \%<#\:c\:.uv_mutex_t> *handle) .UNINDENT .INDENT 0.0 .TP .B void uv_mutex_unlock(uv_mutex_t \%<#\:c\:.uv_mutex_t> *handle) .UNINDENT .SS قفل‌های خواندن-نوشتن (Read-write locks) .sp توابع در صورت موفقیت مقدار 0 یا کد خطای کوچک‌تر از 0 را برمی‌گردانند (البته مگر اینکه نوع بازگشتی void باشد). .INDENT 0.0 .TP .B int uv_rwlock_init(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .INDENT 0.0 .TP .B void uv_rwlock_destroy(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .INDENT 0.0 .TP .B void uv_rwlock_rdlock(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .INDENT 0.0 .TP .B int uv_rwlock_tryrdlock(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .INDENT 0.0 .TP .B void uv_rwlock_rdunlock(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .INDENT 0.0 .TP .B void uv_rwlock_wrlock(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .INDENT 0.0 .TP .B int uv_rwlock_trywrlock(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .INDENT 0.0 .TP .B void uv_rwlock_wrunlock(uv_rwlock_t \%<#\:c\:.uv_rwlock_t> *rwlock) .UNINDENT .SS سمافورها (Semaphores) .sp توابع در صورت موفقیت مقدار 0 یا کد خطای کوچک‌تر از 0 را برمی‌گردانند (البته مگر اینکه نوع بازگشتی void باشد). .INDENT 0.0 .TP .B int uv_sem_init(uv_sem_t \%<#\:c\:.uv_sem_t> *sem, unsigned int value) .UNINDENT .INDENT 0.0 .TP .B void uv_sem_destroy(uv_sem_t \%<#\:c\:.uv_sem_t> *sem) .UNINDENT .INDENT 0.0 .TP .B void uv_sem_post(uv_sem_t \%<#\:c\:.uv_sem_t> *sem) .UNINDENT .INDENT 0.0 .TP .B void uv_sem_wait(uv_sem_t \%<#\:c\:.uv_sem_t> *sem) .UNINDENT .INDENT 0.0 .TP .B int uv_sem_trywait(uv_sem_t \%<#\:c\:.uv_sem_t> *sem) .UNINDENT .SS شرایط (Conditions) .sp توابع در صورت موفقیت مقدار 0 یا کد خطای کوچک‌تر از 0 را برمی‌گردانند (البته مگر اینکه نوع بازگشتی void باشد). .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP 1. 3 فراخوان‌ها باید برای مدیریت بیدارباش‌های کاذب (Spurious wakeups) در \fBuv_cond_wait()\fP و \fBuv_cond_timedwait()\fP آماده باشند. .IP 2. 3 پارامتر timeout در \fBuv_cond_timedwait()\fP نسبت به زمانی است که تابع فراخوانی می‌شود. .IP 3. 3 در z/OS، پارامتر timeout برای \fBuv_cond_timedwait()\fP به یک زمان مطلق سیستم تبدیل می‌شود که در آن انقضای انتظار رخ می‌دهد. اگر ساعت فعلی سیستم از زمان مطلق محاسبه‌شده پیش از سیگنال‌دهی شرط بگذرد، خطای ETIMEDOUT رخ می‌دهد. پس از شروع انتظار، زمان انتظار تحت تأثیر تغییرات ساعت سیستم قرار نمی‌گیرد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_cond_init(uv_cond_t \%<#\:c\:.uv_cond_t> *cond) .UNINDENT .INDENT 0.0 .TP .B void uv_cond_destroy(uv_cond_t \%<#\:c\:.uv_cond_t> *cond) .UNINDENT .INDENT 0.0 .TP .B void uv_cond_signal(uv_cond_t \%<#\:c\:.uv_cond_t> *cond) .UNINDENT .INDENT 0.0 .TP .B void uv_cond_broadcast(uv_cond_t \%<#\:c\:.uv_cond_t> *cond) .UNINDENT .INDENT 0.0 .TP .B void uv_cond_wait(uv_cond_t \%<#\:c\:.uv_cond_t> *cond, uv_mutex_t \%<#\:c\:.uv_mutex_t> *mutex) .UNINDENT .INDENT 0.0 .TP .B int uv_cond_timedwait(uv_cond_t \%<#\:c\:.uv_cond_t> *cond, uv_mutex_t \%<#\:c\:.uv_mutex_t> *mutex, uint64_t timeout) .UNINDENT .SS مانع‌ها (Barriers) .sp توابع در صورت موفقیت مقدار 0 یا کد خطای کوچک‌تر از 0 را برمی‌گردانند (البته مگر اینکه نوع بازگشتی void باشد). .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 تابع \fBuv_barrier_wait()\fP مقداری بزرگ‌تر از صفر را به یک ریسه به‌دلخواه انتخاب‌شده به عنوان «سریال‌ساز» (Serializer) بازمی‌گرداند تا پاک‌سازی را تسهیل کند، یعنی: .INDENT 0.0 .INDENT 3.5 .sp .EX if (uv_barrier_wait(&barrier) > 0) uv_barrier_destroy(&barrier); .EE .UNINDENT .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_barrier_init(uv_barrier_t \%<#\:c\:.uv_barrier_t> *barrier, unsigned int count) .UNINDENT .INDENT 0.0 .TP .B void uv_barrier_destroy(uv_barrier_t \%<#\:c\:.uv_barrier_t> *barrier) .UNINDENT .INDENT 0.0 .TP .B int uv_barrier_wait(uv_barrier_t \%<#\:c\:.uv_barrier_t> *barrier) .UNINDENT .SS ابزارهای متفرقه (Miscellaneous utilities) .sp این بخش شامل توابع متفرقه‌ای است که به بخش‌های دیگر تعلق ندارند. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_buf_t نوع داده بافر (Buffer). .INDENT 7.0 .TP .B char *uv_buf_t\&.base اشاره‌گر به پایه بافر. .UNINDENT .INDENT 7.0 .TP .B size_t uv_buf_t\&.len مجموع بایت‌ها در بافر. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز این فیلد از نوع ULONG است. .UNINDENT .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B typedef void *(*uv_malloc_func)(size_t size) تابع جایگزین برای malloc(3) \%\&. به \fBuv_replace_allocator()\fP مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B typedef void *(*uv_realloc_func)(void *ptr, size_t size) تابع جایگزین برای realloc(3) \%\&. به \fBuv_replace_allocator()\fP مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B typedef void *(*uv_calloc_func)(size_t count, size_t size) تابع جایگزین برای calloc(3) \%\&. به \fBuv_replace_allocator()\fP مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_free_func)(void *ptr) تابع جایگزین برای free(3) \%\&. به \fBuv_replace_allocator()\fP مراجعه کنید. .UNINDENT .INDENT 0.0 .TP .B typedef void (*uv_random_cb)(uv_random_t \%<#\:c\:.uv_random_t> *req, int status, void *buf, size_t buflen) تابع بازخوانی ارسال‌شده به \fBuv_random()\fP\&. پارامتر \fIstatus\fP در صورت بروز خطا غیرصفر است. اشاره‌گر \fIbuf\fP همان اشاره‌گری است که به \fBuv_random()\fP ارسال شده بود. .UNINDENT .INDENT 0.0 .TP .B type uv_file نمایش چندسکویی از دستگیره فایل (File handle). .UNINDENT .INDENT 0.0 .TP .B type uv_os_sock_t نمایش چندسکویی از دستگیره سوکت (Socket handle). .UNINDENT .INDENT 0.0 .TP .B type uv_os_fd_t نمایش انتزاعی از توصیف‌کننده فایل (File descriptor). در سیستم‌های یونیکس این مورد یک \fItypedef\fP از نوع \fIint\fP و در ویندوز یک \fIHANDLE\fP است. .UNINDENT .INDENT 0.0 .TP .B type uv_pid_t نمایش چندسکویی از نوع \fIpid_t\fP\&. .sp افزوده شده در نسخه 1.16.0. .UNINDENT .INDENT 0.0 .TP .B type uv_timeval_t نوع داده ناامن در برابر مسئله سال ۲۰۳۸ (Y2K38\-unsafe) برای ذخیره زمان با دقت میکروثانیه. در نسخه libuv v2.0 با \fBuv_timeval64_t\fP جایگزین خواهد شد. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct { long tv_sec; long tv_usec; } uv_timeval_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_timeval64_t نوع داده امن در برابر مسئله سال ۲۰۳۸ (Y2K38\-safe) برای ذخیره زمان با دقت میکروثانیه. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct { int64_t tv_sec; int32_t tv_usec; } uv_timeval64_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_timespec64_t نوع داده امن در برابر مسئله سال ۲۰۳۸ (Y2K38\-safe) برای ذخیره زمان با دقت نانوثانیه. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct { int64_t tv_sec; int32_t tv_nsec; } uv_timespec64_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B enum uv_clock_id منبع ساعت برای \fBuv_clock_gettime()\fP\&. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef enum { UV_CLOCK_MONOTONIC, UV_CLOCK_REALTIME } uv_clock_id; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_rusage_t نوع داده برای نتایج مصرف منابع (Resource usage). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct { uv_timeval_t ru_utime; /* user CPU time used */ uv_timeval_t ru_stime; /* system CPU time used */ uint64_t ru_maxrss; /* maximum resident set size */ uint64_t ru_ixrss; /* integral shared memory size (X) */ uint64_t ru_idrss; /* integral unshared data size (X) */ uint64_t ru_isrss; /* integral unshared stack size (X) */ uint64_t ru_minflt; /* page reclaims (soft page faults) (X) */ uint64_t ru_majflt; /* page faults (hard page faults) */ uint64_t ru_nswap; /* swaps (X) */ uint64_t ru_inblock; /* block input operations */ uint64_t ru_oublock; /* block output operations */ uint64_t ru_msgsnd; /* IPC messages sent (X) */ uint64_t ru_msgrcv; /* IPC messages received (X) */ uint64_t ru_nsignals; /* signals received (X) */ uint64_t ru_nvcsw; /* voluntary context switches (X) */ uint64_t ru_nivcsw; /* involuntary context switches (X) */ } uv_rusage_t; .EE .UNINDENT .UNINDENT .sp اعضای علامت‌گذاری شده با \fI(X)\fP در ویندوز پشتیبانی نمی‌شوند. برای فیلدهای پشتیبانی‌شده در بسترهای شبه‌یونیکس به getrusage(2) \% مراجعه کنید. .sp حداکثر اندازه مقیم در حافظه (RSS) بر حسب کیلوبایت گزارش می‌شود که واحد بومی اکثر پلتفرم‌ها است. .UNINDENT .INDENT 0.0 .TP .B type uv_cpu_info_t نوع داده برای اطلاعات پردازنده (CPU). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_cpu_info_s { char* model; int speed; struct uv_cpu_times_s { uint64_t user; /* milliseconds */ uint64_t nice; /* milliseconds */ uint64_t sys; /* milliseconds */ uint64_t idle; /* milliseconds */ uint64_t irq; /* milliseconds */ } cpu_times; } uv_cpu_info_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_interface_address_t نوع داده برای آدرس‌های رابط شبکه. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_interface_address_s { char* name; char phys_addr[6]; int is_internal; union { struct sockaddr_in address4; struct sockaddr_in6 address6; } address; union { struct sockaddr_in netmask4; struct sockaddr_in6 netmask6; } netmask; } uv_interface_address_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_passwd_t نوع داده برای اطلاعات فایل گذرواژه (Passwd). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_passwd_s { char* username; long uid; long gid; char* shell; char* homedir; } uv_passwd_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_group_t نوع داده برای اطلاعات فایل گروه (Group). .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_group_s { char* groupname; unsigned long gid; char** members; } uv_group_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_utsname_t نوع داده برای نام و نسخه سیستم‌عامل. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_utsname_s { char sysname[256]; char release[256]; char version[256]; char machine[256]; } uv_utsname_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_env_item_t نوع داده برای ذخیره متغیرهای محیطی. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct uv_env_item_s { char* name; char* value; } uv_env_item_t; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B type uv_random_t نوع درخواست داده‌های تصادفی. .UNINDENT .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B uv_handle_type \%<#\:c\:.uv_handle_type> uv_guess_handle(uv_file \%<#\:c\:.uv_file> file) برای تشخیص اینکه چه نوع جریانی باید با توصیف‌کننده فایل داده‌شده استفاده شود به کار می‌رود. معمولاً در هنگام مقداردهی اولیه برای حدس زدن نوع جریان‌های stdio استفاده می‌شود. .sp برای قابلیتی معادل isatty(3) \% از این تابع استفاده کرده و برای \fIUV_TTY\fP بررسی کنید. .UNINDENT .INDENT 0.0 .TP .B int uv_replace_allocator(uv_malloc_func \%<#\:c\:.uv_malloc_func> malloc_func, uv_realloc_func \%<#\:c\:.uv_realloc_func> realloc_func, uv_calloc_func \%<#\:c\:.uv_calloc_func> calloc_func, uv_free_func \%<#\:c\:.uv_free_func> free_func) افزوده شده در نسخه 1.6.0. .sp جایگزین کردن توابع تخصیص حافظه کتابخانه استاندارد malloc(3) \%، calloc(3) \%، realloc(3) \%، free(3) \%\&. .sp این تابع باید قبل از فراخوانی هر تابع دیگر libuv یا پس از آزاد شدن تمام منابع و در نتیجه زمانی که libuv به هیچ بخش حافظه تخصیص‌یافته‌ای ارجاع ندارد، فراخوانی شود. .sp در صورت موفقیت مقدار 0 و اگر هر یک از اشاره‌گرهای تابع \fINULL\fP باشد مقدار \fIUV_EINVAL\fP را برمی‌گرداند. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 هیچ محافظتی در برابر تغییر چندباره تخصیص‌دهنده حافظه وجود ندارد. در صورت تغییر، کاربر مسئول اطمینان از این است که تغییر زمانی صورت گیرد که هیچ حافظه‌ای با تخصیص‌دهنده قبلی تخصیص نیافته باشد یا اینکه این دو تخصیص‌دهنده با هم سازگار باشند. .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 تخصیص‌دهنده باید ایمن در برابر ریسه (Thread-safe) باشد. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B void uv_library_shutdown(void); افزوده شده در نسخه 1.38.0. .sp آزاد کردن هرگونه وضعیت سراسری که libuv در دست دارد. کتابخانه libuv معمولاً هنگام تخلیه از حافظه به طور خودکار این کار را انجام می‌دهد، اما می‌توان به آن دستور داد تا پاک‌سازی را به صورت دستی انجام دهد. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 تابع \fBuv_library_shutdown()\fP را فقط یک بار فراخوانی کنید. .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 زمانی که هنوز حلقه‌های رویداد یا درخواست‌های I/O فعال هستند، \fBuv_library_shutdown()\fP را فراخوانی نکنید. .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 پس از فراخوانی \fBuv_library_shutdown()\fP، توابع libuv را فراخوانی نکنید. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B uv_buf_t \%<#\:c\:.uv_buf_t> uv_buf_init(char *base, unsigned int len) سازنده برای ساختار \fBuv_buf_t\fP\&. .sp به دلیل تفاوت‌های بسترها، کاربر نمی‌تواند به ترتیب اعضای \fIbase\fP و \fIlen\fP در ساختار uv_buf_t اتکا کند. مسئولیت آزادسازی \fIbase\fP پس از اتمام کار با uv_buf_t بر عهده کاربر است. ساختار بازگشتی با مقدار (by value) ارسال می‌شود. .UNINDENT .INDENT 0.0 .TP .B char **uv_setup_args(int argc, char **argv) ذخیره آرگومان‌های برنامه. برای دریافت / تنظیم عنوان فرایند یا مسیر فایل اجرایی مورد نیاز است. ممکن است libuv مالکیت حافظه‌ای را که \fIargv\fP به آن اشاره می‌کند در دست بگیرد. این تابع باید دقیقاً یک‌بار و در زمان شروع برنامه فراخوانی شود. .sp مثال: .INDENT 7.0 .INDENT 3.5 .sp .EX argv = uv_setup_args(argc, argv); /* May return a copy of argv. */ .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_get_process_title(char *buffer, size_t size) عنوان فرایند جاری را دریافت می‌کند. در سیستم‌های Unix و AIX \fIباید\fP قبل از فراخوانی این تابع، \fIuv_setup_args\fP را فراخوانی کنید. اگر در سیستم‌هایی که به آن نیاز دارند \fIuv_setup_args\fP فراخوانی نشده باشد، \fIUV_ENOBUFS\fP برگردانده می‌شود. اگر \fIbuffer\fP برابر با \fINULL\fP یا \fIsize\fP صفر باشد، \fIUV_EINVAL\fP برگردانده می‌شود. اگر \fIsize\fP گنجایش عنوان فرایند و کاراکتر \fInul\fP پایانی را نداشته باشد، تابع \fIUV_ENOBUFS\fP را برمی‌گرداند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در سیستم‌های BSD، فراخوانی \fIuv_setup_args\fP برای دریافت عنوان اولیه فرایند لازم است. عنوان فرایند بازگردانده شده تا زمانی که \fIuv_setup_args\fP یا \fIuv_set_process_title\fP فراخوانی نشود، یک رشته خالی خواهد بود. .UNINDENT .UNINDENT .sp تغییر یافته در نسخه 1.18.1: اکنون در تمام پلتفرم‌های پشتیبانی‌شده ایمن در برابر ریسه (Thread-safe) است. .sp تغییر یافته در نسخه 1.39.0: اکنون اگر \fIuv_setup_args\fP مورد نیاز باشد اما فراخوانی نشده باشد، یک خطا برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B int uv_set_process_title(const char *title) عنوان فرایند جاری را تنظیم می‌کند. در سیستم‌های Unix و AIX \fIباید\fP قبل از فراخوانی این تابع، \fIuv_setup_args\fP را فراخوانی کنید. اگر در سیستم‌هایی که به آن نیاز دارند \fIuv_setup_args\fP فراخوانی نشده باشد، \fIUV_ENOBUFS\fP برگردانده می‌شود. در بسترهایی با بافر با اندازه ثابت برای عنوان فرایند، محتویات \fItitle\fP در بافر کپی شده و در صورت بزرگ‌تر بودن از فضای موجود کوتاه (truncate) می‌شود. سایر بسترها در صورت عدم امکان تخصیص فضای کافی برای تکثیر محتوای \fItitle\fP، مقدار \fIUV_ENOMEM\fP را برمی‌گردانند. .sp تغییر یافته در نسخه 1.18.1: اکنون در تمام پلتفرم‌های پشتیبانی‌شده ایمن در برابر ریسه (Thread-safe) است. .sp تغییر یافته در نسخه 1.39.0: اکنون اگر \fIuv_setup_args\fP مورد نیاز باشد اما فراخوانی نشده باشد، یک خطا برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B int uv_resident_set_memory(size_t *rss) اندازه مقیم در حافظه (RSS) را برای فرایند جاری دریافت می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_uptime(double *uptime) زمان بالا بودن (Uptime) سیستم را دریافت می‌کند. بسته به سیستم، ثانیه‌ها به صورت کامل یا کسری برگردانده می‌شوند. .UNINDENT .INDENT 0.0 .TP .B int uv_getrusage(uv_rusage_t \%<#\:c\:.uv_rusage_t> *rusage) معیارهای مصرف منابع را برای فرایند جاری دریافت می‌کند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز همه فیلدها مقداردهی نمی‌شوند و فیلدهای پشتیبانی‌نشده با صفر پر می‌شوند. برای جزئیات بیشتر به \fBuv_rusage_t\fP مراجعه کنید. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_getrusage_thread(uv_rusage_t \%<#\:c\:.uv_rusage_t> *rusage) معیارهای مصرف منابع را برای ریسه فراخوان دریافت می‌کند. .sp افزوده شده در نسخه 1.50.0. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در همه بسترها پشتیبانی نمی‌شود و ممکن است \fIUV_ENOTSUP\fP را برگرداند. در macOS و Windows همه فیلدها مقداردهی نمی‌شوند و فیلدهای پشتیبانی‌نشده با صفر پر می‌شوند. برای جزئیات بیشتر به \fBuv_rusage_t\fP مراجعه کنید. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B uv_pid_t \%<#\:c\:.uv_pid_t> uv_os_getpid(void) شناسه فرایند جاری (Process ID) را برمی‌گرداند. .sp افزوده شده در نسخه 1.18.0. .UNINDENT .INDENT 0.0 .TP .B uv_pid_t \%<#\:c\:.uv_pid_t> uv_os_getppid(void) شناسه فرایند والد (Parent Process ID) را برمی‌گرداند. .sp افزوده شده در نسخه 1.16.0. .UNINDENT .INDENT 0.0 .TP .B unsigned int uv_available_parallelism(void) تخمین مقدار موازی‌سازی پیش‌فرضی که یک برنامه باید استفاده کند را بازمی‌گرداند. همواره مقداری غیرصفر برمی‌گرداند. .sp در لینوکس، ماسک وابستگی CPU ریسه فراخوان را بررسی می‌کند تا مشخص شود آیا به CPUهای خاصی متصل (pin) شده است یا خیر. .sp در ویندوز، در سیستم‌هایی با بیش از ۶۴ پردازنده منطقی، موازی‌سازی در دسترس ممکن است کمتر از واقعیت گزارش شود. .sp در سایر بسترها، تعداد پردازنده‌هایی را که سیستم‌عامل فعال (Online) در نظر می‌گیرد گزارش می‌کند. .sp افزوده شده در نسخه 1.44.0. .UNINDENT .INDENT 0.0 .TP .B int uv_cpu_info(uv_cpu_info_t \%<#\:c\:.uv_cpu_info_t> **cpu_infos, int *count) اطلاعات مربوط به پردازنده‌های موجود در سیستم را دریافت می‌کند. آرایه \fIcpu_infos\fP شامل \fIcount\fP عنصر خواهد بود و باید با \fBuv_free_cpu_info()\fP آزاد شود. .sp اگر نیاز دارید بدانید چند پردازنده برای ریسه‌ها یا فرایندهای فرزند در دسترس است، از \fBuv_available_parallelism()\fP استفاده کنید. .UNINDENT .INDENT 0.0 .TP .B void uv_free_cpu_info(uv_cpu_info_t \%<#\:c\:.uv_cpu_info_t> *cpu_infos, int count) آرایه \fIcpu_infos\fP را که قبلاً با \fBuv_cpu_info()\fP تخصیص یافته بود آزاد می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_cpumask_size(void) حداکثر اندازه ماسک استفاده‌شده برای وابستگی فرایند/ریسه را برمی‌گرداند، یا اگر وابستگی در بستر جاری پشتیبانی نشود، \fIUV_ENOTSUP\fP را برمی‌گرداند. .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B int uv_interface_addresses(uv_interface_address_t \%<#\:c\:.uv_interface_address_t> **addresses, int *count) اطلاعات آدرس مربوط به رابط‌های شبکه موجود در سیستم را دریافت می‌کند. آرایه‌ای از \fIcount\fP عنصر تخصیص یافته و در \fIaddresses\fP بازگردانده می‌شود. این آرایه باید توسط کاربر و با فراخوانی \fBuv_free_interface_addresses()\fP آزاد شود. .UNINDENT .INDENT 0.0 .TP .B void uv_free_interface_addresses(uv_interface_address_t \%<#\:c\:.uv_interface_address_t> *addresses, int count) آرایه‌ای از ساختارهای \fBuv_interface_address_t\fP را که توسط \fBuv_interface_addresses()\fP بازگردانده شده بود آزاد می‌کند. .UNINDENT .INDENT 0.0 .TP .B void uv_loadavg(double avg[3]) میانگین بار سیستم (Load average) را دریافت می‌کند. ببینید: \% .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز [0,0,0] برمی‌گرداند (یعنی پیاده‌سازی نشده است). .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_ip4_addr(const char *ip, int port, struct sockaddr_in *addr) یک رشته حاوی آدرس IPv4 را به یک ساختار باینری تبدیل می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_ip6_addr(const char *ip, int port, struct sockaddr_in6 *addr) یک رشته حاوی آدرس IPv6 را به یک ساختار باینری تبدیل می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_ip4_name(const struct sockaddr_in *src, char *dst, size_t size) یک ساختار باینری حاوی آدرس IPv4 را به یک رشته تبدیل می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_ip6_name(const struct sockaddr_in6 *src, char *dst, size_t size) یک ساختار باینری حاوی آدرس IPv6 را به یک رشته تبدیل می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) یک ساختار باینری حاوی آدرس IPv4 یا IPv6 را به یک رشته تبدیل می‌کند. .UNINDENT .INDENT 0.0 .TP .B int uv_inet_ntop(int af, const void *src, char *dst, size_t size) .UNINDENT .INDENT 0.0 .TP .B int uv_inet_pton(int af, const char *src, void *dst) پیاده‌سازی چندسکویی و سازگار با IPv6 از inet_ntop(3) \% و inet_pton(3) \%\&. در صورت موفقیت 0 را برمی‌گردانند. در صورت بروز خطا، اشاره‌گر مقصد \fIdst\fP دست‌نخورده باقی می‌ماند. .UNINDENT .INDENT 0.0 .TP .B UV_IF_NAMESIZE حداکثر طول نام شناسه رابط IPv6. در یونیکس به صورت \fIIFNAMSIZ\fP و در لینوکس و ویندوز به صورت \fIIF_NAMESIZE\fP تعریف شده است. .sp افزوده شده در نسخه 1.16.0. .UNINDENT .INDENT 0.0 .TP .B int uv_if_indextoname(unsigned int ifindex, char *buffer, size_t *size) پیاده‌سازی سازگار با IPv6 از if_indextoname(3) \%\&. هنگام فراخوانی، \fI*size\fP طول \fIbuffer\fP را نشان می‌دهد که برای ذخیره نتیجه استفاده می‌شود. در صورت موفقیت، صفر برگردانده می‌شود، \fIbuffer\fP حاوی نام رابط خواهد بود و \fI*size\fP طول رشته \fIbuffer\fP را بدون احتساب بایت پایان‌بخش NUL نشان می‌دهد. در صورت خطا، یک نتیجه منفی برگردانده می‌شود. اگر \fIbuffer\fP برای نگهداری نتیجه به اندازه کافی بزرگ نباشد، \fIUV_ENOBUFS\fP برگردانده شده و \fI*size\fP اندازه مورد نیاز بر حسب بایت را شامل بایت پایان‌بخش NUL نشان می‌دهد. .sp در یونیکس، نام رابط بازگردانده شده می‌تواند مستقیماً به عنوان شناسه رابط در آدرس‌های دامنه‌دار IPv6 استفاده شود، مانند \fIfe80::abc:def1:2345%en0\fP\&. .sp در ویندوز، رابط بازگردانده شده را نمی‌توان به عنوان شناسه رابط استفاده کرد، زیرا ویندوز از شناسه‌های عددی رابط استفاده می‌کند، مانند \fIfe80::abc:def1:2345%5\fP\&. .sp برای دریافت شناسه رابط به شیوه‌ای سازگار با بسترهای مختلف، از \fIuv_if_indextoiid()\fP استفاده کنید. .sp مثال: .INDENT 7.0 .INDENT 3.5 .sp .EX char ifname[UV_IF_NAMESIZE]; size_t size = sizeof(ifname); uv_if_indextoname(sin6\->sin6_scope_id, ifname, &size); .EE .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.16.0. .UNINDENT .INDENT 0.0 .TP .B int uv_if_indextoiid(unsigned int ifindex, char *buffer, size_t *size) یک شناسه رابط شبکه مناسب برای استفاده در آدرس‌های دامنه‌دار IPv6 را بازیابی می‌کند. در ویندوز، مقدار عددی \fIifindex\fP را به صورت رشته برمی‌گرداند. در سایر بسترها، \fIuv_if_indextoname()\fP فراخوانی می‌شود. نتیجه در \fIbuffer\fP نوشته شده و \fI*size\fP طول \fIbuffer\fP را نشان می‌دهد. اگر \fIbuffer\fP به اندازه کافی بزرگ نباشد، مقدار \fIUV_ENOBUFS\fP برگردانده شده و \fI*size\fP اندازه مورد نیاز شامل بایت NUL برای نگهداری نتیجه را نشان می‌دهد. .sp برای جزئیات بیشتر به \fIuv_if_indextoname\fP مراجعه کنید. .sp افزوده شده در نسخه 1.16.0. .UNINDENT .INDENT 0.0 .TP .B int uv_exepath(char *buffer, size_t *size) مسیر فایل اجرایی را دریافت می‌کند. قبل از فراخوانی این تابع \fIباید\fP \fIuv_setup_args\fP را فراخوانی کنید. .sp در فایل‌های اجرایی setuid احتیاط کنید. در برخی پلتفرم‌ها مسیر فایل اجرایی یک رشته دلخواه است که توسط کاربر کنترل می‌شود. در سایر پلتفرم‌ها متغیرهای محیطی بررسی می‌شوند که ممکن است تحت کنترل کاربر باشند. .UNINDENT .INDENT 0.0 .TP .B int uv_cwd(char *buffer, size_t *size) دایرکتوری کاری فعلی را دریافت کرده و آن را در \fIbuffer\fP ذخیره می‌کند. اگر دایرکتوری کاری فعلی برای جا شدن در \fIbuffer\fP بیش از حد بزرگ باشد، این تابع مقدار \fIUV_ENOBUFS\fP را برمی‌گرداند و \fIsize\fP را روی طول مورد نیاز شامل نویسه پایان‌بخش null تنظیم می‌کند. .sp تغییر یافته در نسخه 1.1.0: در یونیکس مسیر دیگر به اسلش ختم نمی‌شود. .sp تغییر یافته در نسخه 1.9.0: در صورت خطای \fIUV_ENOBUFS\fP طول بازگردانده شده شامل بایت پایان‌بخش null است، و در صورت موفقیت، بافر با null پایان می‌یابد. .UNINDENT .INDENT 0.0 .TP .B int uv_chdir(const char *dir) دایرکتوری کاری جاری را تغییر می‌دهد. .UNINDENT .INDENT 0.0 .TP .B int uv_os_homedir(char *buffer, size_t *size) پوشه خانگی کاربر جاری را دریافت می‌کند. در ویندوز، \fIuv_os_homedir()\fP ابتدا متغیر محیطی \fIUSERPROFILE\fP را با استفاده از \fIGetEnvironmentVariableW()\fP بررسی می‌کند. اگر \fIUSERPROFILE\fP تنظیم نشده باشد، \fIGetUserProfileDirectoryW()\fP فراخوانی می‌شود. در سایر سیستم‌عامل‌ها، \fIuv_os_homedir()\fP ابتدا متغیر محیطی \fIHOME\fP را با getenv(3) \% بررسی می‌کند. اگر \fIHOME\fP تنظیم نشده باشد، getpwuid_r(3) \% فراخوانی می‌شود. دایرکتوری خانگی کاربر در \fIbuffer\fP ذخیره می‌شود. هنگام فراخوانی \fIuv_os_homedir()\fP، پارامتر \fIsize\fP حداکثر اندازه \fIbuffer\fP را نشان می‌دهد. در صورت موفقیت، \fIsize\fP روی طول رشته \fIbuffer\fP تنظیم می‌شود. در صورت شکست \fIUV_ENOBUFS\fP، پارامتر \fIsize\fP روی طول مورد نیاز برای \fIbuffer\fP شامل بایت null تنظیم می‌گردد. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 تابع \fIuv_os_homedir()\fP ایمن در برابر ریسه (Thread-safe) نیست. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.6.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_tmpdir(char *buffer, size_t *size) دایرکتوری موقت را دریافت می‌کند. در ویندوز، \fIuv_os_tmpdir()\fP از \fIGetTempPathW()\fP استفاده می‌کند. در سایر سیستم‌عامل‌ها، \fIuv_os_tmpdir()\fP از اولین متغیر محیطی یافت‌شده در فهرست مرتب‌شده \fITMPDIR\fP، \fITMP\fP، \fITEMP\fP و \fITEMPDIR\fP استفاده می‌کند. اگر هیچ‌یک از این‌ها یافت نشود، مسیر \fI\(dq/tmp\(dq\fP یا در اندروید مسیر \fI\(dq/data/local/tmp\(dq\fP استفاده می‌شود. دایرکتوری موقت در \fIbuffer\fP ذخیره می‌شود. هنگام فراخوانی \fIuv_os_tmpdir()\fP، مقدار \fIsize\fP حداکثر اندازه \fIbuffer\fP را نشان می‌دهد. در صورت موفقیت، \fIsize\fP روی طول رشته \fIbuffer\fP (که شامل null پایان‌بخش نیست) تنظیم می‌شود. در صورت شکست \fIUV_ENOBUFS\fP، مقدار \fIsize\fP روی طول مورد نیاز برای \fIbuffer\fP شامل بایت null تنظیم می‌گردد. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 تابع \fIuv_os_tmpdir()\fP ایمن در برابر ریسه (Thread-safe) نیست. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.9.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_get_passwd(uv_passwd_t \%<#\:c\:.uv_passwd_t> *pwd) زیرمجموعه‌ای از درایه فایل گذرواژه را برای uid مؤثر فعلی (نه uid واقعی) دریافت می‌کند. داده‌های پرشده شامل نام کاربری، euid، gid، شل و دایرکتوری خانگی است. در سیستم‌های غیرویندوزی، تمام داده‌ها از getpwuid_r(3) \% به دست می‌آید. در ویندوز، uid و gid روی \-1 تنظیم شده و معنایی ندارند و shell برابر با \fINULL\fP است. پس از فراخوانی موفق این تابع، حافظه تخصیص‌یافته به \fIpwd\fP باید با \fBuv_os_free_passwd()\fP آزاد شود. .sp افزوده شده در نسخه 1.9.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_get_passwd2(uv_passwd_t \%<#\:c\:.uv_passwd_t> *pwd, uv_uid_t uid) زیرمجموعه‌ای از درایه فایل گذرواژه را برای uid ارائه‌شده دریافت می‌کند. داده‌های پرشده شامل نام کاربری، euid، gid، شل و دایرکتوری خانگی است. در سیستم‌های غیرویندوزی، تمام داده‌ها از getpwuid_r(3) \% به دست می‌آید. در ویندوز، uid و gid روی \-1 تنظیم شده و معنایی ندارند و shell برابر با \fINULL\fP است. پس از فراخوانی موفق این تابع، حافظه تخصیص‌یافته به \fIpwd\fP باید با \fBuv_os_free_passwd()\fP آزاد شود. .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_get_group(uv_group_t \%<#\:c\:.uv_group_t> *group, uv_uid_t gid) زیرمجموعه‌ای از درایه فایل گروه را برای uid ارائه‌شده دریافت می‌کند. داده‌های پرشده شامل نام گروه، gid و اعضا است. در سیستم‌های غیرویندوزی، تمام داده‌ها از getgrgid_r(3) \% به دست می‌آید. در ویندوز، uid و gid روی \-1 تنظیم شده و معنایی ندارند. پس از فراخوانی موفق این تابع، حافظه تخصیص‌یافته به \fIgroup\fP باید با \fBuv_os_free_group()\fP آزاد شود. .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B void uv_os_free_group(uv_passwd_t \%<#\:c\:.uv_passwd_t> *pwd) حافظه‌ای را که قبلاً با \fBuv_os_get_group()\fP تخصیص یافته بود آزاد می‌کند. .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B void uv_os_free_passwd(uv_passwd_t \%<#\:c\:.uv_passwd_t> *pwd) حافظه \fIpwd\fP را که قبلاً با \fBuv_os_get_passwd()\fP تخصیص یافته بود آزاد می‌کند. .sp افزوده شده در نسخه 1.9.0. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_get_free_memory(void) میزان حافظه آزاد موجود در سیستم را طبق گزارش هسته (بر حسب بایت) دریافت می‌کند. در صورت نامشخص بودن 0 برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_get_total_memory(void) میزان کل حافظه فیزیکی سیستم را (بر حسب بایت) دریافت می‌کند. در صورت نامشخص بودن 0 برمی‌گرداند. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_get_constrained_memory(void) میزان کل حافظه در دسترس فرایند را (بر حسب بایت) بر اساس محدودیت‌های اعمال‌شده توسط سیستم‌عامل دریافت می‌کند. اگر چنین محدودیتی وجود نداشته باشد، یا محدودیت ناشناخته باشد، \fI0\fP برگردانده می‌شود. اگر سازوکار محدودکننده وجود داشته باشد اما محدودیتی تعیین نشده باشد، \fIUINT64_MAX\fP برگردانده می‌شود. توجه داشته باشید که کمتر یا بیشتر بودن این مقدار از \fBuv_get_total_memory()\fP غیرعادی نیست. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این تابع در حال حاضر فقط روی لینوکس (بر اساس cgroups در صورت وجود) و در z/OS (بر اساس RLIMIT_MEMLIMIT) مقداری غیرصفر برمی‌گرداند. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.29.0. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_get_available_memory(void) میزان حافظه آزادی را که هنوز در دسترس فرایند است (بر حسب بایت) دریافت می‌کند. تفاوت این تابع با \fBuv_get_free_memory()\fP در این است که محدودیت‌های اعمال‌شده توسط سیستم‌عامل را در نظر می‌گیرد. اگر چنین محدودیتی وجود نداشته باشد یا محدودیت ناشناخته باشد، مقدار بازگردانده شده با \fBuv_get_free_memory()\fP یکسان خواهد بود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 این تابع در حال حاضر تنها در لینوکس مقداری متفاوت از گزارش \fBuv_get_free_memory()\fP برمی‌گرداند (بر اساس cgroups در صورت وجود). .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_hrtime(void) برچسب زمانی با دقت بالا (High-resolution timestamp) را برمی‌گرداند. این مقدار بر حسب نانوثانیه بیان می‌شود. نسبت به یک زمان اختیاری در گذشته سنجیده می‌شود و ارتباطی با ساعت شبانه‌روز ندارد و بنابراین در معرض انحراف ساعت (Clock drift) نیست. کاربرد اصلی آن برای اندازه‌گیری کارایی بین بازه‌ها است. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 همه بسترها از دقت نانوثانیه پشتیبانی نمی‌کنند؛ با این حال، این مقدار همیشه بر حسب نانوثانیه خواهد بود. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B int uv_clock_gettime(uv_clock_id \%<#\:c\:.uv_clock_id> clock_id, uv_timespec64_t \%<#\:c\:.uv_timespec64_t> *ts) زمان فعلی سیستم را از یک منبع ساعت بیدرنگ (Real-time) یا یکنواخت (Monotonic) با دقت بالا به دست می‌آورد. .sp ساعت بیدرنگ از مبدأ یونیکس (1970\-01\-01) شمارش می‌کند و مشمول تنظیمات زمانی است؛ ممکن است در زمان به عقب بپرد. .sp ساعت یکنواخت از یک نقطه دلخواه در گذشته شمارش می‌کند و هرگز در زمان به عقب نمی‌پرد. .sp افزوده شده در نسخه 1.45.0. .UNINDENT .INDENT 0.0 .TP .B void uv_print_all_handles(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, FILE *stream) تمام دستگیره‌های مرتبط با \fIloop\fP داده‌شده را در \fIstream\fP مشخص‌شده چاپ می‌کند. .sp مثال: .INDENT 7.0 .INDENT 3.5 .sp .EX uv_print_all_handles(uv_default_loop(), stderr); /* [\-\-I] signal 0x1a25ea8 [\-AI] async 0x1a25cf0 [R\-\-] idle 0x1a7a8c8 */ .EE .UNINDENT .UNINDENT .sp قالب به صورت \fI[flags] handle\-type handle\-address\fP است. برای \fIflags\fP: .INDENT 7.0 .IP \(bu 2 \fIR\fP برای دستگیره‌ای که به آن ارجاع شده است چاپ می‌شود .IP \(bu 2 \fIA\fP برای دستگیره فعال چاپ می‌شود .IP \(bu 2 \fII\fP برای دستگیره داخلی چاپ می‌شود .UNINDENT .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع برای اشکال‌زدایی موردی (Ad hoc) در نظر گرفته شده است و هیچ تضمینی برای پایداری API/ABI وجود ندارد. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.8.0. .UNINDENT .INDENT 0.0 .TP .B void uv_print_active_handles(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, FILE *stream) این تابع مشابه \fBuv_print_all_handles()\fP است با این تفاوت که فقط دستگیره‌های فعال چاپ می‌شوند. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع برای اشکال‌زدایی موردی (Ad hoc) در نظر گرفته شده است و هیچ تضمینی برای پایداری API/ABI وجود ندارد. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.8.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_environ(uv_env_item_t \%<#\:c\:.uv_env_item_t> **envitems, int *count) تمام متغیرهای محیطی را بازیابی می‌کند. این تابع حافظه‌ای تخصیص می‌دهد که باید با فراخوانی \fBuv_os_free_environ()\fP آزاد شود. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع ایمن در برابر ریسه (Thread-safe) نیست. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.31.0. .UNINDENT .INDENT 0.0 .TP .B void uv_os_free_environ(uv_env_item_t \%<#\:c\:.uv_env_item_t> *envitems, int count); حافظه تخصیص‌یافته برای متغیرهای محیطی توسط \fBuv_os_environ()\fP را آزاد می‌کند. .sp افزوده شده در نسخه 1.31.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_getenv(const char *name, char *buffer, size_t *size) متغیر محیطی مشخص‌شده توسط \fIname\fP را بازیابی کرده، مقدار آن را در \fIbuffer\fP کپی می‌کند و \fIsize\fP را روی طول رشته مقدار تنظیم می‌کند. هنگام فراخوانی این تابع، \fIsize\fP باید روی مقدار حافظه در دسترس در \fIbuffer\fP شامل نویسه پایان‌بخش null تنظیم شده باشد. اگر متغیر محیطی از فضای موجود در \fIbuffer\fP فراتر رود، \fIUV_ENOBUFS\fP برگردانده می‌شود و \fIsize\fP روی مقدار فضای مورد نیاز برای نگهداری مقدار تنظیم می‌گردد. اگر متغیر محیطی منطبقی وجود نداشته باشد، \fIUV_ENOENT\fP برگردانده می‌شود. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع ایمن در برابر ریسه (Thread-safe) نیست. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.12.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_setenv(const char *name, const char *value) متغیر محیطی مشخص‌شده با \fIname\fP را ایجاد کرده یا با \fIvalue\fP به‌روزرسانی می‌کند. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع ایمن در برابر ریسه (Thread-safe) نیست. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.12.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_unsetenv(const char *name) متغیر محیطی مشخص‌شده با \fIname\fP را حذف می‌کند. اگر چنین متغیر محیطی وجود نداشته باشد، این تابع با موفقیت بازمی‌گردد. .sp \fBهشدار:\fP .INDENT 7.0 .INDENT 3.5 این تابع ایمن در برابر ریسه (Thread-safe) نیست. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.12.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_gethostname(char *buffer, size_t *size) نام میزبان (Hostname) را به عنوان یک رشته پایان‌یافته با null در \fIbuffer\fP برمی‌گرداند، و \fIsize\fP را روی طول رشته نام میزبان تنظیم می‌کند. هنگام فراخوانی این تابع، \fIsize\fP باید روی مقدار فضای در دسترس در \fIbuffer\fP شامل نویسه پایان‌بخش null تنظیم شود. اگر نام میزبان از فضای موجود در \fIbuffer\fP فراتر رود، \fIUV_ENOBUFS\fP برگردانده می‌شود و \fIsize\fP روی مقدار فضای مورد نیاز برای نگهداری مقدار تنظیم می‌گردد. .sp افزوده شده در نسخه 1.12.0. .sp تغییر یافته در نسخه 1.26.0: ثابت \fIUV_MAXHOSTNAMESIZE\fP در دسترس است و بیانگر حداکثر اندازه \fIbuffer\fP مورد نیاز برای ذخیره نام میزبان و کاراکتر \fInul\fP انتهایی است. .UNINDENT .INDENT 0.0 .TP .B int uv_os_getpriority(uv_pid_t \%<#\:c\:.uv_pid_t> pid, int *priority) اولویت زمان‌بندی فرایند مشخص‌شده با \fIpid\fP را بازیابی می‌کند. مقدار بازگردانده شده \fIpriority\fP بین \-20 (اولویت بالا) و 19 (اولویت پایین) است. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز، اولویت بازگردانده شده برابر با یکی از ثابت‌های \fIUV_PRIORITY\fP خواهد بود. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.23.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_setpriority(uv_pid_t \%<#\:c\:.uv_pid_t> pid, int priority) اولویت زمان‌بندی فرایند مشخص‌شده با \fIpid\fP را تنظیم می‌کند. دامنه مقدار \fIpriority\fP بین \-20 (اولویت بالا) و 19 (اولویت پایین) است. ثابت‌های \fIUV_PRIORITY_LOW\fP، \fIUV_PRIORITY_BELOW_NORMAL\fP، \fIUV_PRIORITY_NORMAL\fP، \fIUV_PRIORITY_ABOVE_NORMAL\fP، \fIUV_PRIORITY_HIGH\fP و \fIUV_PRIORITY_HIGHEST\fP نیز برای سهولت ارائه شده‌اند. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز، این تابع از \fISetPriorityClass()\fP استفاده می‌کند. آرگومان \fIpriority\fP به یک رده اولویت ویندوز نگاشت می‌شود. هنگام بازیابی اولویت فرایند، نتیجه برابر با یکی از ثابت‌های \fIUV_PRIORITY\fP خواهد بود، و لزوماً مقدار دقیق \fIpriority\fP نیست. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در ویندوز، تنظیم \fIPRIORITY_HIGHEST\fP تنها برای کاربران ارشد (Elevated) کار خواهد کرد، و برای سایرین به طور خودکار به \fIPRIORITY_HIGH\fP کاهش می‌یابد. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در IBM i PASE، بالاترین اولویت فرایند \-10 است. ثابت \fIUV_PRIORITY_HIGHEST\fP برابر \-10، \fIUV_PRIORITY_HIGH\fP برابر \-7، \fIUV_PRIORITY_ABOVE_NORMAL\fP برابر \-4، \fIUV_PRIORITY_NORMAL\fP برابر 0، \fIUV_PRIORITY_BELOW_NORMAL\fP برابر 15 و \fIUV_PRIORITY_LOW\fP برابر 39 است. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 در IBM i PASE، مجاز به تغییر اولویت خود نیستید مگر اینکه دارای مجوز ویژه *JOBCTL باشید (حتی برای کاهش اولویت). .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.23.0. .UNINDENT .INDENT 0.0 .TP .B int uv_os_uname(uv_utsname_t \%<#\:c\:.uv_utsname_t> *buffer) اطلاعات سیستم را در \fIbuffer\fP بازیابی می‌کند. داده‌های پرشده شامل نام سیستم‌عامل، انتشار (Release)، نسخه و معماری ماشین است. در سیستم‌های غیرویندوزی، \fIuv_os_uname()\fP یک پوشش نازک روی uname(2) \% است. در صورت موفقیت صفر و در غیر این صورت یک مقدار خطای غیرصفر برمی‌گرداند. .sp افزوده شده در نسخه 1.25.0. .UNINDENT .INDENT 0.0 .TP .B int uv_gettimeofday(uv_timeval64_t \%<#\:c\:.uv_timeval64_t> *tv) پیاده‌سازی چندسکویی از gettimeofday(2) \%\&. آرگومان timezone در \fIgettimeofday()\fP پشتیبانی نمی‌شود، زیرا منسوخ تلقی می‌گردد. .sp افزوده شده در نسخه 1.28.0. .UNINDENT .INDENT 0.0 .TP .B int uv_random(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_random_t \%<#\:c\:.uv_random_t> *req, void *buf, size_t buflen, unsigned int flags, uv_random_cb \%<#\:c\:.uv_random_cb> cb) بافر \fIbuf\fP را دقیقاً با \fIbuflen\fP بایت تصادفی از نظر رمزنگاری قوی که از CSPRNG سیستم به دست آمده است پر می‌کند. پارامتر \fIflags\fP برای توسعه‌های آتی رزرو شده و در حال حاضر باید 0 باشد. .sp خواندن ناقص (Short read) امکان‌پذیر نیست. هنگامی که کمتر از \fIbuflen\fP بایت تصادفی در دسترس باشد، مقدار خطای غیرصفر بازگردانده شده یا به تابع بازخوانی ارسال می‌شود. .sp نسخه همگام ممکن است در صورت عدم وجود آنتروپی کافی به طور نامحدود مسدود شود. نسخه ناهمگام ممکن است در صورت کمبود آنتروپی سیستم هرگز پایان نیابد. .sp منابع آنتروپی: .INDENT 7.0 .IP \(bu 2 ویندوز: \fIRtlGenRandom _\fP\&. .IP \(bu 2 لینوکس، اندروید: getrandom(2) \% در صورت وجود، یا urandom(4) \% پس از یک‌بار خواندن از \fI/dev/random\fP، یا فراخوانی \fIKERN_RANDOM\fP از طریق sysctl(2) \%\&. .IP \(bu 2 فری‌بی‌اس‌دی: \fIgetrandom(2) _\fP، یا \fI/dev/urandom\fP پس از یک‌بار خواندن از \fI/dev/random\fP. .IP \(bu 2 نت‌بی‌اس‌دی: \fIKERN_ARND\fP \fIsysctl(7) _\fP .IP \(bu 2 مک او اس، اوپن‌بی‌اس‌دی: \fIgetentropy(2) _\fP در صورت وجود، یا \fI/dev/urandom\fP پس از یک‌بار خواندن از \fI/dev/random\fP. .IP \(bu 2 سیستم AIX: پرونده \fI/dev/random\fP\&. .IP \(bu 2 سیستم IBM i: پرونده \fI/dev/urandom\fP\&. .IP \(bu 2 سایر یونیکس‌ها: \fI/dev/urandom\fP پس از یک‌بار خواندن از \fI/dev/random\fP. .UNINDENT .INDENT 7.0 .TP .B مقادیر بازگشتی (Returns) در صورت موفقیت 0، یا یک کد خطای کمتر از 0 در صورت شکست. محتوای \fIbuf\fP پس از بروز خطا تعریف‌نشده است. .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 هنگام استفاده از نسخه همگام، هر دو پارامتر \fIloop\fP و \fIreq\fP استفاده نمی‌شوند و می‌توان آن‌ها را روی \fINULL\fP تنظیم کرد. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.33.0. .UNINDENT .INDENT 0.0 .TP .B void uv_sleep(unsigned int msec) باعث به خواب رفتن ریسه فراخوان به مدت \fImsec\fP میلی‌ثانیه می‌شود. .sp افزوده شده در نسخه 1.34.0. .UNINDENT .SS توابع دستکاری رشته (String manipulation functions) .sp این ابزارهای کار با رشته در داخل کتابخانه برای تعامل با ویندوز مورد نیاز هستند و صادر (export) شده‌اند تا به کلاینت‌ها امکان دهند در صورت کامل نبودن API libuv به صورت یکپارچه با این داده‌ها کار کنند. .INDENT 0.0 .TP .B size_t uv_utf16_length_as_wtf8(const uint16_t *utf16, ssize_t utf16_len) طول یک مقدار UTF\-16 (یا UCS\-2) به نام \fIutf16\fP را پس از تبدیل به WTF\-8 دریافت می‌کند. اگر \fIutf16\fP با NUL خاتمه یافته باشد، \fIutf16_len\fP را می‌توان روی \-1 تنظیم کرد، در غیر این صورت باید به طور صریح مشخص شود. .sp افزوده شده در نسخه 1.47.0. .UNINDENT .INDENT 0.0 .TP .B int uv_utf16_to_wtf8(const uint16_t *utf16, ssize_t utf16_len, char **wtf8_ptr, size_t *wtf8_len_ptr) داده‌های UTF\-16 (یا UCS\-2) موجود در \fIutf16\fP را به داده‌های WTF\-8 در \fI*wtf8_ptr\fP تبدیل می‌کند. شمارش \fIutf16_len\fP (بر حسب کاراکتر) طول \fIutf16\fP را مشخص می‌کند. اگر \fIutf16\fP با NUL پایان یافته باشد، \fIutf16_len\fP می‌تواند روی \-1 تنظیم شود، در غیر این صورت باید مقداردهی شود. اگر \fIwtf8_ptr\fP برابر \fINULL\fP باشد، هیچ نتیجه‌ای محاسبه نمی‌شود، اما طول (برابر با \fIuv_utf16_length_as_wtf8\fP) در \fIwtf8_len_ptr\fP ذخیره خواهد شد. اگر \fI*wtf8_ptr\fP برابر \fINULL\fP باشد، فضا برای تبدیل تخصیص داده شده و در \fIwtf8_ptr\fP برگردانده می‌شود و طول در \fIwtf8_len_ptr\fP برگردانده خواهد شد. در غیر این صورت، طول \fI*wtf8_ptr\fP باید در \fIwtf8_len_ptr\fP ارسال شود. متغیر \fIwtf8_ptr\fP باید شامل فضای اضافی برای یک NUL اضافی بعد از نتیجه باشد. اگر نتیجه کوتاه (truncated) شود، مقدار \fIUV_ENOBUFS\fP برگردانده می‌شود و \fIwtf8_len_ptr\fP طول مورد نیاز برای \fIwtf8_ptr\fP به منظور نگهداری کل نتیجه خواهد بود. .sp افزوده شده در نسخه 1.47.0. .UNINDENT .INDENT 0.0 .TP .B ssize_t uv_wtf8_length_as_utf16(const char *wtf8) طول یک مقدار WTF\-8 خاتمه‌یافته با NUL به نام \fIwtf8\fP را پس از تبدیل به UTF\-16 (یا UCS\-2)، شامل نویسه پایان‌بخش NUL، بر حسب کاراکتر دریافت می‌کند. .sp افزوده شده در نسخه 1.47.0. .UNINDENT .INDENT 0.0 .TP .B void uv_wtf8_to_utf16(const char *utf8, uint16_t *utf16, size_t utf16_len) داده‌های WTF\-8 پایان‌یافته با NUL در \fIwtf8\fP را به داده‌های UTF\-16 (یا UCS\-2) در \fIutf16\fP تبدیل می‌کند. شمارش \fIutf16_len\fP (بر حسب کاراکتر) باید فضا برای بایت پایان‌بخش NUL را شامل شود. .sp افزوده شده در نسخه 1.47.0. .UNINDENT .SS عملیات معیارسنجی (Metrics operations) .sp کتابخانه libuv یک رابط کاربری معیارسنجی (Metrics API) برای ردیابی عملیات داخلی مختلف حلقه رویداد فراهم می‌کند. .SS انواع داده (Data types) .INDENT 0.0 .TP .B type uv_metrics_t ساختاری که معیارهای حلقه رویداد را در خود نگه می‌دارد. توصیه می‌شود این معیارها در یک \fBuv_prepare_cb\fP \%<#\:c\:.uv_prepare_cb> بازیابی شوند تا اطمینان حاصل شود که هیچ‌گونه ناهمخوانی با شمارنده‌های معیارها رخ نمی‌دهد. .INDENT 7.0 .INDENT 3.5 .sp .EX typedef struct { uint64_t loop_count; uint64_t events; uint64_t events_waiting; /* private */ uint64_t* reserved[13]; } uv_metrics_t; .EE .UNINDENT .UNINDENT .UNINDENT .SS اعضای عمومی (Public members) .INDENT 0.0 .TP .B uint64_t uv_metrics_t \%<#\:c\:.uv_metrics_t>\&.loop_count تعداد تکرارهای حلقه رویداد. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_metrics_t \%<#\:c\:.uv_metrics_t>\&.events تعداد رویدادهایی که توسط مدیریت‌کننده رویداد (Event handler) پردازش شده‌اند. .UNINDENT .INDENT 0.0 .TP .B uint64_t uv_metrics_t \%<#\:c\:.uv_metrics_t>\&.events_waiting تعداد رویدادهایی که هنگام فراخوانی ارائه‌دهنده رویداد در انتظار پردازش بودند. .UNINDENT .SS رابط برنامه‌نویسی (API) .INDENT 0.0 .TP .B uint64_t uv_metrics_idle_time(uv_loop_t \%<#\:c\:.uv_loop_t> *loop) مدت زمانی را که حلقه رویداد در ارائه‌دهنده رویداد هسته (مانند \fBepoll_wait\fP) بی‌کار (Idle) بوده است، بازیابی می‌کند. این فراخوانی ایمن در برابر ریسه (Thread-safe) است. .sp مقدار بازگشتی، زمان انباشته سپری‌شده در حالت بی‌کاری در ارائه‌دهنده رویداد هسته از زمانی است که \fBuv_loop_t\fP \%<#\:c\:.uv_loop_t> برای جمع‌آوری زمان بی‌کاری پیکربندی شده بود. .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 حلقه رویداد تا قبل از فراخوانی \fBuv_loop_configure\fP \%<#\:c\:.uv_loop_configure> با \fBUV_METRICS_IDLE_TIME\fP شروع به انباشت زمان بی‌کاری ارائه‌دهنده رویداد نخواهد کرد. .UNINDENT .UNINDENT .sp افزوده شده در نسخه 1.39.0. .UNINDENT .INDENT 0.0 .TP .B int uv_metrics_info(uv_loop_t \%<#\:c\:.uv_loop_t> *loop, uv_metrics_t \%<#\:c\:.uv_metrics_t> *metrics) مجموعه فعلی معیارهای حلقه رویداد را در اشاره‌گر \fBmetrics\fP کپی می‌کند. .sp افزوده شده در نسخه 1.45.0. .UNINDENT .SS راهنمای کاربر .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 محتوای این راهنما به تازگی به مستندات libuv اضافه شده است و هنوز مورد بازبینی دقیق قرار نگرفته است. اگر متوجه خطایی شدید لطفاً یک گزارش مشکل (issue) ثبت کنید، یا حتی بهتر، یک پول ریکوئست (pull request) باز کنید! .UNINDENT .UNINDENT .SS مقدمه .sp این «کتاب» مجموعه‌ای کوچک از آموزش‌ها درباره استفاده از libuv \% به عنوان یک کتابخانه ورودی/خروجی رویدادمحور (evented I/O) با کارایی بالا است که رابط برنامه‌نویسی (API) یکسانی را در ویندوز و یونیکس ارائه می‌دهد. .sp هدف این کتاب پوشش بخش‌های اصلی libuv است، اما مرجع جامعی برای بررسی تک‌تک توابع و ساختارهای داده نیست. برای مشاهده جزئیات کامل می‌توانید به مستندات رسمی libuv \% مراجعه کنید. .sp این کتاب همچنان در حال تکمیل است، بنابراین ممکن است برخی بخش‌ها ناقص باشند، اما امیدوارم با گسترش آن از مطالعه‌اش لذت ببرید. .SS مخاطبان این کتاب .sp اگر در حال خواندن این کتاب هستید، یکی از این دو دسته هستید: .INDENT 0.0 .IP 1. 3 یک برنامه‌نویس سیستم هستید که برنامه‌های سطح پایین مانند دیمن‌ها (daemons) یا سرویس‌ها و کلاینت‌های شبکه را ایجاد می‌کند. شما متوجه شده‌اید که رویکرد حلقه رویداد (event loop) برای برنامه شما بسیار مناسب است و تصمیم به استفاده از libuv گرفته‌اید. .IP 2. 3 یک نویسنده ماژول node.js هستید که می‌خواهد رابط‌های برنامه‌نویسی پلتفرم را که با C یا ++C نوشته شده‌اند، با مجموعه‌ای از APIهای همگام یا ناهمگام که در اختیار JavaScript قرار می‌گیرند بسته‌بندی کند. شما از libuv صرفاً در زمینه node.js استفاده خواهید کرد. برای این کار به منابع دیگری نیاز خواهید داشت زیرا این کتاب بخش‌های اختصاصی v8/node.js را پوشش نمی‌دهد. .UNINDENT .sp این کتاب فرض می‌کند که شما با زبان برنامه‌نویسی C آشنایی کامل دارید. .SS پیش‌زمینه .sp پروژه node.js \% در سال ۲۰۰۹ به عنوان یک محیط اجرای جاوااسکریپت مستقل از مرورگر آغاز شد. با استفاده از موتور V8 گوگل \% و کتابخانه libev اثر مارک لمان \%، پروژه node.js یک مدل I/O رویدادمحور را با زبانی که به دلیل شکل‌گیری در بستر مرورگرها با این سبک برنامه‌نویسی سازگار بود ترکیب کرد. با افزایش محبوبیت node.js، اجرای آن در ویندوز اهمیت یافت، اما libev فقط در یونیکس اجرا می‌شد. معادل ویندوزی مکانیزم‌های آگاه‌سازی رویداد هسته مانند kqueue یا epoll/poll، سازوکار IOCP است. کتابخانه libuv یک لایه انتزاعی روی libev یا IOCP (بسته به پلتفرم) بود که یک API بر پایه libev در اختیار کاربران قرار می‌داد. در نسخه node-v0.9.0 از libuv، وابستگی به libev حذف شد \%\&. .sp از آن زمان، libuv به بلوغ خود ادامه داده و به یک کتابخانه مستقل و باکیفیت برای برنامه‌نویسی سیستم تبدیل شده است. کاربران خارج از node.js شامل زبان برنامه‌نویسی Rust بنیاد موزیلا \% و انواع اتصالات زبانی (language bindings) مختلف \% هستند. .sp این کتاب و کدهای آن بر اساس نسخه v1.42.0 کتابخانه libuv \% نگارش شده است. .SS کدها .sp تمامی کدهای نمونه و منبع کتاب به عنوان بخشی از پروژه libuv \% در گیت‌هاب قرار دارند. مخزن libuv \% را کلون یا دانلود کنید، سپس آن را بسازید: .INDENT 0.0 .INDENT 3.5 .sp .EX sh autogen.sh \&./configure make .EE .UNINDENT .UNINDENT .sp نیازی به اجرای \fBmake install\fP نیست. برای ساخت نمونه‌ها، دستور \fBmake\fP را در دایرکتوری \fBdocs/code/\fP اجرا کنید. .SS مبانی libuv .sp کتابخانه libuv یک سبک برنامه‌نویسی \fBناهمگام (asynchronous)\fP و \fBرویدادمحور (event\-driven)\fP را اعمال می‌کند. وظیفه اصلی آن فراهم کردن یک حلقه رویداد و اعلان‌های مبتنی بر کال‌بک (callback) برای عملیات ورودی/خروجی و سایر فعالیت‌ها است. کتابخانه libuv ابزارهای پایه‌ای مانند تایمرها، پشتیبانی از شبکه غیرمسدودکننده، دسترسی ناهمگام به فایل‌سیستم، فرآیندهای فرزند و موارد دیگر را ارائه می‌دهد. .SS حلقه‌های رویداد .sp در برنامه‌نویسی رویدادمحور، یک برنامه تمایل خود را برای رویدادهای خاصی اعلام می‌کند و هنگام وقوع آن‌ها پاسخ می‌دهد. مسئولیت گردآوری رویدادها از سیستم‌عامل یا پایش سایر منابع رویداد بر عهده libuv است و کاربر می‌تواند کال‌بک‌هایی (callbacks) را ثبت کند تا هنگام رخ دادن یک رویداد فراخوانی شوند. حلقه رویداد معمولاً \fIبه صورت نامحدود (forever)\fP اجرا می‌شود. در قالب شبه‌کد: .INDENT 0.0 .INDENT 3.5 .sp .EX while there are still events to process: e = get the next event if there is a callback associated with e: call the callback .EE .UNINDENT .UNINDENT .sp برخی نمونه‌های رویداد عبارتند از: .INDENT 0.0 .IP \(bu 2 فایل برای نوشتن آماده است .IP \(bu 2 یک سوکت داده‌ای آماده خواندن دارد .IP \(bu 2 یک تایمر منقضی شده است .UNINDENT .sp این حلقه رویداد درون تابع \fBuv_run()\fP کپسوله‌سازی شده است \-\- تابع نهایی و همه‌کاره هنگام استفاده از libuv. .sp رایج‌ترین فعالیت برنامه‌های سیستمی رسیدگی به ورودی و خروجی است، نه پردازش‌های سنگین محاسباتی. مشکل استفاده از توابع متداول ورودی/خروجی (\fBread\fP، \fBfprintf\fP و غیره) این است که آن‌ها \fBمسدودکننده (blocking)\fP هستند. نوشتن واقعی روی دیسک سخت یا خواندن از شبکه در مقایسه با سرعت پردازنده زمان نامتناسب و طولانی می‌برد. این توابع تا زمان اتمام کار بازنمی‌گردند، بنابراین برنامه شما عملاً هیچ کاری انجام نمی‌دهد. برای برنامه‌هایی که به کارایی بالا نیاز دارند، این یک مانع بزرگ است زیرا سایر فعالیت‌ها و عملیات ورودی/خروجی دیگر معطل می‌مانند. .sp یکی از راه‌حل‌های استاندارد استفاده از نخ‌ها (threads) است. هر عملیات I/O مسدودکننده در یک نخ جداگانه (یا در یک استخر نخ) آغاز می‌شود. هنگامی که تابع مسدودکننده در نخ فراخوانی می‌شود، سیستم‌عامل می‌تواند نخ دیگری را برای اجرا زمان‌بندی کند که واقعاً به CPU نیاز دارد. .sp رویکردی که libuv دنبال می‌کند از سبک دیگری استفاده می‌کند که سبک \fBناهمگام و غیرمسدودکننده (asynchronous, non\-blocking)\fP است. اکثر سیستم‌عامل‌های مدرن زیرسیستم‌های اعلان رویداد را ارائه می‌دهند. به عنوان مثال، یک فراخوانی عادی \fBread\fP روی سوکت مسدود می‌شود تا زمانی که فرستنده واقعاً چیزی ارسال کند. در عوض، برنامه می‌تواند از سیستم‌عامل بخواهد سوکت را پایش کند و یک اعلان رویداد در صف قرار دهد. برنامه می‌تواند به دلخواه خود رویدادها را بررسی کند (شاید پیش از آن محاسباتی انجام دهد تا حداکثر استفاده را از پردازنده ببرد) و داده‌ها را بردارد. این رویکرد \fBناهمگام (asynchronous)\fP است زیرا برنامه در یک نقطه اعلام علاقه کرده و سپس در نقطه‌ای دیگر (در زمان و فضا) از داده‌ها استفاده کرده است. همچنین \fBغیرمسدودکننده (non\-blocking)\fP است زیرا فرآیند برنامه برای انجام سایر وظایف آزاد بوده است. این سبک به خوبی با رویکرد حلقه رویداد libuv هماهنگ است، زیرا رویدادهای سیستم‌عامل می‌توانند به سادگی به عنوان یک رویداد دیگر libuv در نظر گرفته شوند. ماهیت غیرمسدودکننده تضمین می‌کند که به سایر رویدادها به محض رسیدن، با حداکثر سرعت رسیدگی شود [1]\&. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 نحوه اجرای I/O در پس‌زمینه اهمیتی برای ما ندارد، اما به دلیل سازوکار سخت‌افزار رایانه‌ها که نخ واحد پایه‌ای پردازنده است، libuv و سیستم‌عامل‌ها معمولاً نخ‌های پس‌زمینه/کارگر و/یا نمونه‌برداری (polling) را برای انجام وظایف به صورت غیرمسدودکننده اجرا می‌کنند. .UNINDENT .UNINDENT .sp برت بلدر (Bert Belder)، یکی از توسعه‌دهندگان اصلی libuv، ویدیوی کوتاهی دارد که معماری libuv و پیش‌زمینه آن را توضیح می‌دهد. اگر تجربه قبلی کار با libuv یا libev را ندارید، تماشای آن کوتاه و مفید خواهد بود. .sp حلقه رویداد libuv با جزئیات بیشتر در مستندات \% توضیح داده شده است. .SS برنامه آغازین (Hello World) .sp با گذر از مبانی اولیه، بیایید اولین برنامه libuv خود را بنویسیم. این برنامه کاری انجام نمی‌دهد جز شروع یک حلقه که بلافاصله خارج می‌شود. .sp helloworld/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main() { uv_loop_t *loop = malloc(sizeof(uv_loop_t)); uv_loop_init(loop); printf(\(dqNow quitting.\en\(dq); uv_run(loop, UV_RUN_DEFAULT); uv_loop_close(loop); free(loop); return 0; } .EE .UNINDENT .UNINDENT .sp این برنامه بلافاصله خارج می‌شود زیرا هیچ رویدادی برای پردازش ندارد. یک حلقه رویداد libuv باید با استفاده از توابع مختلف API برای پایش رویدادها تنظیم شود. .sp از نسخه libuv v1.0 به بعد، کاربران باید پیش از مقداردهی اولیه حلقه با \fBuv_loop_init(uv_loop_t *)\fP حافظه مورد نیاز آن را تخصیص دهند. این کار به شما امکان می‌دهد از مدیریت حافظه سفارشی استفاده کنید. به یاد داشته باشید که حلقه را با \fBuv_loop_close(uv_loop_t *)\fP آزاد و غیرفعال کنید و سپس حافظه را پاک نمایید. برنامه‌های نمونه هرگز حلقه‌ها را نمی‌بندند زیرا برنامه پس از پایان حلقه به پایان می‌رسد و سیستم حافظه را پس می‌گیرد. اما در پروژه‌های سطح عملیاتی، به‌ویژه برنامه‌های سیستمی با اجرای طولانی‌مدت، باید دقت کرد که آزادسازی منابع به درستی انجام شود. .SS حلقه پیش‌فرض (Default loop) .sp یک حلقه پیش‌فرض توسط libuv ارائه می‌شود که با \fBuv_default_loop()\fP قابل دسترسی است. اگر فقط به یک حلقه واحد نیاز دارید، باید از این حلقه استفاده کنید. .sp default\-loop/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main() { uv_loop_t *loop = uv_default_loop(); printf(\(dqDefault loop.\en\(dq); uv_run(loop, UV_RUN_DEFAULT); uv_loop_close(loop); return 0; } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 محیط node.js از حلقه پیش‌فرض به عنوان حلقه اصلی خود استفاده می‌کند. اگر در حال نوشتن اتصالات زبانی (bindings) هستید، باید از این نکته آگاه باشید. .UNINDENT .UNINDENT .SS مدیریت خطاها (Error handling) .sp توابع مقداردهی اولیه یا توابع همگام که ممکن است با شکست مواجه شوند، در صورت خطا یک عدد منفی برمی‌گردانند. توابع ناهمگام که ممکن است با شکست مواجه شوند، یک پارامتر وضعیت (status) به کال‌بک‌های خود ارسال می‌کنند. پیام‌های خطا به صورت ثابت‌های \fBUV_E*\fP \% تعریف شده‌اند. .sp می‌توانید از توابع \fBuv_strerror(int)\fP و \fBuv_err_name(int)\fP استفاده کنید تا به ترتیب یک رشته \fBconst char *\fP توصیف‌کننده خطا یا نام خطا را دریافت کنید. .sp به کال‌بک‌های خواندن I/O (مانند فایل‌ها و سوکت‌ها) پارامتری به نام \fBnread\fP ارسال می‌شود. اگر \fBnread\fP کمتر از ۰ باشد، خطایی رخ داده است (UV_EOF خطای پایان فایل است که ممکن است بخواهید آن را به شکل متفاوتی مدیریت کنید). .SS هندل‌ها و درخواست‌ها (Handles and Requests) .sp کتابخانه libuv بر این اساس کار می‌کند که کاربر تمایل خود را برای رویدادهای خاص اعلام کند. این کار معمولاً با ایجاد یک \fBهندل (handle)\fP برای یک دستگاه I/O، تایمر یا فرآیند انجام می‌شود. هندل‌ها ساختارهای مات (opaque structs) با نام \fBuv_TYPE_t\fP هستند که در آن type کاربرد هندل را مشخص می‌کند. .sp پایشگرهای libuv .INDENT 0.0 .INDENT 3.5 .sp .EX /* Handle types. */ typedef struct uv_loop_s uv_loop_t; typedef struct uv_handle_s uv_handle_t; typedef struct uv_dir_s uv_dir_t; typedef struct uv_stream_s uv_stream_t; typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_udp_s uv_udp_t; typedef struct uv_pipe_s uv_pipe_t; typedef struct uv_tty_s uv_tty_t; typedef struct uv_poll_s uv_poll_t; typedef struct uv_timer_s uv_timer_t; typedef struct uv_prepare_s uv_prepare_t; typedef struct uv_check_s uv_check_t; typedef struct uv_idle_s uv_idle_t; typedef struct uv_async_s uv_async_t; typedef struct uv_process_s uv_process_t; typedef struct uv_fs_event_s uv_fs_event_t; typedef struct uv_fs_poll_s uv_fs_poll_t; typedef struct uv_signal_s uv_signal_t; /* Request types. */ typedef struct uv_req_s uv_req_t; typedef struct uv_getaddrinfo_s uv_getaddrinfo_t; typedef struct uv_getnameinfo_s uv_getnameinfo_t; typedef struct uv_shutdown_s uv_shutdown_t; typedef struct uv_write_s uv_write_t; typedef struct uv_connect_s uv_connect_t; typedef struct uv_udp_send_s uv_udp_send_t; typedef struct uv_fs_s uv_fs_t; typedef struct uv_work_s uv_work_t; typedef struct uv_random_s uv_random_t; /* None of the above. */ typedef struct uv_env_item_s uv_env_item_t; typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; typedef struct uv_dirent_s uv_dirent_t; typedef struct uv_passwd_s uv_passwd_t; typedef struct uv_utsname_s uv_utsname_t; typedef struct uv_statfs_s uv_statfs_t; .EE .UNINDENT .UNINDENT .sp هندل‌ها نشان‌دهنده اشیاء با طول عمر طولانی هستند. عملیات‌های ناهمگام روی این هندل‌ها با استفاده از \fBدرخواست‌ها (requests)\fP شناسایی می‌شوند. یک درخواست عمر کوتاهی دارد (معمولاً فقط در طول یک کال‌بک استفاده می‌شود) و معمولاً نشان‌دهنده یک عملیات ورودی/خروجی روی یک هندل است. درخواست‌ها برای حفظ زمینه (context) بین شروع عملیات و کال‌بک مربوط به هر اقدام استفاده می‌شوند. برای مثال، یک سوکت UDP توسط یک \fBuv_udp_t\fP نشان داده می‌شود، در حالی که عملیات نوشتن روی سوکت از یک ساختار \fBuv_udp_send_t\fP استفاده می‌کند که پس از اتمام نوشتن به کال‌بک ارسال می‌شود. .sp هندل‌ها توسط تابع مربوطه مقداردهی اولیه می‌شوند: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_TYPE_init(uv_loop_t *, uv_TYPE_t *) .EE .UNINDENT .UNINDENT .sp .sp کال‌بک‌ها توابعی هستند که هر زمان رویداد مورد علاقه پایشگر رخ دهد، توسط libuv فراخوانی می‌شوند. منطق اختصاصی برنامه معمولاً در کال‌بک پیاده‌سازی می‌شود. به عنوان مثال، کال‌بک یک پایشگر IO داده‌های خوانده‌شده از فایل را دریافت می‌کند، کال‌بک تایمر هنگام انقضای زمان فعال می‌شود و غیره. .SS بیکاری (Idling) .sp در اینجا نمونه‌ای از استفاده از یک هندل بیکاری (idle handle) آورده شده است. کال‌بک در هر دور از حلقه رویداد یک بار فراخوانی می‌شود. یک مورد کاربرد برای هندل‌های بیکار در بخش ابزارها \%<> بررسی شده است. بیایید از یک پایشگر بیکار برای مشاهده چرخه حیات پایشگر استفاده کنیم و ببینیم چگونه \fBuv_run()\fP به دلیل وجود یک پایشگر مسدود خواهد ماند. پایشگر بیکار با رسیدن شمارنده به مقدار تعیین‌شده متوقف می‌شود و \fBuv_run()\fP به دلیل نبود پایشگرهای فعال خارج می‌گردد. .sp idle\-basic/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int64_t counter = 0; void wait_for_a_while(uv_idle_t* handle) { counter++; if (counter >= 10e6) uv_idle_stop(handle); } int main() { uv_idle_t idler; uv_idle_init(uv_default_loop(), &idler); uv_idle_start(&idler, wait_for_a_while); printf(\(dqIdling...\en\(dq); uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); return 0; } .EE .UNINDENT .UNINDENT .SS ذخیره زمینه (Storing context) .sp در سبک برنامه‌نویسی مبتنی بر کال‌بک، اغلب می‌خواهید مقداری «زمینه (context)» \-\- اطلاعات اختصاصی برنامه \-\- را بین محل فراخوانی و کال‌بک منتقل کنید. تمامی هندل‌ها و درخواست‌ها دارای یک عضو \fBvoid* data\fP هستند که می‌توانید آن را روی اطلاعات زمینه تنظیم کرده و در کال‌بک مجدداً کست کنید. این یک الگوی رایج در سراسر اکوسیستم کتابخانه‌های C است. علاوه بر این، ساختار \fBuv_loop_t\fP نیز عضو داده مشابهی دارد. .sp .ce ---- .ce 0 .sp .IP [1] 5 البته بسته به ظرفیت سخت‌افزار. .SS سیستم فایل (Filesystem) .sp خواندن و نوشتن ساده در سیستم فایل با استفاده از توابع \fBuv_fs_*\fP و ساختار \fBuv_fs_t\fP انجام می‌شود. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 عملیات سیستم فایل در libuv با عملیات سوکت متفاوت است \%<>\&. عملیات سوکت از عملیات غیرمسدودکننده ارائه شده توسط سیستم‌عامل استفاده می‌کنند. اما عملیات سیستم فایل در داخل از توابع مسدودکننده استفاده می‌کنند ولی این توابع را در یک استخر نخ (thread pool) \% اجرا کرده و در صورت نیاز به تعامل با برنامه، پایشگرهای ثبت‌شده در حلقه رویداد را مطلع می‌سازند. .UNINDENT .UNINDENT .sp تمامی توابع سیستم فایل دارای دو شکل هستند \- \fIهمگام (synchronous)\fP و \fIناهمگام (asynchronous)\fP\&. .sp شکل‌های \fIهمگام\fP در صورتی که کال‌بک null باشد به صورت خودکار فراخوانی شده (و \fBمسدود می‌شوند\fP). مقدار بازگشتی توابع یک کد خطای libuv است \%<#\:libuv-error-handling>\&. این معمولاً فقط برای فراخوانی‌های همگام کاربرد دارد. شکل \fIناهمگام\fP زمانی فراخوانی می‌شود که یک کال‌بک ارسال شده باشد و مقدار بازگشتی 0 است. .SS خواندن/نوشتن فایل‌ها .sp توصیف‌کننده فایل با استفاده از تابع زیر به دست می‌آید: .INDENT 0.0 .INDENT 3.5 .sp .EX int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) .EE .UNINDENT .UNINDENT .sp پارامترهای \fBflags\fP و \fBmode\fP پرچم‌های استاندارد یونیکس هستند \%\&. کتابخانه libuv وظیفه تبدیل آن‌ها به پرچم‌های مناسب ویندوز را بر عهده دارد. .sp توصیف‌کننده‌های فایل با استفاده از تابع زیر بسته می‌شوند: .INDENT 0.0 .INDENT 3.5 .sp .EX int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) .EE .UNINDENT .UNINDENT .sp کال‌بک‌های عملیات سیستم فایل دارای امضای زیر هستند: .INDENT 0.0 .INDENT 3.5 .sp .EX void callback(uv_fs_t* req); .EE .UNINDENT .UNINDENT .sp بیایید یک پیاده‌سازی ساده از دستور \fBcat\fP را ببینیم. کار را با ثبت یک کال‌بک برای زمان باز شدن فایل شروع می‌کنیم: .sp uvcat/main.c \- باز کردن فایل .INDENT 0.0 .INDENT 3.5 .sp .EX // The request passed to the callback is the same as the one the call setup // function was passed. assert(req == &open_req); if (req\->result >= 0) { iov = uv_buf_init(buffer, sizeof(buffer)); uv_fs_read(uv_default_loop(), &read_req, req\->result, &iov, 1, \-1, on_read); } else { fprintf(stderr, \(dqerror opening file: %s\en\(dq, uv_strerror((int)req\->result)); } } .EE .UNINDENT .UNINDENT .sp فیلد \fBresult\fP در ساختار \fBuv_fs_t\fP در کال‌بک \fBuv_fs_open\fP همان توصیف‌کننده فایل است. اگر فایل با موفقیت باز شود، شروع به خواندن آن می‌کنیم. .sp uvcat/main.c \- کال‌بک خواندن .INDENT 0.0 .INDENT 3.5 .sp .EX if (req\->result < 0) { fprintf(stderr, \(dqRead error: %s\en\(dq, uv_strerror(req\->result)); } else if (req\->result == 0) { uv_fs_t close_req; // synchronous uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL); } else if (req\->result > 0) { iov.len = req\->result; uv_fs_write(uv_default_loop(), &write_req, 1, &iov, 1, \-1, on_write); } } .EE .UNINDENT .UNINDENT .sp در مورد فراخوانی خواندن، باید یک بافر \fIمقداردهی اولیه شده\fP را ارسال کنید که پیش از فعال شدن کال‌بک خواندن با داده‌ها پر می‌شود. عملیات‌های \fBuv_fs_*\fP تقریباً مستقیماً به توابع خاص POSIX نگاشت می‌شوند، بنابراین پایان فایل (EOF) در این حالت با مقدار 0 در \fBresult\fP مشخص می‌شود. در مورد استریم‌ها یا پایپ‌ها، ثابت \fBUV_EOF\fP به عنوان وضعیت ارسال می‌شد. .sp در اینجا یک الگوی رایج هنگام نوشتن برنامه‌های ناهمگام را مشاهده می‌کنید. فراخوانی \fBuv_fs_close()\fP به صورت همگام انجام می‌شود. \fIمعمولاً کارهایی که یک‌باره هستند یا به عنوان بخشی از مرحله راه‌اندازی یا خاموش‌سازی انجام می‌شوند، به صورت همگام اجرا می‌گردند، زیرا ما زمانی به I/O سریع علاقه‌مندیم که برنامه در حال انجام وظیفه اصلی خود و رسیدگی به چندین منبع ورودی/خروجی است\fP\&. برای وظایف تک‌باره تفاوت عملکرد معمولاً ناچیز است و می‌تواند به کدهای ساده‌تر منجر شود. .sp نوشتن در سیستم فایل با استفاده از \fBuv_fs_write()\fP به همین سادگی است. \fIکال‌بک شما پس از اتمام نوشتن فعال خواهد شد\fP\&. در مورد ما، کال‌بک به سادگی خواندن بعدی را هدایت می‌کند. بنابراین خواندن و نوشتن به صورت گام‌به‌گام از طریق کال‌بک‌ها پیش می‌روند. .sp uvcat/main.c \- کال‌بک نوشتن .INDENT 0.0 .INDENT 3.5 .sp .EX if (req\->result < 0) { fprintf(stderr, \(dqWrite error: %s\en\(dq, uv_strerror((int)req\->result)); } else { uv_fs_read(uv_default_loop(), &read_req, open_req.result, &iov, 1, \-1, on_read); } } .EE .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 به دلیل نحوه پیکربندی سیستم‌های فایل و دیسک‌درایوها برای کارایی، عملیات نوشتنی که «موفقیت‌آمیز» گزارش می‌شود ممکن است هنوز روی دیسک ثبت نشده باشد. .UNINDENT .UNINDENT .sp حرکت دومینوها را در تابع \fBmain()\fP آغاز می‌کنیم: .sp uvcat/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX uv_fs_open(uv_default_loop(), &open_req, argv[1], O_RDONLY, 0, on_open); uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_fs_req_cleanup(&open_req); uv_fs_req_cleanup(&read_req); uv_fs_req_cleanup(&write_req); return 0; } .EE .UNINDENT .UNINDENT .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 تابع \fBuv_fs_req_cleanup()\fP باید همیشه روی درخواست‌های سیستم فایل فراخوانی شود تا تخصیص‌های حافظه داخلی در libuv آزاد شوند. .UNINDENT .UNINDENT .SS عملیات‌های سیستم فایل .sp تمامی عملیات استاندارد سیستم فایل مانند \fBunlink\fP، \fBrmdir\fP، \fBstat\fP به صورت ناهمگام پشتیبانی می‌شوند و ترتیب آرگومان‌های شهودی دارند. آن‌ها از همان الگوهای فراخوانی read/write/open پیروی می‌کنند و نتیجه را در فیلد \fBuv_fs_t.result\fP برمی‌گردانند. فهرست کامل: .sp عملیات‌های سیستم فایل (Filesystem operations) .INDENT 0.0 .INDENT 3.5 .sp .EX int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb); int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb); int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb); int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb); int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb); int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb); int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent); int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb); int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb); int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb); int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb); int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb); int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb); int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb); int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb); int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); .EE .UNINDENT .UNINDENT .SS بافرها و جریان‌ها .sp هندل پایه I/O در libuv جریان یا استریم (\fBuv_stream_t\fP) است. سوکت‌های TCP، سوکت‌های UDP و پایپ‌ها (pipes) برای I/O فایل و IPC همگی به عنوان زیرکلاس‌های استریم در نظر گرفته می‌شوند. .sp جریان‌ها با استفاده از توابع سفارشی برای هر زیرکلاس مقداردهی اولیه می‌شوند و سپس با توابع زیر مورد استفاده قرار می‌گیرند: .INDENT 0.0 .INDENT 3.5 .sp .EX int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb); int uv_read_stop(uv_stream_t*); int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); .EE .UNINDENT .UNINDENT .sp استفاده از توابع مبتنی بر استریم ساده‌تر از توابع سیستم فایل است و libuv با یک بار فراخوانی \fBuv_read_start()\fP به طور خودکار به خواندن از استریم ادامه می‌دهد تا زمانی که \fBuv_read_stop()\fP فراخوانی شود. .sp واحد گسسته داده، بافر است \-\- \fBuv_buf_t\fP\&. این ساختار صرفاً مجموعه‌ای از یک اشاره‌گر به بایت‌ها (\fBuv_buf_t.base\fP) و طول آن‌ها (\fBuv_buf_t.len\fP) است. ساختار \fBuv_buf_t\fP سبک بوده و به صورت مقداری (by value) منتقل می‌شود. آنچه به مدیریت نیاز دارد، بایت‌های واقعی هستند که باید توسط برنامه تخصیص داده شده و آزاد شوند. .sp \fBخطا:\fP .INDENT 0.0 .INDENT 3.5 \fBاین برنامه همیشه کار نمی‌کند، به چیزی بهتر نیاز است\fP .UNINDENT .UNINDENT .sp برای نمایش استریم‌ها باید از \fBuv_pipe_t\fP استفاده کنیم. این امکان استریم کردن فایل‌های محلی را فراهم می‌کند [2]\&. در اینجا یک ابزار ساده مانند tee با استفاده از libuv آورده شده است. انجام تمامی عملیات به صورت ناهمگام قدرت I/O رویدادمحور را نشان می‌دهد. دو عملیات نوشتن یکدیگر را مسدود نمی‌کنند، اما باید دقت کنیم که داده‌های بافر را کپی کنیم تا مطمئن شویم بافر پیش از نوشته شدن آزاد نمی‌شود. .sp برنامه باید به این صورت اجرا شود: .INDENT 0.0 .INDENT 3.5 .sp .EX \&./uvtee .EE .UNINDENT .UNINDENT .sp کار را با باز کردن پایپ‌ها روی فایل‌های مورد نیاز شروع می‌کنیم. پایپ‌های libuv به یک فایل به طور پیش‌فرض به صورت دوطرفه (bidirectional) باز می‌شوند. .sp uvtee/main.c \- خواندن روی پایپ‌ها .INDENT 0.0 .INDENT 3.5 .sp .EX loop = uv_default_loop(); uv_pipe_init(loop, &stdin_pipe, 0); uv_pipe_open(&stdin_pipe, 0); uv_pipe_init(loop, &stdout_pipe, 0); uv_pipe_open(&stdout_pipe, 1); uv_fs_t file_req; int fd = uv_fs_open(loop, &file_req, argv[1], O_CREAT | O_RDWR, 0644, NULL); uv_pipe_init(loop, &file_pipe, 0); uv_pipe_open(&file_pipe, fd); uv_read_start((uv_stream_t*)&stdin_pipe, alloc_buffer, read_stdin); uv_run(loop, UV_RUN_DEFAULT); return 0; } .EE .UNINDENT .UNINDENT .sp آرگومان سوم \fBuv_pipe_init()\fP برای IPC با استفاده از پایپ‌های نام‌گذاری‌شده باید روی 1 تنظیم شود. این موضوع در بخش فرآیندها \%<> پوشش داده شده است. فراخوانی \fBuv_pipe_open()\fP پایپ را با توصیف‌کننده فایل مرتبط می‌کند، که در این مورد \fB0\fP (ورودی استاندارد) است. .sp ما شروع به پایش \fBstdin\fP می‌کنیم. کال‌بک \fBalloc_buffer\fP هنگام نیاز به بافرهای جدید برای نگهداری داده‌های ورودی فراخوانی می‌شود. تابع \fBread_stdin\fP با این بافرها فراخوانی خواهد شد. .sp uvtee/main.c \- خواندن بافرها .INDENT 0.0 .INDENT 3.5 .sp .EX *buf = uv_buf_init((char*) malloc(suggested_size), suggested_size); } void free_write_req(uv_write_t *req) { if (nread < 0){ if (nread == UV_EOF){ // end of file uv_close((uv_handle_t *)&stdin_pipe, NULL); uv_close((uv_handle_t *)&stdout_pipe, NULL); uv_close((uv_handle_t *)&file_pipe, NULL); } } else if (nread > 0) { write_data((uv_stream_t *)&stdout_pipe, nread, *buf, on_stdout_write); write_data((uv_stream_t *)&file_pipe, nread, *buf, on_file_write); } // OK to free buffer as write_data copies it. if (buf\->base) free(buf\->base); } .EE .UNINDENT .UNINDENT .sp تابع استاندارد \fBmalloc\fP در اینجا کافی است، اما می‌توانید از هر روش تخصیص حافظه دیگری استفاده کنید. به عنوان مثال، node.js از تخصیص‌دهنده اسلب (slab allocator) اختصاصی خود استفاده می‌کند که بافرها را با اشیاء V8 مرتبط می‌سازد. .sp پارامتر \fBnread\fP در کال‌بک خواندن در صورت بروز هرگونه خطا کمتر از 0 است. این خطا ممکن است EOF باشد، که در این حالت تمامی استریم‌ها را با استفاده از تابع عمومی \fBuv_close()\fP که بر اساس نوع داخلی هندل با آن رفتار می‌کند، می‌بندیم. در غیر این صورت \fBnread\fP یک عدد غیرمنفی است و می‌توانیم برای نوشتن آن تعداد بایت در استریم‌های خروجی تلاش کنیم. در نهایت به یاد داشته باشید که تخصیص و آزادسازی بافر بر عهده برنامه است، بنابراین ما داده‌ها را آزاد می‌کنیم. .sp کال‌بک تخصیص حافظه ممکن است در صورت عدم موفقیت در تخصیص حافظه، بافری با طول صفر برگرداند. در این حالت، کال‌بک خواندن با خطای UV_ENOBUFS فراخوانی می‌شود. با این حال، libuv به تلاش برای خواندن استریم ادامه می‌دهد، بنابراین اگر می‌خواهید با شکست تخصیص متوقف شوید، باید صراحتاً \fBuv_close()\fP را فراخوانی کنید. .sp کال‌بک خواندن ممکن است با \fBnread = 0\fP فراخوانی شود که نشان می‌دهد در این لحظه داده‌ای برای خواندن وجود ندارد. اکثر برنامه‌ها به سادگی این وضعیت را نادیده می‌گیرند. .sp uvtee/main.c \- نوشتن روی پایپ .INDENT 0.0 .INDENT 3.5 .sp .EX uv_write_t req; uv_buf_t buf; } write_req_t; uv_loop_t *loop; write_req_t *wr = (write_req_t*) req; free(wr\->buf.base); free(wr); } void on_stdout_write(uv_write_t *req, int status) { free_write_req(req); } void on_file_write(uv_write_t *req, int status) { free_write_req(req); } void write_data(uv_stream_t *dest, size_t size, uv_buf_t buf, uv_write_cb cb) { write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t)); req\->buf = uv_buf_init((char*) malloc(size), size); memcpy(req\->buf.base, buf.base, size); uv_write((uv_write_t*) req, (uv_stream_t*)dest, &req\->buf, 1, cb); } .EE .UNINDENT .UNINDENT .sp تابع \fBwrite_data()\fP یک نسخه کپی از بافر به دست آمده از خواندن تهیه می‌کند. این بافر به کال‌بک نوشتن که پس از اتمام نوشتن فعال می‌شود، منتقل نمی‌شود. برای رفع این مشکل، یک درخواست نوشتن و یک بافر را در \fBwrite_req_t\fP بسته‌بندی کرده و در کال‌بک‌ها آن را باز می‌کنیم. ما یک کپی تهیه می‌کنیم تا بتوانیم دو بافر حاصل از دو فراخوانی \fBwrite_data\fP را مستقل از یکدیگر آزاد کنیم. اگرچه این کار برای یک برنامه نمایشی مانند این قابل قبول است، اما در هر برنامه بزرگ احتمالاً به مدیریت حافظه هوشمندانه‌تری مانند بافرهای با شمارش ارجاع یا استخر بافر نیاز خواهید داشت. .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 اگر برنامه شما برای استفاده در کنار برنامه‌های دیگر طراحی شده است، ممکن است دانسته یا ندانسته در حال نوشتن در یک پایپ باشد. این امر آن را در معرض توقف ناگهانی در صورت دریافت سیگنال SIGPIPE قرار می‌دهد \%\&. ایده خوبی است که دستور زیر را: .INDENT 0.0 .INDENT 3.5 .sp .EX signal(SIGPIPE, SIG_IGN) .EE .UNINDENT .UNINDENT .sp در مراحل مقداردهی اولیه برنامه خود قرار دهید. .UNINDENT .UNINDENT .SS رویدادهای تغییر فایل .sp تمامی سیستم‌عامل‌های مدرن APIهایی برای قرار دادن پایشگر روی فایل‌ها یا دایرکتوری‌های مجزا و اطلاع از تغییر فایل‌ها ارائه می‌دهند. کتابخانه libuv کتابخانه‌های رایج اعلان تغییر فایل را بسته‌بندی می‌کند [1]\&. این یکی از ناهمگون‌ترین بخش‌های libuv است. سیستم‌های اعلان تغییر فایل خود در پلتفرم‌های مختلف بسیار متفاوت هستند، بنابراین اجرای روان همه‌چیز در همه جا دشوار است. برای نمایش، یک ابزار ساده می‌سازیم که هر زمان یکی از فایل‌های پایش‌شده تغییر کرد، یک دستور را اجرا کند: .INDENT 0.0 .INDENT 3.5 .sp .EX \&./onchange [file2] ... .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در حال حاضر این مثال فقط در OSX و Windows کار می‌کند. به یادداشت‌های تابع uv_fs_event_start \% مراجعه کنید. .UNINDENT .UNINDENT .sp اعلان تغییر فایل با استفاده از \fBuv_fs_event_init()\fP آغاز می‌شود: .sp onchange/main.c \- آماده‌سازی .INDENT 0.0 .INDENT 3.5 .sp .EX int main(int argc, char **argv) { if (argc <= 2) { fprintf(stderr, \(dqUsage: %s [file2 ...]\en\(dq, argv[0]); return 1; } loop = uv_default_loop(); command = argv[1]; while (argc\-\- > 2) { fprintf(stderr, \(dqAdding watch on %s\en\(dq, argv[argc]); uv_fs_event_t *fs_event_req = malloc(sizeof(uv_fs_event_t)); uv_fs_event_init(loop, fs_event_req); // The recursive flag watches subdirectories too. uv_fs_event_start(fs_event_req, run_command, argv[argc], UV_FS_EVENT_RECURSIVE); } return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp آرگومان سوم، فایل یا دایرکتوری واقعی برای پایش است. آخرین آرگومان، یعنی \fBflags\fP، می‌تواند مقادیر زیر باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX /* * Flags to be passed to uv_fs_event_start(). */ enum uv_fs_event_flags { UV_FS_EVENT_WATCH_ENTRY = 1, UV_FS_EVENT_STAT = 2, UV_FS_EVENT_RECURSIVE = 4 }; .EE .UNINDENT .UNINDENT .sp پرچم‌های \fBUV_FS_EVENT_WATCH_ENTRY\fP و \fBUV_FS_EVENT_STAT\fP (هنوز) کاری انجام نمی‌دهند. پرچم \fBUV_FS_EVENT_RECURSIVE\fP در پلتفرم‌های پشتیبانی‌شده پایش زیردایرکتوری‌ها را نیز آغاز می‌کند. .sp کال‌بک آرگومان‌های زیر را دریافت خواهد کرد: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP 1. 3 \fBuv_fs_event_t *handle\fP \- هندل مربوطه. فیلد \fBpath\fP در هندل، همان فایلی است که پایش روی آن تنظیم شده است. .IP 2. 3 \fBconst char *filename\fP \- اگر یک دایرکتوری در حال پایش باشد، این همان فایلی است که تغییر کرده است. فقط در لینوکس و ویندوز مقداری غیر از \fBnull\fP دارد. حتی در آن پلتفرم‌ها نیز ممکن است \fBnull\fP باشد. .IP 3. 3 \fBint events\fP \- یکی از مقادیر \fBUV_RENAME\fP یا \fBUV_CHANGE\fP، یا عملگر بیتی OR از هر دو. .IP 4. 3 \fBint status\fP \- اگر \fBstatus < 0\fP باشد، یک خطای libuv رخ داده است \%<#\:libuv-error-handling>\&. .UNINDENT .UNINDENT .UNINDENT .sp در مثال خود به سادگی آرگومان‌ها را چاپ کرده و با استفاده از \fBsystem()\fP دستور را اجرا می‌کنیم. .sp onchange/main.c \- کال‌بک اعلان تغییر فایل .INDENT 0.0 .INDENT 3.5 .sp .EX void run_command(uv_fs_event_t *handle, const char *filename, int events, int status) { char path[1024]; size_t size = 1023; // Does not handle error if path is longer than 1023. uv_fs_event_getpath(handle, path, &size); path[size] = \(aq\e0\(aq; fprintf(stderr, \(dqChange detected in %s: \(dq, path); if (events & UV_RENAME) fprintf(stderr, \(dqrenamed\(dq); if (events & UV_CHANGE) fprintf(stderr, \(dqchanged\(dq); fprintf(stderr, \(dq %s\en\(dq, filename ? filename : \(dq\(dq); system(command); } .EE .UNINDENT .UNINDENT .sp .ce ---- .ce 0 .sp .IP [1] 5 سیستم inotify در لینوکس، FSEvents در داروین (Darwin)، سازوکار kqueue در سیستم‌های BSD، تابع ReadDirectoryChangesW در ویندوز، درگاه‌های رویداد (event ports) در سولاریس، و بدون پشتیبانی در Cygwin .IP [2] 5 به بخش ارتباط والد و فرزند \%<#\:pipes> مراجعه کنید .SS شبکه .sp شبکه‌سازی در libuv تفاوت چندانی با استفاده مستقیم از رابط سوکت BSD ندارد؛ برخی موارد ساده‌تر شده‌اند، همه‌چیز غیرمسدودکننده است، اما مفاهیم یکسان باقی می‌مانند. علاوه بر این، libuv توابع کمکی را برای انتزاع وظایف خسته‌کننده، تکراری و سطح پایین مانند راه‌اندازی سوکت‌ها با استفاده از ساختارهای سوکت BSD، جستجوی DNS و تنظیم پارامترهای مختلف سوکت ارائه می‌دهد. .sp ساختارهای \fBuv_tcp_t\fP و \fBuv_udp_t\fP برای ورودی/خروجی شبکه استفاده می‌شوند. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 نمونه کدهای این فصل برای نمایش APIهای خاصی از libuv ارائه شده‌اند. آن‌ها نمونه‌هایی از کدهای باکیفیت نیستند. آن‌ها دچار نشت حافظه هستند و اتصالات را همیشه به درستی نمی‌بندند. .UNINDENT .UNINDENT .SS پروتکل TCP .sp پروتکل TCP یک پروتکل مبتنی بر اتصال و جریانی (stream) است و بنابراین بر پایه زیرساخت استریم‌های libuv بنا شده است. .SS سرور (Server) .sp سوکت‌های سرور مراحل زیر را طی می‌کنند: .INDENT 0.0 .IP 1. 3 هندل TCP را با \fBuv_tcp_init\fP مقداردهی اولیه کنید. .IP 2. 3 آن را با \fBuv_tcp_bind\fP متصل (bind) کنید. .IP 3. 3 تابع \fBuv_listen\fP را روی هندل فراخوانی کنید تا هر زمان اتصال جدیدی توسط کلاینت برقرار شد، یک کال‌بک فراخوانی شود. .IP 4. 3 از \fBuv_accept\fP برای پذیرش اتصال استفاده کنید. .IP 5. 3 از عملیات‌های استریم \%<#\:buffers-and-streams> برای برقراری ارتباط با کلاینت استفاده کنید. .UNINDENT .sp در اینجا یک سرور انعکاس (echo server) ساده آورده شده است: .sp tcp\-echo\-server/main.c \- سوکت شنود .INDENT 0.0 .INDENT 3.5 .sp .EX uv_close((uv_handle_t*) client, on_close); } } int main() { loop = uv_default_loop(); uv_tcp_t server; uv_tcp_init(loop, &server); uv_ip4_addr(\(dq0.0.0.0\(dq, DEFAULT_PORT, &addr); uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0); int r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, on_new_connection); if (r) { fprintf(stderr, \(dqListen error %s\en\(dq, uv_strerror(r)); return 1; } return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp می‌توانید مشاهده کنید که تابع کمکی \fBuv_ip4_addr\fP برای تبدیل یک جفت آدرس IP و پورت خوانا به ساختار sockaddr_in مورد نیاز APIهای سوکت BSD استفاده شده است. عملیات معکوس را می‌توان با استفاده از \fBuv_ip4_name\fP انجام داد. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 توابع معادل \fBuv_ip6_*\fP برای توابع ip4 نیز وجود دارند. .UNINDENT .UNINDENT .sp اکثر توابع راه‌اندازی همگام هستند زیرا وابسته به پردازنده (CPU\-bound) می‌باشند. در تابع \fBuv_listen\fP است که به سبک مبتنی بر کال‌بک libuv بازمی‌گردیم. آرگومان دوم صف backlog است \-\- حداکثر طول اتصالات در صف انتظار. .sp هنگامی که اتصالی توسط کلاینت‌ها آغاز می‌شود، کال‌بک موظف است یک هندل برای سوکت کلاینت تنظیم کند و هندل را با استفاده از \fBuv_accept\fP مرتبط سازد. در این حالت ما همچنین تمایل خود را برای خواندن از این استریم اعلام می‌کنیم. .sp tcp\-echo\-server/main.c \- پذیرش کلاینت .INDENT 0.0 .INDENT 3.5 .sp .EX free(buf\->base); } void on_new_connection(uv_stream_t *server, int status) { if (status < 0) { fprintf(stderr, \(dqNew connection error %s\en\(dq, uv_strerror(status)); // error! return; } uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read); } .EE .UNINDENT .UNINDENT .sp مجموعه توابع باقیمانده بسیار شبیه به مثال استریم‌ها است و می‌توان آن را در کد پیدا کرد. فقط به یاد داشته باشید هنگامی که سوکت دیگر مورد نیاز نیست، \fBuv_close\fP را فراخوانی کنید. این کار را حتی می‌توان در کال‌بک \fBuv_listen\fP انجام داد اگر تمایلی به پذیرش اتصال ندارید. .SS کلاینت (Client) .sp در حالی که در سمت سرور عملیات bind/listen/accept را انجام می‌دهید، در سمت کلاینت کافی است تابع \fBuv_tcp_connect\fP را فراخوانی کنید. همان سبک کال‌بک \fBuv_connect_cb\fP در \fBuv_listen\fP توسط \fBuv_tcp_connect\fP نیز استفاده می‌شود. کد زیر را امتحان کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, socket); uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t)); struct sockaddr_in dest; uv_ip4_addr(\(dq127.0.0.1\(dq, 80, &dest); uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect); .EE .UNINDENT .UNINDENT .sp که در آن \fBon_connect\fP پس از برقراری اتصال فراخوانی خواهد شد. کال‌بک ساختار \fBuv_connect_t\fP را دریافت می‌کند که دارای عضوی به نام \fB\&.handle\fP است که به سوکت اشاره دارد. .SS پروتکل UDP .sp پروتکل دیتاگرام کاربر (User Datagram Protocol) \% ارتباط شبکه‌ای بدون اتصال و غیرقابل اعتمادی را ارائه می‌دهد. بنابراین libuv برای آن یک استریم ارائه نمی‌دهد. در عوض libuv پشتیبانی غیرمسدودکننده UDP را از طریق هندل \fIuv_udp_t\fP (برای دریافت) و درخواست \fIuv_udp_send_t\fP (برای ارسال) و توابع مربوطه فراهم می‌کند. با این حال، رابط واقعی برای خواندن/نوشتن بسیار شبیه به خواندن عادی از استریم است. برای بررسی نحوه استفاده از UDP، مثال زیر اولین مرحله دریافت آدرس IP از سرور DHCP \% را نشان می‌دهد \-\- یعنی مرحله DHCP Discover. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 شما باید برنامه \fIudp\-dhcp\fP را به عنوان \fBroot\fP اجرا کنید زیرا از شماره پورت‌های شناخته‌شده زیر 1024 استفاده می‌کند. .UNINDENT .UNINDENT .sp udp\-dhcp/main.c \- آماده‌سازی و ارسال بسته‌های UDP .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t *loop; uv_udp_t send_socket; uv_udp_t recv_socket; int main() { loop = uv_default_loop(); uv_udp_init(loop, &recv_socket); struct sockaddr_in recv_addr; uv_ip4_addr(\(dq0.0.0.0\(dq, 68, &recv_addr); uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR); uv_udp_recv_start(&recv_socket, alloc_buffer, on_read); uv_udp_init(loop, &send_socket); struct sockaddr_in broadcast_addr; uv_ip4_addr(\(dq0.0.0.0\(dq, 0, &broadcast_addr); uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0); uv_udp_set_broadcast(&send_socket, 1); uv_udp_send_t send_req; uv_buf_t discover_msg = make_discover_msg(); struct sockaddr_in send_addr; uv_ip4_addr(\(dq255.255.255.255\(dq, 67, &send_addr); uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 آدرس IP با مقدار \fB0.0.0.0\fP برای اتصال به تمام رابط‌ها استفاده می‌شود. آدرس IP با مقدار \fB255.255.255.255\fP یک آدرس برودکست (پخش عمومی) است، به این معنی که بسته‌ها به تمام رابط‌های موجود در زیرشبکه ارسال خواهند شد. پورت \fB0\fP به این معنی است که سیستم‌عامل یک پورت را به طور تصادفی اختصاص می‌دهد. .UNINDENT .UNINDENT .sp ابتدا سوکت دریافت‌کننده را تنظیم می‌کنیم تا به تمام رابط‌ها روی پورت 68 (کلاینت DHCP) متصل شود و خواندن روی آن را آغاز می‌کنیم. این کار پاسخ‌های دریافتی از هر سرور DHCP که پاسخ دهد را می‌خواند. ما از پرچم UV_UDP_REUSEADDR استفاده می‌کنیم تا با سایر کلاینت‌های DHCP سیستم که روی همین پورت در رایانه اجرا می‌شوند تداخلی نداشته باشد. سپس یک سوکت ارسال مشابه را تنظیم کرده و از \fBuv_udp_send\fP برای ارسال یک \fIپیام برودکست\fP روی پورت 67 (سرور DHCP) استفاده می‌کنیم. .sp تنظیم پرچم برودکست \fBالزامی\fP است، در غیر این صورت با خطای \fBEACCES\fP مواجه خواهید شد [1]\&. پیام دقیقی که ارسال می‌شود ارتباطی به این کتاب ندارد و در صورت تمایل می‌توانید کد را مطالعه کنید. طبق معمول، کال‌بک‌های خواندن و نوشتن در صورت بروز مشکل، یک کد وضعیت کمتر از 0 دریافت خواهند کرد. .sp از آنجا که سوکت‌های UDP به یک طرف ارتباطی (peer) خاص متصل نیستند، کال‌بک خواندن یک پارامتر اضافی درباره فرستنده بسته دریافت می‌کند. .sp پارامتر \fBnread\fP در صورتی که داده بیشتری برای خواندن وجود نداشته باشد ممکن است صفر باشد. اگر \fBaddr\fP برابر با NULL باشد، نشان می‌دهد چیزی برای خواندن وجود ندارد (کال‌بک نباید کاری انجام دهد)، و اگر NULL نباشد، نشان می‌دهد که یک دیتاگرام خالی از میزبان در \fBaddr\fP دریافت شده است. پارامتر \fBflags\fP در صورتی که بافر ارائه‌شده توسط تخصیص‌دهنده شما به اندازه کافی بزرگ نباشد تا داده‌ها را در خود جای دهد، ممکن است \fBUV_UDP_PARTIAL\fP باشد. \fIدر این حالت، سیستم‌عامل داده‌هایی را که در بافر جا نشده‌اند دور می‌ریزد\fP (این خاصیت UDP است!). .sp udp\-dhcp/main.c \- خواندن بسته‌ها .INDENT 0.0 .INDENT 3.5 .sp .EX void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) { if (nread < 0) { fprintf(stderr, \(dqRead error %s\en\(dq, uv_err_name(nread)); uv_close((uv_handle_t*) req, NULL); free(buf\->base); return; } char sender[17] = { 0 }; uv_ip4_name((const struct sockaddr_in*) addr, sender, 16); fprintf(stderr, \(dqRecv from %s\en\(dq, sender); // ... DHCP specific code unsigned int *as_integer = (unsigned int*)buf\->base; unsigned int ipbin = ntohl(as_integer[4]); unsigned char ip[4] = {0}; int i; for (i = 0; i < 4; i++) ip[i] = (ipbin >> i*8) & 0xff; fprintf(stderr, \(dqOffered IP %d.%d.%d.%d\en\(dq, ip[3], ip[2], ip[1], ip[0]); free(buf\->base); uv_udp_recv_stop(req); } .EE .UNINDENT .UNINDENT .SS گزینه‌های UDP .SS طول عمر بسته (Time\-to\-live) .sp مقدار TTL بسته‌های ارسال‌شده روی سوکت را می‌توان با استفاده از \fBuv_udp_set_ttl\fP تغییر داد. .SS فقط پشته IPv6 .sp سوکت‌های IPv6 را می‌توان هم برای ارتباط IPv4 و هم IPv6 استفاده کرد. اگر می‌خواهید سوکت را فقط به IPv6 محدود کنید، پرچم \fBUV_UDP_IPV6ONLY\fP را به \fBuv_udp_bind\fP ارسال کنید. .SS چندپخشی (Multicast) .sp یک سوکت می‌تواند با استفاده از دستور زیر در یک گروه چندپخشی (multicast) عضو شده یا از آن خارج شود: .sp که در آن \fBmembership\fP برابر با \fBUV_JOIN_GROUP\fP یا \fBUV_LEAVE_GROUP\fP است. .sp مفاهیم چندپخشی به خوبی در این راهنما \% توضیح داده شده است. .sp لوپ‌بک محلی بسته‌های چندپخشی به طور پیش‌فرض فعال است [2]، برای غیرفعال کردن آن از \fBuv_udp_set_multicast_loop\fP استفاده کنید. .sp طول عمر بسته برای بسته‌های چندپخشی را می‌توان با استفاده از \fBuv_udp_set_multicast_ttl\fP تغییر داد. .SS پرس‌وجوی DNS (Querying DNS) .sp کتابخانه libuv امکان تحلیل و تفکیک نام ناهمگام DNS را فراهم می‌کند. برای این منظور، جایگزین اختصاصی \fBgetaddrinfo\fP را ارائه می‌دهد [3]\&. در کال‌بک می‌توانید عملیات معمول سوکت را روی آدرس‌های دریافت شده انجام دهید. بیایید برای مشاهده نمونه‌ای از تحلیل DNS به Libera.chat متصل شویم. .sp dns/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX int main() { loop = uv_default_loop(); struct addrinfo hints; hints.ai_family = PF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = 0; uv_getaddrinfo_t resolver; fprintf(stderr, \(dqirc.libera.chat is... \(dq); int r = uv_getaddrinfo(loop, &resolver, on_resolved, \(dqirc.libera.chat\(dq, \(dq6667\(dq, &hints); if (r) { fprintf(stderr, \(dqgetaddrinfo call error %s\en\(dq, uv_err_name(r)); return 1; } return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp اگر \fBuv_getaddrinfo\fP مقداری غیر از صفر برگرداند، مشکلی در راه‌اندازی رخ داده و کال‌بک شما اصلاً فراخوانی نخواهد شد. تمامی آرگومان‌ها را می‌توان بلافاصله پس از بازگشت \fBuv_getaddrinfo\fP آزاد کرد. ساختارهای \fIhostname\fP، \fIservname\fP و \fIhints\fP در صفحه راهنمای getaddrinfo \% مستند شده‌اند. کال‌بک می‌تواند \fBNULL\fP باشد که در این صورت تابع به صورت همگام اجرا خواهد شد. .sp در کال‌بک تحلیل‌گر، می‌توانید هر IP را از فهرست پیوندی ساختارهای \fBstruct addrinfo(s)\fP انتخاب کنید. این مثال همچنین نحوه استفاده از \fBuv_tcp_connect\fP را نشان می‌دهد. فراخوانی \fBuv_freeaddrinfo\fP در کال‌بک الزامی است. .sp dns/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) { if (status < 0) { fprintf(stderr, \(dqgetaddrinfo callback error %s\en\(dq, uv_err_name(status)); return; } char addr[17] = {\(aq\e0\(aq}; uv_ip4_name((struct sockaddr_in*) res\->ai_addr, addr, 16); fprintf(stderr, \(dq%s\en\(dq, addr); uv_connect_t *connect_req = (uv_connect_t*) malloc(sizeof(uv_connect_t)); uv_tcp_t *socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, socket); uv_tcp_connect(connect_req, socket, (const struct sockaddr*) res\->ai_addr, on_connect); uv_freeaddrinfo(res); } .EE .UNINDENT .UNINDENT .sp کتابخانه libuv همچنین تابع معکوس uv_getnameinfo \% را ارائه می‌دهد. .SS رابط‌های شبکه (Network interfaces) .sp اطلاعات مربوط به رابط‌های شبکه سیستم را می‌توان از طریق libuv با استفاده از \fBuv_interface_addresses\fP به دست آورد. این برنامه ساده فقط تمام جزئیات رابط‌ها را چاپ می‌کند تا با فیلدهای موجود آشنا شوید. این ویژگی برای اینکه به سرویس خود اجازه دهید هنگام شروع به آدرس‌های IP متصل شود مفید است. .sp interfaces/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main() { char buf[512]; uv_interface_address_t *info; int count, i; uv_interface_addresses(&info, &count); i = count; printf(\(dqNumber of interfaces: %d\en\(dq, count); while (i\-\-) { uv_interface_address_t interface_a = info[i]; printf(\(dqName: %s\en\(dq, interface_a.name); printf(\(dqInternal? %s\en\(dq, interface_a.is_internal ? \(dqYes\(dq : \(dqNo\(dq); if (interface_a.address.address4.sin_family == AF_INET) { uv_ip4_name(&interface_a.address.address4, buf, sizeof(buf)); printf(\(dqIPv4 address: %s\en\(dq, buf); } else if (interface_a.address.address4.sin_family == AF_INET6) { uv_ip6_name(&interface_a.address.address6, buf, sizeof(buf)); printf(\(dqIPv6 address: %s\en\(dq, buf); } printf(\(dq\en\(dq); } uv_free_interface_addresses(info, count); return 0; } .EE .UNINDENT .UNINDENT .sp مقدار \fBis_internal\fP برای رابط‌های لوپ‌بک (loopback) برابر با true است. توجه داشته باشید که اگر یک رابط فیزیکی دارای چندین آدرس IPv4/IPv6 باشد، نام آن چندین بار گزارش می‌شود و هر بار یکی از آدرس‌ها گزارش خواهد شد. .sp .ce ---- .ce 0 .sp .IP [1] 5 \% .IP [2] 5 \% .IP [3] 5 کتابخانه libuv از تابع سیستم \fBgetaddrinfo\fP در استخر نخ libuv استفاده می‌کند. نسخه v0.8.0 و نسخه‌های قدیمی‌تر libuv همچنین شامل c\-ares \% به عنوان یک جایگزین بودند، اما این مورد در v0.9.0 حذف شده است. .SS "رشته‌ها (Threads)" .sp یک لحظه صبر کنید! چرا سراغ رشته‌ها رفتیم؟ مگر قرار نبود حلقه‌های رویداد \fBروش اصلی\fP برای \fIبرنامه‌نویسی مقیاس وب (web\-scale programming)\fP باشند؟ خوب... خیر. رشته‌ها همچنان بستری هستند که پردازنده‌ها کارهای خود را در آن انجام می‌دهند. بنابراین رشته‌ها گاهی بسیار مفید هستند، حتی اگر مجبور باشید با سازوکارهای گوناگون همگام‌سازی دست‌وپنجه نرم کنید. .sp رشته‌ها در داخل سیستم برای شبیه‌سازی ماهیت غیرهمگام تمام فراخوان‌های سیستمی استفاده می‌شوند. libuv همچنین با اجرای یک رشته و جمع‌آوری نتیجه پس از پایان کار، به شما (برنامه کاربردی) اجازه می‌دهد وظایفی را که در واقع مسدودکننده (blocking) هستند، به صورت غیرهمگام انجام دهید. .sp امروزه دو کتابخانه اصلی رشته وجود دارد: پیاده‌سازی رشته‌های ویندوز و pthreads(7) در POSIX \%\&. رابط برنامه‌نویسی رشته در libuv مشابه API مربوط به pthreads است و اغلب معناشناسی یکسانی دارد. .sp یک جنبه قابل توجه از امکانات رشته libuv این است که بخشی مستقل در داخل libuv محسوب می‌شود. در حالی که سایر قابلیت‌ها وابستگی نزدیکی به حلقه رویداد و اصول بازخوانی (callback) دارند، رشته‌ها کاملاً مستقل عمل می‌کنند؛ در صورت نیاز مسدود می‌شوند، خطاها را مستقیماً از طریق مقادیر بازگشتی اعلام می‌کنند و همان‌طور که در اولین مثال نشان داده شده است، حتی نیازی به یک حلقه رویداد در حال اجرا ندارند. .sp رابط برنامه‌نویسی رشته libuv همچنین بسیار محدود است، زیرا معناشناسی و نحو رشته‌ها در پلتفرم‌های مختلف متفاوت بوده و سطوح متفاوتی از کامل بودن را دارند. .sp این بخش فرض زیر را در نظر می‌گیرد: \fBتنها یک حلقه رویداد وجود دارد که در یک رشته (رشته اصلی) اجرا می‌شود\fP\&. هیچ رشته دیگری با حلقه رویداد تعامل ندارد (مگر با استفاده از \fBuv_async_send\fP). .SS "عملیات اصلی رشته‌ها (Core thread operations)" .sp در اینجا پیچیدگی خاصی وجود ندارد، فقط یک رشته را با استفاده از \fBuv_thread_create()\fP شروع می‌کنید و با \fBuv_thread_join()\fP منتظر بسته‌شدن آن می‌مانید. .sp thread\-create/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX int tracklen = 10; uv_thread_t hare_id; uv_thread_t tortoise_id; uv_thread_create(&hare_id, hare, &tracklen); uv_thread_create(&tortoise_id, tortoise, &tracklen); uv_thread_join(&hare_id); uv_thread_join(&tortoise_id); return 0; } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 شناسه \fBuv_thread_t\fP در یونیکس صرفاً یک نام مستعار برای \fBpthread_t\fP است، اما این یک جزئیات پیاده‌سازی است و نباید همیشه به آن وابسته باشید. .UNINDENT .UNINDENT .sp پارامتر دوم تابعی است که به عنوان نقطه ورود رشته عمل می‌کند و پارامتر آخر یک آرگومان \fBvoid *\fP است که می‌توان از آن برای ارسال پارامترهای سفارشی به رشته استفاده کرد. تابع \fBhare\fP اکنون در یک رشته جداگانه اجرا می‌شود و زمان‌بندی آن توسط سیستم‌عامل به صورت پیش‌دستانه (pre\-emptively) انجام می‌گیرد: .sp thread\-create/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX int tracklen = *((int *) arg); while (tracklen) { tracklen\-\-; uv_sleep(1000); fprintf(stderr, \(dqHare ran another step\en\(dq); } fprintf(stderr, \(dqHare done running!\en\(dq); } .EE .UNINDENT .UNINDENT .sp برخلاف \fBpthread_join()\fP که به رشته هدف اجازه می‌دهد با استفاده از پارامتر دوم یک مقدار را به رشته فراخوان بازگرداند، \fBuv_thread_join()\fP این کار را انجام نمی‌دهد. برای ارسال مقادیر از بخش ارتباط بین‌رشته‌ای استفاده کنید. .SS "سازوکارهای همگام‌سازی (Synchronization Primitives)" .sp این بخش عمداً مختصر نوشته شده است. این مستند درباره رشته‌ها نیست، بنابراین فقط موارد غیرمنتظره در رابط‌های libuv فهرست شده‌اند. برای سایر موارد می‌توانید به صفحات راهنمای pthreads(7) \% مراجعه کنید. .SS "موتکس‌ها (Mutexes)" .sp توابع موتکس \fBنگاشت مستقیمی\fP به معادل‌های pthread خود دارند. .sp توابع موتکس libuv .INDENT 0.0 .INDENT 3.5 .sp .EX int uv_mutex_init(uv_mutex_t* handle); int uv_mutex_init_recursive(uv_mutex_t* handle); void uv_mutex_destroy(uv_mutex_t* handle); void uv_mutex_lock(uv_mutex_t* handle); int uv_mutex_trylock(uv_mutex_t* handle); void uv_mutex_unlock(uv_mutex_t* handle); .EE .UNINDENT .UNINDENT .sp توابع \fBuv_mutex_init()\fP، \fBuv_mutex_init_recursive()\fP و \fBuv_mutex_trylock()\fP در صورت موفقیت 0 و در غیر این صورت یک کد خطا بازمی‌گردانند. .sp اگر \fIlibuv\fP با فعال بودن خطایابی کامپایل شده باشد، توابع \fBuv_mutex_destroy()\fP، \fBuv_mutex_lock()\fP و \fBuv_mutex_unlock()\fP در صورت بروز خطا تابع \fBabort()\fP را فراخوانی می‌کنند. به طور مشابه، \fBuv_mutex_trylock()\fP در صورتی که خطا چیزی \fIبه‌جز\fP \fBEAGAIN\fP یا \fBEBUSY\fP باشد برنامه را متوقف می‌کند. .sp موتکس‌های بازگشتی (Recursive mutexes) پشتیبانی می‌شوند، اما نباید به آن‌ها وابسته باشید. همچنین، نباید از آن‌ها با متغیرهای \fBuv_cond_t\fP استفاده کرد. .sp پیاده‌سازی پیش‌فرض موتکس BSD اگر رشته‌ای که یک موتکس را قفل کرده دوباره تلاش کند آن را قفل کند، خطا ایجاد می‌کند. به عنوان مثال، ساختاری مانند: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_mutex_init(a_mutex); uv_mutex_lock(a_mutex); uv_thread_create(thread_id, entry, (void *)a_mutex); uv_mutex_lock(a_mutex); // more things here .EE .UNINDENT .UNINDENT .sp می‌تواند برای انتظار تا زمانی که رشته دیگر مواردی را مقداردهی کرده و سپس \fBa_mutex\fP را باز کند استفاده شود، اما در حالت اشکال‌زدایی (debug) باعث کرش برنامه شده یا در فراخوانی دوم \fBuv_mutex_lock()\fP خطا بازمی‌گرداند. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 موتکس‌ها در ویندوز همیشه بازگشتی هستند. .UNINDENT .UNINDENT .SS "قفل‌ها (Locks)" .sp قفل‌های خواندن\-نوشتن (Read\-write locks) سازوکار دسترسی دقیق‌تری هستند. دو خواننده می‌توانند همزمان به حافظه مشترک دسترسی داشته باشند. یک نویسنده نمی‌تواند قفلی را که در اختیار یک خواننده است دریافت کند. یک خواننده یا نویسنده نمی‌تواند قفلی را که در اختیار یک نویسنده است دریافت کند. قفل‌های خواندن\-نوشتن مکرراً در پایگاه‌های داده استفاده می‌شوند. در اینجا یک مثال ساده آورده شده است. .sp locks/main.c \- قفل‌های rwlock ساده .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include uv_barrier_t blocker; uv_rwlock_t numlock; int shared_num; void reader(void *n) { int num = *(int *)n; int i; for (i = 0; i < 20; i++) { uv_rwlock_rdlock(&numlock); printf(\(dqReader %d: acquired lock\en\(dq, num); printf(\(dqReader %d: shared num = %d\en\(dq, num, shared_num); uv_rwlock_rdunlock(&numlock); printf(\(dqReader %d: released lock\en\(dq, num); } uv_barrier_wait(&blocker); } void writer(void *n) { int num = *(int *)n; int i; for (i = 0; i < 20; i++) { uv_rwlock_wrlock(&numlock); printf(\(dqWriter %d: acquired lock\en\(dq, num); shared_num++; printf(\(dqWriter %d: incremented shared num = %d\en\(dq, num, shared_num); uv_rwlock_wrunlock(&numlock); printf(\(dqWriter %d: released lock\en\(dq, num); } uv_barrier_wait(&blocker); } int main() { uv_barrier_init(&blocker, 4); shared_num = 0; uv_rwlock_init(&numlock); uv_thread_t threads[3]; int thread_nums[] = {1, 2, 1}; uv_thread_create(&threads[0], reader, &thread_nums[0]); uv_thread_create(&threads[1], reader, &thread_nums[1]); uv_thread_create(&threads[2], writer, &thread_nums[2]); uv_barrier_wait(&blocker); uv_barrier_destroy(&blocker); uv_rwlock_destroy(&numlock); return 0; } .EE .UNINDENT .UNINDENT .sp این برنامه را اجرا کنید و ببینید چگونه خواننده‌ها گاهی با یکدیگر همپوشانی دارند. در صورت وجود چندین نویسنده، زمان‌بندها معمولاً اولویت بالاتری به آن‌ها می‌دهند، بنابراین اگر دو نویسنده اضافه کنید، خواهید دید که هر دو نویسنده تمایل دارند ابتدا کار خود را به پایان برسانند قبل از اینکه دوباره به خواننده‌ها فرصتی داده شود. .sp ما همچنین در مثال بالا از موانع (barriers) استفاده می‌کنیم تا رشته اصلی بتواند منتظر بماند تا همه خواننده‌ها و نویسنده‌ها اتمام کار خود را اعلام کنند. .SS "سایر موارد (Others)" .sp کتابخانه libuv همچنین از سمافورها (semaphores) \%، متغیرهای شرطی (condition variables) \% و موانع (barriers) \% با رابط‌هایی بسیار مشابه معادل‌های pthread پشتیبانی می‌کند. .sp علاوه بر این، libuv تابع کمکی \fBuv_once()\fP را ارائه می‌دهد. چندین رشته می‌توانند با یک گارد مشخص و یک اشاره‌گر تابع اقدام به فراخوانی \fBuv_once()\fP کنند؛ \fBفقط اولین فراخوانی برنده خواهد شد و تابع تنها و تنها یک بار فراخوانی می‌شود\fP: .INDENT 0.0 .INDENT 3.5 .sp .EX /* Initialize guard */ static uv_once_t once_only = UV_ONCE_INIT; int i = 0; void increment() { i++; } void thread1() { /* ... work */ uv_once(once_only, increment); } void thread2() { /* ... work */ uv_once(once_only, increment); } int main() { /* ... spawn threads */ } .EE .UNINDENT .UNINDENT .sp پس از اتمام تمام رشته‌ها، مقدار \fBi == 1\fP خواهد بود. .sp از نسخه v0.11.11 به بعد libuv ساختار و API جدیدی به نام \fBuv_key_t\fP \% برای حافظه محلی رشته (thread\-local storage) اضافه کرده است. .SS "صف کار libuv (libuv work queue)" .sp تابع \fBuv_queue_work()\fP یک تابع کمکی است که به برنامه اجازه می‌دهد وظیفه‌ای را در یک رشته جداگانه اجرا کند و پس از اتمام کار، بازخوانی مربوطه فراخوانی شود. یک تابع به ظاهر ساده، آنچه \fBuv_queue_work()\fP را جذاب می‌کند این است که اجازه می‌دهد به طور بالقوه هر کتابخانه شخص ثالثی با الگوی حلقه رویداد استفاده شود. وقتی از حلقه‌های رویداد استفاده می‌کنید، \fIضروری است مطمئن شوید هیچ تابعی که به صورت دوره‌ای در رشته حلقه اجرا می‌شود، هنگام انجام I/O مسدود نشده و مصرف سنگین CPU نداشته باشد\fP، زیرا این امر باعث کند شدن حلقه شده و رویدادها با حداکثر ظرفیت پردازش نمی‌شوند. .sp با این حال، بسیاری از کدهای موجود دارای توابع مسدودکننده هستند (برای مثال روالی که در پس‌زمینه I/O انجام می‌دهد) که در صورت تمایل به پاسخ‌گویی سریع باید با رشته‌ها استفاده شوند (مدل سرور کلاسیک «یک رشته به ازای هر کلاینت»)، و هماهنگ کردن آن‌ها با یک کتابخانه حلقه رویداد معمولاً نیازمند پیاده‌سازی سیستم اختصاصی برای اجرای وظیفه در رشته‌ای جداگانه است. libuv یک انتزاع مناسب برای این منظور ارائه می‌دهد. .sp در اینجا یک مثال ساده با الهام از node.js is cancer \% آورده شده است. ما می‌خواهیم اعداد فیبوناچی را محاسبه کنیم، در این مسیر کمی توقف (sleep) داشته باشیم، اما آن را در یک رشته جداگانه اجرا کنیم تا وظیفه مسدودکننده و وابسته به پردازنده مانع انجام سایر فعالیت‌های حلقه رویداد نشود. .sp queue\-work/main.c \- فیبوناچی تنبل .INDENT 0.0 .INDENT 3.5 .sp .EX void fib(uv_work_t *req) { int n = *(int *) req\->data; if (random() % 2) sleep(1); else sleep(3); long fib = fib_(n); fprintf(stderr, \(dq%dth fibonacci is %lu\en\(dq, n, fib); } void after_fib(uv_work_t *req, int status) { fprintf(stderr, \(dqDone calculating %dth fibonacci\en\(dq, *(int *) req\->data); } .EE .UNINDENT .UNINDENT .sp تابع وظیفه واقعی ساده است و هیچ نشانه‌ای از اجرای آن در یک رشته جداگانه وجود ندارد. ساختار \fBuv_work_t\fP کلید این کار است. می‌توانید داده‌های دلخواه را از طریق فیلد \fBvoid* data\fP به آن ارسال کنید و از آن برای ارتباط به رشته و از رشته استفاده کنید. اما مطمئن شوید در صورتی که داده‌ها هنگام اجرای همزمان هر دو رشته تغییر می‌کنند، از قفل‌های مناسب استفاده می‌کنید. .sp محرک اجرا \fBuv_queue_work\fP است: .sp queue\-work/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX int main() { loop = uv_default_loop(); int data[FIB_UNTIL]; uv_work_t req[FIB_UNTIL]; int i; for (i = 0; i < FIB_UNTIL; i++) { data[i] = i; req[i].data = (void *) &data[i]; uv_queue_work(loop, &req[i], fib, after_fib); } return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp تابع رشته در یک رشته جداگانه راه‌اندازی شده و ساختار \fBuv_work_t\fP به آن ارسال می‌شود و پس از بازگشت تابع، تابع \fIafter\fP در رشته‌ای که حلقه رویداد در آن اجرا می‌شود فراخوانی خواهد شد. همان ساختار به آن ارسال می‌شود. .sp برای نوشتن رَپرها (wrappers) برای کتابخانه‌های مسدودکننده، یک الگوی متداول \%<#\:baton> استفاده از باتوم (baton) برای تبادل داده است. .sp از نسخه \fI0.9.4\fP کتابخانه libuv یک تابع اضافی به نام \fBuv_cancel()\fP در دسترس قرار گرفته است. این تابع به شما امکان می‌دهد وظایف موجود در صف کار libuv را لغو کنید. فقط وظایفی که \fIهنوز شروع نشده‌اند\fP قابل لغو هستند. اگر وظیفه‌ای \fIقبلاً اجرای خود را آغاز کرده باشد یا اجرای آن پایان یافته باشد\fP، تابع \fBuv_cancel()\fP \fBشکست خواهد خورد\fP\&. .sp تابع \fBuv_cancel()\fP برای پاک‌سازی وظایف در انتظار در صورت درخواست پایان برنامه توسط کاربر بسیار مفید است. به عنوان مثال، یک پخش‌کننده موسیقی ممکن است چندین پوشه را برای اسکن فایل‌های صوتی در صف قرار دهد. اگر کاربر برنامه را متوقف کند، برنامه باید فوراً خارج شود و منتظر اجرای تمام درخواست‌های در صف نماند. .sp بیایید مثال فیبوناچی را برای نمایش عملکرد \fBuv_cancel()\fP تغییر دهیم. ابتدا یک گرداننده سیگنال برای خاتمه برنامه تنظیم می‌کنیم. .sp queue\-cancel/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX int main() { loop = uv_default_loop(); int data[FIB_UNTIL]; int i; for (i = 0; i < FIB_UNTIL; i++) { data[i] = i; fib_reqs[i].data = (void *) &data[i]; uv_queue_work(loop, &fib_reqs[i], fib, after_fib); } uv_signal_t sig; uv_signal_init(loop, &sig); uv_signal_start(&sig, signal_handler, SIGINT); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp هنگامی که کاربر با فشردن کلیدهای \fBCtrl+C\fP سیگنال را ارسال می‌کند، ما \fBuv_cancel()\fP را به تمام کارگران (workers) ارسال می‌کنیم. تابع \fBuv_cancel()\fP برای وظایفی که در انتظار اجرا هستند و لغو شده‌اند مقدار \fB0\fP را بازمی‌گرداند. .sp queue\-cancel/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void signal_handler(uv_signal_t *req, int signum) { printf(\(dqSignal received!\en\(dq); int i; for (i = 0; i < FIB_UNTIL; i++) { uv_cancel((uv_req_t*) &fib_reqs[i]); } uv_signal_stop(req); } .EE .UNINDENT .UNINDENT .sp برای وظایفی که با موفقیت لغو می‌شوند، تابع \fIafter\fP با مقدار \fBstatus\fP برابر با \fBUV_ECANCELED\fP فراخوانی می‌شود. .sp queue\-cancel/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void after_fib(uv_work_t *req, int status) { if (status == UV_ECANCELED) fprintf(stderr, \(dqCalculation of %d cancelled.\en\(dq, *(int *) req\->data); } .EE .UNINDENT .UNINDENT .sp تابع \fBuv_cancel()\fP همچنین می‌تواند با درخواست‌های \fBuv_fs_t\fP و \fBuv_getaddrinfo_t\fP استفاده شود. برای خانواده توابع سیستم فایل، مقدار \fBuv_fs_t.errorno\fP روی \fBUV_ECANCELED\fP تنظیم خواهد شد. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 یک برنامه با طراحی مناسب روشی برای پایان دادن به کارگرانی که مدت زیادی در حال اجرا بوده‌اند و اجرای آن‌ها از قبل آغاز شده است خواهد داشت. چنین کارگری می‌تواند به صورت دوره‌ای متغیری را بررسی کند که فقط فرایند اصلی برای اعلام پایان تنظیم می‌کند. .UNINDENT .UNINDENT .SS "ارتباط بین‌رشته‌ای (Inter\-thread communication)" .sp گاهی اوقات می‌خواهید رشته‌های مختلف \fIهنگام اجرا\fP پیام‌هایی برای یکدیگر ارسال کنند. برای مثال ممکن است در حال اجرای یک وظیفه طولانی در یک رشته جداگانه باشید (شاید با استفاده از \fBuv_queue_work\fP) اما بخواهید پیشرفت کار را به رشته اصلی اطلاع دهید. این یک مثال ساده از یک مدیر دانلود است که وضعیت دانلودهای در حال اجرا را به کاربر اطلاع می‌دهد. .sp progress/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t *loop; uv_async_t async; int main() { loop = uv_default_loop(); uv_work_t req; int size = 10240; req.data = (void*) &size; uv_async_init(loop, &async, print_progress); uv_queue_work(loop, &req, fake_download, after); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp ارتباط رشته‌ای غیرهمگام \fBروی حلقه‌ها\fP کار می‌کند، بنابراین با اینکه هر رشته‌ای می‌تواند فرستنده پیام باشد، فقط رشته‌هایی که دارای حلقه‌های libuv هستند می‌توانند گیرنده باشند (یا بهتر بگوییم، خود حلقه گیرنده است). libuv هر زمان پیامی دریافت کند، بازخوانی (\fBprint_progress\fP) را با پایشگر ناهمگام فراخوانی می‌کند. .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 بسیار مهم است بدانید از آنجا که ارسال پیام \fIغیرهمگام\fP است، بازخوانی ممکن است بلافاصله پس از فراخوانی \fBuv_async_send\fP در رشته دیگر اجرا شود، یا ممکن است پس از گذشت مدتی فراخوانی گردد. همچنین ممکن است libuv چندین فراخوانی به \fBuv_async_send\fP را ترکیب کند و بازخوانی شما را فقط یک بار فراخوانی نماید. تنها تضمینی که libuv می‌دهد این است: تابع بازخوانی \fIحداقل یک بار\fP پس از فراخوانی \fBuv_async_send\fP فراخوانی می‌شود. اگر هیچ فراخوانی معوقی به \fBuv_async_send\fP نداشته باشید، بازخوانی اجرا نخواهد شد. اگر دو یا چند فراخوانی انجام دهید و libuv هنوز فرصت اجرای بازخوانی را پیدا نکرده باشد، \fIممکن است\fP بازخوانی شما را برای چندین فراخوانی \fBuv_async_send\fP \fIفقط یک بار\fP اجرا کند. بازخوانی شما هرگز دو بار برای یک رویداد اجرا نخواهد شد. .UNINDENT .UNINDENT .sp progress/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX double percentage; void fake_download(uv_work_t *req) { int size = *((int*) req\->data); int downloaded = 0; while (downloaded < size) { percentage = downloaded*100.0/size; async.data = (void*) &percentage; uv_async_send(&async); sleep(1); downloaded += (200+random())%1000; // can only download max 1000bytes/sec, // but at least a 200; } } .EE .UNINDENT .UNINDENT .sp در تابع دانلود، ما شاخص پیشرفت را تغییر می‌دهیم و پیام را برای تحویل با \fBuv_async_send\fP در صف قرار می‌دهیم. به یاد داشته باشید: \fBuv_async_send\fP نیز غیرمسدودکننده است و فوراً بازمی‌گردد. .sp progress/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void print_progress(uv_async_t *handle) { double percentage = *((double*) handle\->data); fprintf(stderr, \(dqDownloaded %.2f%%\en\(dq, percentage); } .EE .UNINDENT .UNINDENT .sp تابع بازخوانی یک الگوی استاندارد در libuv است که داده‌ها را از پایشگر استخراج می‌کند. .sp در نهایت، بسیار مهم است که پاک‌سازی پایشگر را فراموش نکنید. .sp progress/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void after(uv_work_t *req, int status) { fprintf(stderr, \(dqDownload complete\en\(dq); uv_close((uv_handle_t*) &async, NULL); } .EE .UNINDENT .UNINDENT .sp پس از این مثال که استفاده نادرست از فیلد \fBdata\fP را نشان داد، bnoordhuis \% اشاره کرد که استفاده از فیلد \fBdata\fP امن در برابر رشته‌ها (thread safe) نیست و \fBuv_async_send()\fP در واقع فقط برای بیدار کردن حلقه رویداد در نظر گرفته شده است. از یک موتکس یا rwlock استفاده کنید تا مطمئن شوید دسترسی‌ها با ترتیب صحیح انجام می‌شوند. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 موتکس‌ها و rwlockها در داخل گرداننده سیگنال \fBکار نمی‌کنند\fP، در حالی که \fBuv_async_send\fP کار می‌کند. .UNINDENT .UNINDENT .sp یک مورد استفاده که در آن \fBuv_async_send\fP الزامی است، زمان تعامل با کتابخانه‌هایی است که برای عملکرد خود به پیوستگی رشته‌ای (thread affinity) نیاز دارند. برای مثال در node.js، یک نمونه موتور v8، کانتکست‌ها و اشیای آن به رشته‌ای که نمونه v8 در آن راه‌اندازی شده مقید هستند. تعامل با ساختارهای داده v8 از یک رشته دیگر می‌تواند منجر به نتایج تعریف‌نشده شود. اکنون یک ماژول node.js را در نظر بگیرید که یک کتابخانه شخص ثالث را متصل می‌کند. روند ممکن است به صورت زیر باشد: .INDENT 0.0 .IP 1. 3 در node، کتابخانه شخص ثالث با یک بازخوانی جاوااسکریپت تنظیم می‌شود تا برای دریافت اطلاعات بیشتر فراخوانی شود: .INDENT 3.0 .INDENT 3.5 .sp .EX var lib = require(\(aqlib\(aq); lib.on_progress(function() { console.log(\(dqProgress\(dq); }); lib.do(); // do other stuff .EE .UNINDENT .UNINDENT .IP 2. 3 تابع \fBlib.do\fP قرار است غیرمسدودکننده باشد اما کتابخانه شخص ثالث مسدودکننده است، بنابراین بایندینگ از \fBuv_queue_work\fP استفاده می‌کند. .IP 3. 3 کار واقعی انجام‌شده در یک رشته جداگانه می‌خواهد بازخوانی پیشرفت را اجرا کند، اما نمی‌تواند مستقیماً با v8 برای تعامل با جاوااسکریپت ارتباط برقرار کند. بنابراین از \fBuv_async_send\fP استفاده می‌کند. .IP 4. 3 بازخوانی ناهمگام که در رشته حلقه اصلی (که همان رشته v8 است) اجرا می‌شود، سپس با v8 تعامل برقرار کرده تا بازخوانی جاوااسکریپت را فراخوانی کند. .UNINDENT .sp .ce ---- .ce 0 .sp .SS "فرایندها (Processes)" .sp کتابخانه libuv امکانات قابل توجهی برای مدیریت فرایندهای فرزند ارائه می‌دهد و تفاوت‌های پلتفرم‌ها را انتزاع کرده و ارتباط با فرایند فرزند را با استفاده از جریان‌ها (streams) یا پایپ‌های نام‌گذاری‌شده فراهم می‌کند. .sp یک اصطلاح رایج در یونیکس این است که هر فرایند یک کار را انجام دهد و آن را به خوبی انجام دهد. در چنین حالتی، یک فرایند اغلب از چندین فرایند فرزند برای انجام وظایف استفاده می‌کند (مشابه استفاده از پایپ‌ها در شل). یک مدل چندفرایندی همراه با پیام‌ها نیز ممکن است در مقایسه با مدلی با رشته‌ها و حافظه مشترک، تحلیل و درک آسان‌تری داشته باشد. .sp یک انتقاد رایج علیه برنامه‌های مبتنی بر رویداد این است که نمی‌توانند از چندین هسته در کامپیوترهای مدرن بهره ببرند. در یک برنامه چندرشته‌ای، هسته سیستم‌عامل می‌تواند زمان‌بندی را انجام داده و رشته‌های مختلف را به هسته‌های مختلف اختصاص دهد و کارایی را افزایش دهد. اما یک حلقه رویداد فقط یک رشته دارد. راه‌حل جایگزین می‌تواند راه‌اندازی چندین فرایند باشد، به‌طوری‌که هر فرایند یک حلقه رویداد را اجرا کرده و به یک هسته پردازنده جداگانه اختصاص یابد. .SS "ایجاد فرایندهای فرزند (Spawning child processes)" .sp ساده‌ترین حالت زمانی است که صرفاً می‌خواهید یک فرایند را اجرا کرده و از زمان خروج آن مطلع شوید. این کار با استفاده از \fBuv_spawn\fP انجام می‌شود. .sp spawn/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t *loop; uv_process_t child_req; uv_process_options_t options; int main() { loop = uv_default_loop(); char* args[3]; args[0] = \(dqmkdir\(dq; args[1] = \(dqtest\-dir\(dq; args[2] = NULL; options.exit_cb = on_exit; options.file = \(dqmkdir\(dq; options.args = args; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, \(dq%s\en\(dq, uv_strerror(r)); return 1; } else { fprintf(stderr, \(dqLaunched process with ID %d\en\(dq, child_req.pid); } return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 متغیر \fBoptions\fP به دلیل سراسری بودن، به طور ضمنی با صفر مقداردهی اولیه می‌شود. اگر \fBoptions\fP را به یک متغیر محلی تغییر دادید، به یاد داشته باشید که تمام فیلدهای بدون استفاده آن را با صفر مقداردهی کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_process_options_t options = {0}; .EE .UNINDENT .UNINDENT .UNINDENT .UNINDENT .sp ساختار \fBuv_process_t\fP فقط به عنوان هندل عمل می‌کند و تمام گزینه‌ها از طریق \fBuv_process_options_t\fP تنظیم می‌شوند. برای اجرای ساده یک فرایند، فقط باید فیلدهای \fBfile\fP و \fBargs\fP را تنظیم کنید. فیلد \fBfile\fP برنامه‌ای است که باید اجرا شود. از آنجا که \fBuv_spawn\fP در داخل از execvp(3) \% استفاده می‌کند، نیازی به ارائه مسیر کامل نیست. در نهایت طبق قراردادهای بنیادین، \fBطول آرایه آرگومان‌ها باید یکی بیشتر از تعداد آرگومان‌ها باشد و آخرین عنصر آن برابر با NULL قرار گیرد\fP\&. .sp پس از فراخوانی \fBuv_spawn\fP، فیلد \fBuv_process_t.pid\fP حاوی شناسه فرایند (PID) فرزند خواهد بود. .sp بازخوانی خروج با \fIوضعیت خروج\fP و نوع \fIسیگنالی\fP که باعث خروج شده فراخوانی خواهد شد. .sp توجه داشته باشید که بسیار مهم است \fBقبل از\fP اجرای بازخوانی خروج، تابع \fBuv_close\fP را فراخوانی \fBنکنید\fP. .sp spawn/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void on_exit(uv_process_t *req, int64_t exit_status, int term_signal) { fprintf(stderr, \(dqProcess exited with status %\(dq PRId64 \(dq, signal %d\en\(dq, exit_status, term_signal); uv_close((uv_handle_t*) req, NULL); .EE .UNINDENT .UNINDENT .sp بستن پایشگر فرایند پس از خروج فرایند \fBالزامی\fP است. .SS "تغییر پارامترهای فرایند (Changing process parameters)" .sp قبل از اجرای فرایند فرزند می‌توانید محیط اجرای آن را با استفاده از فیلدهای موجود در \fBuv_process_options_t\fP کنترل کنید. .SS "تغییر دایرکتوری اجرا (Change execution directory)" .sp فیلد \fBuv_process_options_t.cwd\fP را روی دایرکتوری مربوطه تنظیم کنید. .SS "تنظیم متغیرهای محیطی (Set environment variables)" .sp فیلد \fBuv_process_options_t.env\fP یک آرایه رشته‌ای پایان‌یافته با null است که هر عنصر آن به شکل \fBVAR=VALUE\fP برای تنظیم متغیرهای محیطی فرایند استفاده می‌شود. برای به ارث بردن محیط از فرایند والد (این فرایند)، آن را برابر \fBNULL\fP قرار دهید. .SS "فلگ‌های گزینه‌ها (Option flags)" .sp تنظیم \fBuv_process_options_t.flags\fP با عملگر بیتی OR از فلگ‌های زیر، رفتار فرایند فرزند را تغییر می‌دهد: .INDENT 0.0 .IP \(bu 2 \fBUV_PROCESS_SETUID\fP \- شناسه کاربر اجرای فرزند را روی \fBuv_process_options_t.uid\fP تنظیم می‌کند. .IP \(bu 2 \fBUV_PROCESS_SETGID\fP \- شناسه گروه اجرای فرزند را روی \fBuv_process_options_t.gid\fP تنظیم می‌کند. .UNINDENT .sp تغییر UID/GID فقط در یونیکس پشتیبانی می‌شود و \fBuv_spawn\fP در ویندوز با خطای \fBUV_ENOTSUP\fP شکست خواهد خورد. .INDENT 0.0 .IP \(bu 2 \fBUV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS\fP \- در ویندوز هیچ‌گونه کوتیشن یا اسکیپ کردنی روی \fBuv_process_options_t.args\fP اعمال نمی‌شود. در یونیکس نادیده گرفته می‌شود. .IP \(bu 2 \fBUV_PROCESS_DETACHED\fP \- فرایند فرزند را در یک سشن (session) جدید راه‌اندازی می‌کند که پس از خروج فرایند والد به اجرای خود ادامه خواهد داد. مثال زیر را ببینید. .UNINDENT .SS "جدا کردن فرایندها (Detaching processes)" .sp ارسال فلگ \fBUV_PROCESS_DETACHED\fP می‌تواند برای راه‌اندازی دیمون‌ها (daemons) یا فرایندهای فرزندی که مستقل از والد هستند استفاده شود تا خروج والد تأثیری روی آن‌ها نداشته باشد. .sp detach/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX int main() { loop = uv_default_loop(); char* args[3]; args[0] = \(dqsleep\(dq; args[1] = \(dq100\(dq; args[2] = NULL; options.exit_cb = NULL; options.file = \(dqsleep\(dq; options.args = args; options.flags = UV_PROCESS_DETACHED; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, \(dq%s\en\(dq, uv_strerror(r)); return 1; } fprintf(stderr, \(dqLaunched sleep with PID %d\en\(dq, child_req.pid); uv_unref((uv_handle_t*) &child_req); return uv_run(loop, UV_RUN_DEFAULT); .EE .UNINDENT .UNINDENT .sp فقط به یاد داشته باشید که هندل همچنان در حال نظارت بر فرزند است، بنابراین برنامه شما خارج نخواهد شد. اگر می‌خواهید رویکرد \fIاجرا کن و رها کن (fire\-and\-forget)\fP داشته باشید، از \fBuv_unref()\fP استفاده کنید. .SS "ارسال سیگنال به فرایندها (Sending signals to processes)" .sp کتابخانه libuv فراخوان سیستمی استاندارد \fBkill(2)\fP را در یونیکس پوشش داده و رفتاری مشابه در ویندوز پیاده‌سازی می‌کند، البته با \fIیک نکته مهم\fP: تمام سیگنال‌های \fBSIGTERM\fP، \fBSIGINT\fP و \fBSIGKILL\fP منجر به خاتمه فرایند می‌شوند. امضای تابع \fBuv_kill\fP به صورت زیر است: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_err_t uv_kill(int pid, int signum); .EE .UNINDENT .UNINDENT .sp برای فرایندهایی که با استفاده از libuv شروع شده‌اند، می‌توانید به جای آن از \fBuv_process_kill\fP استفاده کنید که به جای pid، پایشگر \fBuv_process_t\fP را به عنوان آرگومان اول می‌پذیرد. در این حالت، \fBبه یاد داشته باشید\fP که \fBuv_close\fP را روی پایشگر _پس از_ فراخوانی بازخوانی خروج صدا بزنید. .SS "سیگنال‌ها (Signals)" .sp کتابخانه libuv رَپرهایی را در کنار برخی پشتیبانی‌ها از ویندوز \% برای سیگنال‌های یونیکس فراهم می‌کند. .sp از \fBuv_signal_init()\fP برای مقداردهی اولیه یک هندل و مرتبط کردن آن با یک حلقه استفاده کنید. برای گوش دادن به سیگنال‌های خاص در آن هندلر، از \fBuv_signal_start()\fP به همراه تابع گرداننده استفاده کنید. هر گرداننده فقط می‌تواند با یک شماره سیگنال مرتبط باشد و فراخوانی‌های بعدی به \fBuv_signal_start()\fP ارتباط‌های قبلی را بازنویسی می‌کنند. از \fBuv_signal_stop()\fP برای توقف نظارت استفاده کنید. در اینجا یک مثال کوچک برای نمایش حالات مختلف آورده شده است: .sp signal/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include #include uv_loop_t* create_loop() { uv_loop_t *loop = malloc(sizeof(uv_loop_t)); if (loop) { uv_loop_init(loop); } return loop; } void signal_handler(uv_signal_t *handle, int signum) { printf(\(dqSignal received: %d\en\(dq, signum); uv_signal_stop(handle); } // two signal handlers in one loop void thread1_worker(void *userp) { uv_loop_t *loop1 = create_loop(); uv_signal_t sig1a, sig1b; uv_signal_init(loop1, &sig1a); uv_signal_start(&sig1a, signal_handler, SIGUSR1); uv_signal_init(loop1, &sig1b); uv_signal_start(&sig1b, signal_handler, SIGUSR1); uv_run(loop1, UV_RUN_DEFAULT); } // two signal handlers, each in its own loop void thread2_worker(void *userp) { uv_loop_t *loop2 = create_loop(); uv_loop_t *loop3 = create_loop(); uv_signal_t sig2; uv_signal_init(loop2, &sig2); uv_signal_start(&sig2, signal_handler, SIGUSR1); uv_signal_t sig3; uv_signal_init(loop3, &sig3); uv_signal_start(&sig3, signal_handler, SIGUSR1); while (uv_run(loop2, UV_RUN_NOWAIT) || uv_run(loop3, UV_RUN_NOWAIT)) { } } int main() { printf(\(dqPID %d\en\(dq, getpid()); uv_thread_t thread1, thread2; uv_thread_create(&thread1, thread1_worker, 0); uv_thread_create(&thread2, thread2_worker, 0); uv_thread_join(&thread1); uv_thread_join(&thread2); return 0; } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 تابع \fBuv_run(loop, UV_RUN_NOWAIT)\fP شبیه به \fBuv_run(loop, UV_RUN_ONCE)\fP است از این جهت که فقط یک رویداد را پردازش می‌کند. حالت UV_RUN_ONCE در صورت عدم وجود رویدادهای در انتظار مسدود می‌شود، در حالی که UV_RUN_NOWAIT فوراً بازمی‌گردد. ما از NOWAIT استفاده می‌کنیم تا یکی از حلقه‌ها به دلیل عدم وجود فعالیت معوق در حلقه دیگر دچار گرسنگی (starvation) نشود. .UNINDENT .UNINDENT .sp سیگنال \fBSIGUSR1\fP را به فرایند ارسال کنید، خواهید دید که هندلر ۴ بار اجرا می‌شود، یک بار برای هر \fBuv_signal_t\fP\&. هندلر به سادگی هر هندل را متوقف می‌کند تا برنامه خارج شود. این نوع توزیع پیام به همه هندلرها بسیار مفید است. سروری که از چندین حلقه رویداد استفاده می‌کند می‌تواند اطمینان حاصل کند که همه داده‌ها قبل از خاتمه با امنیت ذخیره می‌شوند، صرفاً با افزودن یک پایشگر برای \fBSIGINT\fP به هر حلقه. .SS "ورودی/خروجی فرایند فرزند (Child Process I/O)" .sp یک فرایند معمولی و تازه ایجادشده دارای مجموعه توصیف‌کننده‌های فایل اختصاصی خود است که 0، 1 و 2 به ترتیب \fBstdin\fP، \fBstdout\fP و \fBstderr\fP هستند. گاهی اوقات ممکن است بخواهید توصیف‌کننده‌های فایل را با فرزند به اشتراک بگذارید. برای مثال، شاید برنامه شما یک زیردستور را اجرا می‌کند و می‌خواهید هرگونه خطا در فایل لاگ ثبت شود، اما \fBstdout\fP نادیده گرفته شود. برای این منظور می‌خواهید \fBstderr\fP فرزند همانند stderr والد باشد. در این حالت، libuv از \fIبه ارث بردن\fP توصیف‌کننده‌های فایل پشتیبانی می‌کند. در این نمونه، برنامه آزمایشی زیر را فراخوانی می‌کنیم: .sp proc\-streams/test.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main() { fprintf(stderr, \(dqThis is stderr\en\(dq); printf(\(dqThis is stdout\en\(dq); return 0; } .EE .UNINDENT .UNINDENT .sp برنامه واقعی \fBproc\-streams\fP این کد را اجرا می‌کند در حالی که فقط \fBstderr\fP را به اشتراک می‌گذارد. توصیف‌کننده‌های فایل فرایند فرزند با استفاده از فیلد \fBstdio\fP در \fBuv_process_options_t\fP تنظیم می‌شوند. ابتدا فیلد \fBstdio_count\fP را روی تعداد توصیف‌کننده‌های فایل تنظیم‌شده قرار دهید. فیلد \fBuv_process_options_t.stdio\fP آرایه‌ای از ساختار \fBuv_stdio_container_t\fP است: .INDENT 0.0 .INDENT 3.5 .sp .EX typedef struct uv_stdio_container_s { uv_stdio_flags flags; union { uv_stream_t* stream; int fd; } data; } uv_stdio_container_t; .EE .UNINDENT .UNINDENT .sp که در آن flags می‌تواند مقادیر متعددی داشته باشد. اگر قرار نیست استفاده شود از \fBUV_IGNORE\fP استفاده کنید. اگر سه فیلد اول \fBstdio\fP به عنوان \fBUV_IGNORE\fP علامت‌گذاری شوند، به \fB/dev/null\fP هدایت خواهند شد. .sp از آنجا که می‌خواهیم یک توصیف‌کننده موجود را منتقل کنیم، از \fBUV_INHERIT_FD\fP استفاده می‌کنیم. سپس مقدار \fBfd\fP را روی \fBstderr\fP تنظیم می‌کنیم. .sp proc\-streams/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX int main() { loop = uv_default_loop(); /* ... */ options.stdio_count = 3; uv_stdio_container_t child_stdio[3]; child_stdio[0].flags = UV_IGNORE; child_stdio[1].flags = UV_IGNORE; child_stdio[2].flags = UV_INHERIT_FD; child_stdio[2].data.fd = 2; options.stdio = child_stdio; options.exit_cb = on_exit; options.file = args[0]; options.args = args; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, \(dq%s\en\(dq, uv_strerror(r)); return 1; } return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp اگر \fBproc\-stream\fP را اجرا کنید، خواهید دید که فقط خط \(dqThis is stderr\(dq نمایش داده می‌شود. علامت‌گذاری \fBstdout\fP به عنوان به ارث برده شده را امتحان کنید و خروجی را بررسی نمایید. .sp اعمال این تغییر مسیر به جریان‌ها بسیار ساده است. با تنظیم \fBflags\fP روی \fBUV_INHERIT_STREAM\fP و تنظیم \fBdata.stream\fP به جریان موجود در فرایند والد، فرایند فرزند می‌تواند آن جریان را به عنوان ورودی/خروجی استاندارد در نظر بگیرد. این روش می‌تواند برای پیاده‌سازی چیزی شبیه به CGI \% استفاده شود. .sp یک اسکریپت/برنامه اجرایی نمونه CGI به صورت زیر است: .sp cgi/tick.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main() { int i; for (i = 0; i < 10; i++) { printf(\(dqtick\en\(dq); fflush(stdout); sleep(1); } printf(\(dqBOOM!\en\(dq); return 0; } .EE .UNINDENT .UNINDENT .sp سرور CGI مفاهیم این بخش و بخش شبکه‌سازی را ترکیب می‌کند تا به هر کلاینت ده بار عبارت tick ارسال شود و پس از آن اتصال بسته شود. .sp cgi/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void on_new_connection(uv_stream_t *server, int status) { if (status == \-1) { // error! return; } uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { invoke_cgi_script(client); } else { uv_close((uv_handle_t*) client, NULL); } .EE .UNINDENT .UNINDENT .sp در اینجا ما به سادگی اتصال TCP را می‌پذیریم و سوکت (\fIstream\fP) را به \fBinvoke_cgi_script\fP منتقل می‌کنیم. .sp cgi/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX args[1] = NULL; /* ... finding the executable path and setting up arguments ... */ options.stdio_count = 3; uv_stdio_container_t child_stdio[3]; child_stdio[0].flags = UV_IGNORE; child_stdio[1].flags = UV_INHERIT_STREAM; child_stdio[1].data.stream = (uv_stream_t*) client; child_stdio[2].flags = UV_IGNORE; options.stdio = child_stdio; options.exit_cb = cleanup_handles; options.file = args[0]; options.args = args; // Set this so we can close the socket after the child process exits. child_req.data = (void*) client; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, \(dq%s\en\(dq, uv_strerror(r)); .EE .UNINDENT .UNINDENT .sp خروجی استاندارد \fBstdout\fP اسکریپت CGI روی سوکت تنظیم می‌شود تا هر آنچه اسکریپت تیک چاپ می‌کند به کلاینت ارسال شود. با استفاده از فرایندها، می‌توانیم بافرینگ خواندن/نوشتن را به سیستم‌عامل واگذار کنیم، بنابراین از نظر راحتی این روش عالی است. فقط توجه داشته باشید که ایجاد فرایندها عملیاتی سنگین و هزینه‌بر است. .SS "ارتباط بین‌فرایندی والد و فرزند (Parent\-child IPC)" .sp والد و فرزند می‌توانند از طریق پایپی که با تنظیم \fBuv_stdio_container_t.flags\fP با ترکیب بیتی \fBUV_CREATE_PIPE\fP و \fBUV_READABLE_PIPE\fP یا \fBUV_WRITABLE_PIPE\fP ایجاد می‌شود، ارتباط یک‌طرفه یا دوطرفه داشته باشند. فلگ خواندن/نوشتن از دیدگاه فرایند فرزند است. در این حالت، فیلد \fBuv_stream_t* stream\fP باید روی یک نمونه مقداردهی‌شده و بازنشده از \fBuv_pipe_t\fP تنظیم شود. .SS "پایپ‌های جدید stdio (New stdio Pipes)" .sp ساختار \fBuv_pipe_t\fP چیزی فراتر از صرفاً pipe(7) \% (یا \fB|\fP) را نمایندگی می‌کند و از هر شیء استریم‌گونه شبه‌فایل پشتیبانی می‌نماید. در ویندوز، تنها شیء با این توصیف Named Pipe \% است. در یونیکس، این می‌تواند هر یک از Unix Domain Socket \%، موارد مشتق‌شده از mkfifo(1) \% یا در واقع یک pipe(7) \% واقعی باشد. هنگامی که \fBuv_spawn\fP ساختار \fBuv_pipe_t\fP را به دلیل فلگ \fIUV_CREATE_PIPE\fP مقداردهی اولیه می‌کند، ایجاد یک socketpair(2) \% را برمی‌گزیند. .sp هدف از این کار فراهم کردن امکان ارتباط چند فرایند libuv با استفاده از IPC است که در ادامه به آن پرداخته می‌شود. .SS "ارتباط بین‌فرایندی میان فرایندهای دلخواه (Arbitrary process IPC)" .sp از آنجا که سوکت‌های دامنه [1] می‌توانند نامی مشخص و مکانی در سیستم فایل داشته باشند، می‌توان از آن‌ها برای IPC میان فرایندهای غیرمرتبط استفاده کرد. سیستم D\-BUS \% که توسط محیط‌های دسکتاپ متن‌باز استفاده می‌شود از سوکت‌های دامنه برای اعلان رویدادها بهره می‌برد. برنامه‌های مختلف می‌توانند هنگام آنلاین شدن یک مخاطب یا شناسایی سخت‌افزار جدید واکنش نشان دهند. سرور MySQL نیز یک سوکت دامنه اجرا می‌کند که کلاینت‌ها می‌توانند با آن تعامل داشته باشند. .sp هنگام استفاده از سوکت‌های دامنه، معمولاً از الگوی کلاینت\-سرور پیروی می‌شود و ایجادکننده/مالک سوکت به عنوان سرور عمل می‌کند. پس از راه‌اندازی اولیه، تبادل پیام تفاوتی با TCP ندارد، بنابراین مجدداً از مثال سرور اکو استفاده می‌کنیم. .sp pipe\-echo\-server/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void remove_sock(int sig) { uv_fs_t req; uv_fs_unlink(loop, &req, PIPENAME, NULL); exit(0); } int main() { loop = uv_default_loop(); uv_pipe_t server; uv_pipe_init(loop, &server, 0); signal(SIGINT, remove_sock); int r; if ((r = uv_pipe_bind(&server, PIPENAME))) { fprintf(stderr, \(dqBind error %s\en\(dq, uv_err_name(r)); return 1; } if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) { fprintf(stderr, \(dqListen error %s\en\(dq, uv_err_name(r)); return 2; } return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp ما سوکت را \fBecho.sock\fP نام‌گذاری می‌کنیم، به این معنی که در دایرکتوری محلی ایجاد خواهد شد. این سوکت اکنون تا جایی که به API جریان‌ها مربوط می‌شود رفتاری مشابه سوکت‌های TCP دارد. می‌توانید این سرور را با استفاده از socat \% آزمایش کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX $ socat \- /path/to/socket .EE .UNINDENT .UNINDENT .sp کلاینتی که می‌خواهد به یک سوکت دامنه متصل شود از تابع زیر استفاده می‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX void uv_pipe_connect(uv_connect_t *req, uv_pipe_t *handle, const char *name, uv_connect_cb cb); .EE .UNINDENT .UNINDENT .sp که در آن \fBname\fP برابر \fBecho.sock\fP یا مشابه آن خواهد بود. در سیستم‌های یونیکس، \fBname\fP باید به یک فایل معتبر اشاره کند (مانند \fB/tmp/echo.sock\fP). در ویندوز، \fBname\fP از قالب \fB\e\e?\epipe\eecho.sock\fP پیروی می‌کند. .SS "ارسال توصیف‌کننده‌های فایل از طریق پایپ‌ها (Sending file descriptors over pipes)" .sp ویژگی جالب سوکت‌های دامنه این است که می‌توان توصیف‌کننده‌های فایل را با ارسال از طریق یک سوکت دامنه میان فرایندها ردوبدل کرد. این ویژگی به فرایندها امکان می‌دهد ورودی/خروجی خود را به فرایندهای دیگر واگذار کنند. کاربردها شامل سرورهای توزیع بار (load\-balancing)، فرایندهای کارگر و سایر روش‌های استفاده بهینه از پردازنده است. کتابخانه libuv در حال حاضر فقط از ارسال \fBسوکت‌های TCP یا سایر پایپ‌ها\fP از طریق پایپ‌ها پشتیبانی می‌کند. .sp برای نشان دادن این موضوع، به پیاده‌سازی یک سرور اکو نگاهی می‌اندازیم که کلاینت‌ها را به صورت چرخشی (round\-robin) به فرایندهای کارگر واگذار می‌کند. این برنامه کمی پیچیده‌تر است و در حالی که فقط بخش‌هایی از آن در این کتاب گنجانده شده، توصیه می‌شود برای درک واقعی آن کد کامل را مطالعه کنید. .sp فرایند کارگر کاملاً ساده است، زیرا توصیف‌کننده فایل توسط فرایند اصلی (master) به آن تحویل داده می‌شود. .sp multi\-echo\-server/worker.c .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t *loop; uv_pipe_t queue; int main() { loop = uv_default_loop(); uv_pipe_init(loop, &queue, 1 /* ipc */); uv_pipe_open(&queue, 0); uv_read_start((uv_stream_t*)&queue, alloc_buffer, on_new_connection); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp متغیر \fBqueue\fP پایپی است که به فرایند اصلی در طرف دیگر متصل است و توصیف‌کننده‌های فایل جدید از طریق آن ارسال می‌شوند. بسیار مهم است که آرگومان \fBipc\fP در \fBuv_pipe_init\fP را روی 1 قرار دهید تا مشخص شود از این پایپ برای ارتباط بین‌فرایندی استفاده خواهد شد! از آنجا که فرایند اصلی هندل فایل را در ورودی استاندارد کارگر می‌نویسد، ما با استفاده از \fBuv_pipe_open\fP پایپ را به \fBstdin\fP متصل می‌کنیم. .sp multi\-echo\-server/worker.c .INDENT 0.0 .INDENT 3.5 .sp .EX void on_new_connection(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf) { if (nread < 0) { if (nread != UV_EOF) fprintf(stderr, \(dqRead error %s\en\(dq, uv_err_name(nread)); uv_close((uv_handle_t*) q, NULL); return; } uv_pipe_t *pipe = (uv_pipe_t*) q; if (!uv_pipe_pending_count(pipe)) { fprintf(stderr, \(dqNo pending count\en\(dq); return; } uv_handle_type pending = uv_pipe_pending_type(pipe); assert(pending == UV_TCP); uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(q, (uv_stream_t*) client) == 0) { uv_os_fd_t fd; uv_fileno((const uv_handle_t*) client, &fd); fprintf(stderr, \(dqWorker %d: Accepted fd %d\en\(dq, getpid(), fd); uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read); } else { uv_close((uv_handle_t*) client, NULL); } } .EE .UNINDENT .UNINDENT .sp ابتدا \fBuv_pipe_pending_count()\fP را فراخوانی می‌کنیم تا مطمئن شویم هندلی برای خواندن در دسترس است. اگر برنامه شما می‌توانست با انواع مختلفی از هندل‌ها کار کند، می‌توانستید از \fBuv_pipe_pending_type()\fP برای تعیین نوع استفاده کنید. اگرچه استفاده از \fBaccept\fP در این کد عجیب به نظر می‌رسد، اما در واقع کاملاً منطقی است. کاری که \fBaccept\fP به طور سنتی انجام می‌دهد دریافت یک توصیف‌کننده فایل (کلاینت) از یک توصیف‌کننده فایل دیگر (سوکت شنود) است؛ که دقیقاً همان کاری است که ما در اینجا انجام می‌دهیم: دریافت توصیف‌کننده فایل (\fBclient\fP) از \fBqueue\fP\&. از این نقطه به بعد کارگر کارهای معمول سرور اکو را انجام می‌دهد. .sp اکنون به سراغ فرایند اصلی (master) می‌رویم و نگاهی می‌اندازیم به اینکه چگونه کارگران برای برقراری تعادل بار راه‌اندازی می‌شوند. .sp multi\-echo\-server/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX struct child_worker { uv_process_t req; uv_process_options_t options; uv_pipe_t pipe; } *workers; .EE .UNINDENT .UNINDENT .sp ساختار \fBchild_worker\fP فرایند و پایپ میان فرایند اصلی و هر فرایند اختصاصی را بسته‌بندی می‌کند. .sp multi\-echo\-server/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void setup_workers() { round_robin_counter = 0; // ... // launch same number of workers as number of CPUs uv_cpu_info_t *info; int cpu_count; uv_cpu_info(&info, &cpu_count); uv_free_cpu_info(info, cpu_count); child_worker_count = cpu_count; workers = calloc(cpu_count, sizeof(struct child_worker)); while (cpu_count\-\-) { struct child_worker *worker = &workers[cpu_count]; uv_pipe_init(loop, &worker\->pipe, 1); uv_stdio_container_t child_stdio[3]; child_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; child_stdio[0].data.stream = (uv_stream_t*) &worker\->pipe; child_stdio[1].flags = UV_IGNORE; child_stdio[2].flags = UV_INHERIT_FD; child_stdio[2].data.fd = 2; worker\->options.stdio = child_stdio; worker\->options.stdio_count = 3; worker\->options.exit_cb = close_process_handle; worker\->options.file = args[0]; worker\->options.args = args; uv_spawn(loop, &worker\->req, &worker\->options); fprintf(stderr, \(dqStarted worker %d\en\(dq, worker\->req.pid); } } .EE .UNINDENT .UNINDENT .sp در راه‌اندازی کارگران، ما از تابع سودمند \fBuv_cpu_info\fP در libuv برای به دست آوردن تعداد پردازنده‌ها استفاده می‌کنیم تا بتوانیم به همان تعداد کارگر راه‌اندازی کنیم. باز هم تأکید می‌شود که مقداردهی اولیه پایپی که به عنوان کانال IPC عمل می‌کند با آرگومان سوم برابر با 1 الزامی است. سپس مشخص می‌کنیم که ورودی استاندارد \fBstdin\fP فرایند فرزند قرار است یک پایپ خواندنی باشد (از دیدگاه فرزند). تا اینجا همه چیز سرراست است. کارگران راه‌اندازی شده و منتظر نوشتن توصیف‌کننده‌های فایل در ورودی استاندارد خود هستند. .sp در تابع \fBon_new_connection\fP (زیرساخت TCP در \fBmain()\fP مقداردهی اولیه شده است) است که ما سوکت کلاینت را می‌پذیریم و آن را به کارگر بعدی در چرخه ارسال می‌کنیم. .sp multi\-echo\-server/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void on_new_connection(uv_stream_t *server, int status) { if (status == \-1) { // error! return; } uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { uv_write_t *write_req = (uv_write_t*) malloc(sizeof(uv_write_t)); dummy_buf = uv_buf_init(\(dqa\(dq, 1); struct child_worker *worker = &workers[round_robin_counter]; uv_write2(write_req, (uv_stream_t*) &worker\->pipe, &dummy_buf, 1, (uv_stream_t*) client, NULL); round_robin_counter = (round_robin_counter + 1) % child_worker_count; } else { uv_close((uv_handle_t*) client, NULL); } } .EE .UNINDENT .UNINDENT .sp فراخوانی \fBuv_write2\fP تمام انتزاع را انجام می‌دهد و صرفاً ارسال هندل (\fBclient\fP) به عنوان آرگومان مناسب مطرح است. با این کار، سرور اکو چندفرایندی ما آماده به کار خواهد بود. .sp با تشکر از Kyle به خاطر اشاره به این موضوع \% که تابع \fBuv_write2()\fP حتی هنگام ارسال هندل‌ها نیازمند یک بافر غیرخالی است. .sp .ce ---- .ce 0 .sp .IP [1] 5 در این بخش سوکت‌های دامنه نماینده پایپ‌های نام‌گذاری‌شده در ویندوز نیز هستند. .SS "حلقه‌های رویداد پیشرفته (Advanced event loops)" .sp کتابخانه libuv کنترل قابل‌توجهی بر روی حلقه‌های رویداد در اختیار کاربر قرار می‌دهد و شما می‌توانید با مدیریت همزمان چند حلقه به نتایج جالبی دست یابید. همچنین می‌توانید حلقه رویداد libuv را در کتابخانه دیگری که مبتنی بر حلقه رویداد است جاسازی کنید \-\- تصور کنید یک رابط کاربری مبتنی بر Qt دارید و حلقه رویداد Qt بخش بک‌اند libuv را که وظایف فشرده سیستمی را انجام می‌دهد هدایت می‌کند. .SS "متوقف کردن یک حلقه رویداد (Stopping an event loop)" .sp تابع \fBuv_stop()\fP می‌تواند برای متوقف کردن یک حلقه رویداد استفاده شود. زودترین زمانی که حلقه متوقف خواهد شد \fIدر تکرار (iteration) بعدی\fP است، و احتمالاً دیرتر. این بدان معناست که رویدادهایی که برای پردازش در این تکرار حلقه آماده هستند همچنان پردازش خواهند شد، بنابراین \fBuv_stop()\fP نمی‌تواند به عنوان یک کلید قطع اضطراری (kill switch) استفاده شود. هنگامی که \fBuv_stop()\fP فراخوانی می‌شود، حلقه در این تکرار برای I/O مسدود (\fBblock\fP) \fBنخواهد شد\fP\&. درک معناشناسی این موارد ممکن است کمی دشوار باشد، بنابراین بیایید به \fBuv_run()\fP نگاه کنیم که تمام جریان کنترل در آن رخ می‌دهد. .sp src/unix/core.c \- uv_run .INDENT 0.0 .INDENT 3.5 .sp .EX uv_signal_t* sh; /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it\(aqs still * possible for it to be active in the sense that uv__is_active() returns * true. * * A good example is when the user calls uv_shutdown(), immediately followed * by uv_close(). The handle is considered active at this point because the * completion of the shutdown req is still pending. */ assert(handle\->flags & UV_HANDLE_CLOSING); assert(!(handle\->flags & UV_HANDLE_CLOSED)); handle\->flags |= UV_HANDLE_CLOSED; switch (handle\->type) { case UV_PREPARE: case UV_CHECK: case UV_IDLE: case UV_ASYNC: case UV_TIMER: case UV_PROCESS: .EE .UNINDENT .UNINDENT .sp پرچم \fBstop_flag\fP توسط \fBuv_stop()\fP تنظیم می‌شود. اکنون تمام فراخوان‌های (callbacks) libuv درون حلقه رویداد اجرا می‌شوند، به همین دلیل فراخوانی \fBuv_stop()\fP در آنها همچنان منجر به اجرای تکرار فعلی حلقه می‌شود. ابتدا libuv تایمرها را به‌روزرسانی می‌کند، سپس فراخوان‌های معلق تایمر، idle و prepare را اجرا کرده و هرگونه فراخوان معلق I/O را فراخوانی می‌کند. اگر در هر یک از آنها \fBuv_stop()\fP را فراخوانی کنید، \fBstop_flag\fP تنظیم خواهد شد. این باعث می‌شود \fBuv_backend_timeout()\fP مقدار \fB0\fP را برگرداند، به همین دلیل است که حلقه روی I/O مسدود نمی‌شود. از سوی دیگر، اگر \fBuv_stop()\fP را در یکی از گرداننده‌های check فراخوانی کنید، عملیات I/O از قبل تمام شده است و تحت تأثیر قرار نمی‌گیرد. .sp تابع \fBuv_stop()\fP برای خاموش کردن یک حلقه در زمانی که نتیجه محاسبه شده یا خطایی رخ داده است مفید است، بدون اینکه نیاز باشد تک‌تک گرداننده‌ها را یکی‌یکی متوقف کنید. .sp در اینجا یک مثال ساده آورده شده است که حلقه را متوقف کرده و نشان می‌دهد چگونه تکرار فعلی حلقه همچنان اجرا می‌شود. .sp uvstop/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int64_t counter = 0; void idle_cb(uv_idle_t *handle) { printf(\(dqIdle callback\en\(dq); counter++; if (counter >= 5) { uv_stop(uv_default_loop()); printf(\(dquv_stop() called\en\(dq); } } void prep_cb(uv_prepare_t *handle) { printf(\(dqPrep callback\en\(dq); } int main() { uv_idle_t idler; uv_prepare_t prep; uv_idle_init(uv_default_loop(), &idler); uv_idle_start(&idler, idle_cb); uv_prepare_init(uv_default_loop(), &prep); uv_prepare_start(&prep, prep_cb); uv_run(uv_default_loop(), UV_RUN_DEFAULT); return 0; } .EE .UNINDENT .UNINDENT .SS "ابزارهای کاربردی (Utilities)" .sp این فصل ابزارها و تکنیک‌هایی را فهرست می‌کند که برای کارهای متداول مفید هستند. صفحه راهنمای libev در نشانی \% قبلاً برخی الگوها را پوشش داده است که می‌توانند با تغییرات ساده در رابط برنامه‌نویسی به libuv منتقل شوند. همچنین بخش‌هایی از API کتابخانه libuv را که نیازی به اختصاص یک فصل کامل ندارند پوشش می‌دهد. .SS "تایمرها (Timers)" .sp تایمرها پس از گذشت مدت زمان مشخصی از شروع به کار، تابع فراخوان (callback) را اجرا می‌کنند. تایمرهای libuv همچنین می‌توانند طوری تنظیم شوند که به جای فقط یک بار، در فواصل منظم تکرار شوند. .sp استفاده ساده به این صورت است که یک ناظر (watcher) را مقداردهی اولیه کرده و آن را با یک \fBtimeout\fP و مقدار اختیاری \fBrepeat\fP شروع کنید. تایمرها در هر زمانی می‌توانند متوقف شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX uv_timer_t timer_req; uv_timer_init(loop, &timer_req); uv_timer_start(&timer_req, callback, 5000, 2000); .EE .UNINDENT .UNINDENT .sp یک تایمر تکرارشونده را شروع می‌کند که اولین بار ۵ ثانیه (مقدار \fBtimeout\fP) پس از اجرای \fBuv_timer_start\fP شروع می‌شود، سپس هر ۲ ثانیه یک‌بار (مقدار \fBrepeat\fP) تکرار می‌گردد. از دستور زیر استفاده کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_timer_stop(&timer_req); .EE .UNINDENT .UNINDENT .sp برای متوقف کردن تایمر. این کار می‌تواند با ایمنی کامل از داخل خود تابع فراخوان نیز انجام شود. .sp فاصله تکرار می‌تواند در هر زمانی با دستور زیر تغییر کند: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_timer_set_repeat(uv_timer_t *timer, int64_t repeat); .EE .UNINDENT .UNINDENT .sp که \fBدر صورت امکان\fP اعمال خواهد شد. اگر این تابع از داخل یک تابع فراخوان تایمر فراخوانی شود، به این معناست که: .INDENT 0.0 .IP \(bu 2 اگر تایمر غیرتکرارشونده بود، تایمر قبلاً متوقف شده است. دوباره از \fBuv_timer_start\fP استفاده کنید. .IP \(bu 2 اگر تایمر تکرارشونده است، مهلت بعدی از قبل زمان‌بندی شده است، بنابراین فاصله تکرار قدیمی یک بار دیگر پیش از تغییر به فاصله جدید استفاده خواهد شد. .UNINDENT .sp تابع کمکی: .INDENT 0.0 .INDENT 3.5 .sp .EX int uv_timer_again(uv_timer_t *) .EE .UNINDENT .UNINDENT .sp \fBفقط برای تایمرهای تکرارشونده\fP کاربرد دارد و معادل متوقف کردن تایمر و سپس راه‌اندازی مجدد آن با تنظیم هر دو مقدار اولیه \fBtimeout\fP و \fBrepeat\fP به مقدار قبلی \fBrepeat\fP است. اگر تایمر هنوز شروع نشده باشد با شکست مواجه می‌شود (کد خطای \fBUV_EINVAL\fP) و مقدار \-1 را برمی‌گرداند. .sp یک مثال واقعی از تایمر در بخش شمارش ارجاع آورده شده است. .SS "شمارش ارجاع حلقه رویداد (Event loop reference count)" .sp حلقه رویداد فقط تا زمانی اجرا می‌شود که هندل‌های فعالی وجود داشته باشند. این سیستم به این صورت کار می‌کند که هر هندل هنگام شروع، شمارنده ارجاع (reference count) حلقه رویداد را افزایش داده و هنگام توقف، شمارنده ارجاع را کاهش می‌دهد. همچنین می‌توان شمارنده ارجاع هندل‌ها را به صورت دستی با استفاده از توابع زیر تغییر داد: .INDENT 0.0 .INDENT 3.5 .sp .EX void uv_ref(uv_handle_t*); void uv_unref(uv_handle_t*); .EE .UNINDENT .UNINDENT .sp این توابع می‌توانند برای اجازه دادن به حلقه برای خروج حتی در زمان فعال بودن یک ناظر استفاده شوند، یا برای استفاده از شیءهای سفارشی جهت زنده نگه داشتن حلقه به کار روند. .sp حالت دوم می‌تواند با تایمرهای دوره‌ای استفاده شود. ممکن است یک زباله‌روب (garbage collector) داشته باشید که هر X ثانیه اجرا می‌شود، یا سرویس شبکه شما ممکن است به صورت دوره‌ای سیگنال ضربان قلب (heartbeat) به دیگران ارسال کند، اما شما نمی‌خواهید مجبور باشید آنها را در تمام مسیرهای خروج پاک یا سناریوهای خطا متوقف کنید. یا ممکن است بخواهید برنامه زمانی که تمام ناظران دیگر کارشان تمام شد خارج شود. در این صورت بلافاصله پس از ایجاد، تایمر را unref کنید تا اگر تنها ناظر در حال اجرا باشد، \fBuv_run\fP همچنان خارج شود. .sp این موضوع همچنین در node.js استفاده می‌شود که در آن برخی از متدهای libuv به سطح JavaScript API منتقل می‌شوند. برای هر شیء JS یک \fBuv_handle_t\fP (کلاس پایه تمام ناظران) ایجاد می‌شود و می‌تواند ref یا unref شود. .sp ref\-timer/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t *loop; uv_timer_t gc_req; uv_timer_t fake_job_req; int main() { loop = uv_default_loop(); uv_timer_init(loop, &gc_req); uv_unref((uv_handle_t*) &gc_req); uv_timer_start(&gc_req, gc, 0, 2000); // could actually be a TCP download or something uv_timer_init(loop, &fake_job_req); uv_timer_start(&fake_job_req, fake_job, 9000, 0); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp ما تایمر زباله‌روب را مقداردهی اولیه می‌کنیم، سپس بلافاصله آن را \fBunref\fP می‌کنیم. مشاهده کنید که چگونه پس از ۹ ثانیه، وقتی کار ساختگی تمام می‌شود، برنامه به‌طور خودکار خارج می‌شود، حتی با اینکه زباله‌روب همچنان در حال اجراست. .SS "الگوی بیکار (Idler pattern)" .sp فراخوان‌های هندل‌های idle یک‌بار در هر حلقه رویداد فراخوانی می‌شوند. فراخوان idle می‌تواند برای انجام برخی فعالیت‌های با اولویت بسیار پایین استفاده شود. برای مثال، می‌توانید در دوره‌های بیکاری، خلاصه‌ای از عملکرد روزانه برنامه را برای تحلیل به توسعه‌دهندگان ارسال کنید، یا از زمان پردازنده برنامه برای انجام محاسبات SETI استفاده کنید :) یک ناظر idle در یک برنامه گرافیکی (GUI) نیز مفید است. فرض کنید از یک حلقه رویداد برای دانلود فایل استفاده می‌کنید. اگر سوکت TCP هنوز در حال برقراری ارتباط باشد و رویداد دیگری وجود نداشته باشد، حلقه رویداد شما متوقف (\fBblock\fP) می‌شود، به این معنی که نوار پیشرفت شما قفل شده و کاربر با یک برنامه پاسخ‌نداده مواجه خواهد شد. در چنین حالتی یک ناظر idle را در صف قرار دهید تا رابط کاربری فعال و پاسخگو باقی بماند. .sp idle\-compute/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t *loop; uv_fs_t stdin_watcher; uv_idle_t idler; char buffer[1024]; int main() { loop = uv_default_loop(); uv_idle_init(loop, &idler); uv_buf_t buf = uv_buf_init(buffer, 1024); uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, \-1, on_type); uv_idle_start(&idler, crunch_away); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp در اینجا ما ناظر idle را مقداردهی اولیه کرده و آن را همراه با رویدادهای واقعی که مد نظرمان است در صف قرار می‌دهیم. تابع \fBcrunch_away\fP اکنون به طور مکرر فراخوانی می‌شود تا زمانی که کاربر چیزی تایپ کند و Return را فشار دهد. سپس برای مدت کوتاهی متوقف می‌شود زیرا حلقه داده‌های ورودی را پردازش می‌کند، و پس از آن دوباره فراخوانی فراخوان idle ادامه می‌یابد. .sp idle\-compute/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX void crunch_away(uv_idle_t* handle) { // Compute extra\-terrestrial life // fold proteins // computer another digit of PI // or similar fprintf(stderr, \(dqComputing PI...\en\(dq); // just to avoid overwhelming your terminal emulator uv_idle_stop(handle); } .EE .UNINDENT .UNINDENT .SS "ارسال داده به ریسه کارگر (Passing data to worker thread)" .sp هنگام استفاده از \fBuv_queue_work\fP معمولاً باید داده‌های پیچیده‌ای را به ریسه کارگر ارسال کنید. راه‌حل استفاده از یک \fBstruct\fP و تنظیم \fBuv_work_t.data\fP برای اشاره به آن است. یک تغییر کوچک این است که خود \fBuv_work_t\fP به عنوان اولین عضو این ساختار قرار گیرد (که baton [1] نامیده می‌شود). این کار امکان پاکسازی درخواست کار و تمام داده‌ها را در یک فراخوانی free فراهم می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX struct ftp_baton { uv_work_t req; char *host; int port; char *username; char *password; } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX ftp_baton *baton = (ftp_baton*) malloc(sizeof(ftp_baton)); baton\->req.data = (void*) baton; baton\->host = strdup(\(dqmy.webhost.com\(dq); baton\->port = 21; // ... uv_queue_work(loop, &baton\->req, ftp_session, ftp_cleanup); .EE .UNINDENT .UNINDENT .sp در اینجا baton را ایجاد کرده و تسک را در صف قرار می‌دهیم. .sp اکنون تابع تسک می‌تواند داده‌های مورد نیاز خود را استخراج کند: .INDENT 0.0 .INDENT 3.5 .sp .EX void ftp_session(uv_work_t *req) { ftp_baton *baton = (ftp_baton*) req\->data; fprintf(stderr, \(dqConnecting to %s\en\(dq, baton\->host); } void ftp_cleanup(uv_work_t *req) { ftp_baton *baton = (ftp_baton*) req\->data; free(baton\->host); // ... free(baton); } .EE .UNINDENT .UNINDENT .sp سپس baton را آزاد می‌کنیم که ناظر را نیز آزاد می‌کند. .SS "ورودی/خروجی خارجی با Polling (External I/O with polling)" .sp معمولاً کتابخانه‌های شخص ثالث I/O خود را مدیریت کرده و سوکت‌ها و سایر فایل‌های خود را به صورت داخلی ردیابی می‌کنند. در این حالت امکان استفاده از عملیات استاندارد جریان I/O وجود ندارد، اما کتابخانه همچنان می‌تواند در حلقه رویداد libuv ادغام شود. تنها چیزی که نیاز است این است که کتابخانه به شما اجازه دهد به توصیف‌گرهای فایل زیرین دسترسی داشته باشید و توابعی را ارائه دهد که وظایف را در مراحل کوچک بر اساس تصمیم برنامه شما پردازش کنند. با این حال برخی کتابخانه‌ها چنین دسترسی را مجاز نمی‌دانند و فقط یک تابع مسدودکننده استاندارد ارائه می‌دهند که کل تراکنش I/O را انجام می‌دهد و سپس بازمی‌گردد. استفاده از این موارد در ریسه حلقه رویداد عاقلانه نیست، در عوض از زمان‌بندی کار مخزن ریسه در \%<#\:threadpool> استفاده کنید. البته این کار به معنای از دست دادن کنترل دقیق بر کتابخانه خواهد بود. .sp بخش \fBuv_poll\fP در libuv صرفاً توصیف‌گرهای فایل را با استفاده از مکانیزم اطلاع‌رسانی سیستم‌عامل نظارت می‌کند. به نوعی، تمام عملیات I/O که خود libuv پیاده‌سازی می‌کند نیز مبتنی بر کدهایی شبیه به \fBuv_poll\fP هستند. هر زمان که سیستم‌عامل متوجه تغییر وضعیت در توصیف‌گرهای فایل تحت نظارت شود، libuv تابع فراخوان مربوطه را اجرا خواهد کرد. .sp در اینجا یک برنامه مدیریت دانلود ساده را بررسی می‌کنیم که از libcurl در نشانی \% برای دانلود فایل‌ها استفاده می‌کند. به جای دادن تمام کنترل به libcurl، از حلقه رویداد libuv استفاده خواهیم کرد و از رابط غیرمسدودکننده و ناهمگام multi در نشانی \% برای پیشبرد دانلود در هر زمان که libuv آمادگی I/O را اطلاع می‌دهد بهره می‌بریم. .sp uvwget/main.c \- پیکربندی و راه‌اندازی .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include #include #include uv_loop_t *loop; CURLM *curl_handle; uv_timer_t timeout; int main(int argc, char **argv) { loop = uv_default_loop(); if (argc <= 1) return 0; if (curl_global_init(CURL_GLOBAL_ALL)) { fprintf(stderr, \(dqCould not init cURL\en\(dq); return 1; } uv_timer_init(loop, &timeout); curl_handle = curl_multi_init(); curl_multi_setopt(curl_handle, CURLMOPT_SOCKETFUNCTION, handle_socket); curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout); while (argc\-\- > 1) { add_download(argv[argc], argc); } uv_run(loop, UV_RUN_DEFAULT); curl_multi_cleanup(curl_handle); return 0; } .EE .UNINDENT .UNINDENT .sp نحوه ادغام هر کتابخانه با libuv متفاوت خواهد بود. در مورد libcurl، می‌توانیم دو تابع فراخوان ثبت کنیم. فراخوان سوکت \fBhandle_socket\fP هر زمان که وضعیت یک سوکت تغییر کند و مجبور باشیم نظارت بر آن را آغاز کنیم، فراخوانی می‌شود. تابع \fBstart_timeout\fP توسط libcurl فراخوانی می‌شود تا فاصله مهلت زمانی (timeout) بعدی را به ما اطلاع دهد، که پس از آن باید صرف‌نظر از وضعیت I/O کار libcurl را پیش ببریم. این برای آن است که libcurl بتواند خطاها را مدیریت کند یا هر کار دیگری که برای ادامه دانلود لازم است انجام دهد. .sp دانلودر ما به این صورت اجرا می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX $ ./uvwget [url1] [url2] ... .EE .UNINDENT .UNINDENT .sp بنابراین هر آرگومان را به عنوان یک نشانی اینترنتی (URL) اضافه می‌کنیم: .sp uvwget/main.c \- افزودن نشانی‌ها (URLs) .INDENT 0.0 .INDENT 3.5 .sp .EX void add_download(const char *url, int num) { char filename[50]; sprintf(filename, \(dq%d.download\(dq, num); FILE *file; file = fopen(filename, \(dqw\(dq); if (file == NULL) { fprintf(stderr, \(dqError opening %s\en\(dq, filename); return; } CURL *handle = curl_easy_init(); curl_easy_setopt(handle, CURLOPT_WRITEDATA, file); curl_easy_setopt(handle, CURLOPT_URL, url); curl_multi_add_handle(curl_handle, handle); fprintf(stderr, \(dqAdded download %s \-> %s\en\(dq, url, filename); } .EE .UNINDENT .UNINDENT .sp ما اجازه می‌دهیم libcurl داده‌ها را مستقیماً در یک فایل بنویسد، اما در صورت تمایل کارهای بسیار بیشتری امکان‌پذیر است. .sp تابع \fBstart_timeout\fP بلافاصله برای اولین بار توسط libcurl فراخوانی می‌شود، بنابراین فرآیندها به حرکت درمی‌آیند. این تابع به سادگی یک تایمر libuv در \%<#\:timers> را شروع می‌کند که هر زمان منقضی شود، \fBcurl_multi_socket_action\fP را با \fBCURL_SOCKET_TIMEOUT\fP هدایت می‌کند. تابع \fBcurl_multi_socket_action\fP چیزی است که libcurl را به پیش می‌برد و هر زمان که سوکت‌ها تغییر وضعیت دهند آن را فراخوانی می‌کنیم. اما قبل از پرداختن به آن، باید هر زمان که \fBhandle_socket\fP فراخوانی شد، روی سوکت‌ها نظارت (poll) کنیم. .sp uvwget/main.c \- راه‌اندازی نظارت (Polling) .INDENT 0.0 .INDENT 3.5 .sp .EX void start_timeout(CURLM *multi, long timeout_ms, void *userp) { if (timeout_ms <= 0) timeout_ms = 1; /* 0 means directly call socket_action, but we\(aqll do it in a bit */ uv_timer_start(&timeout, on_timeout, timeout_ms, 0); } int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) { curl_context_t *curl_context; if (action == CURL_POLL_IN || action == CURL_POLL_OUT) { if (socketp) { curl_context = (curl_context_t*) socketp; } else { curl_context = create_curl_context(s); curl_multi_assign(curl_handle, s, (void *) curl_context); } } switch (action) { case CURL_POLL_IN: uv_poll_start(&curl_context\->poll_handle, UV_READABLE, curl_perform); break; case CURL_POLL_OUT: uv_poll_start(&curl_context\->poll_handle, UV_WRITABLE, curl_perform); break; case CURL_POLL_REMOVE: if (socketp) { uv_poll_stop(&((curl_context_t*)socketp)\->poll_handle); destroy_curl_context((curl_context_t*) socketp); curl_multi_assign(curl_handle, s, NULL); } break; default: abort(); } return 0; } .EE .UNINDENT .UNINDENT .sp ما به توصیف‌گر فایل سوکت \fBs\fP و عملیات \fBaction\fP علاقه‌مندیم. برای هر سوکت در صورتی که وجود نداشته باشد یک هندل \fBuv_poll_t\fP ایجاد می‌کنیم و با استفاده از \fBcurl_multi_assign\fP آن را به سوکت متصل می‌سازیم. به این ترتیب هر زمان که تابع فراخوان اجرا شود، \fBsocketp\fP به آن اشاره می‌کند. .sp در صورتی که دانلود کامل شده یا با شکست مواجه شود، libcurl درخواست حذف نظارت را می‌دهد. بنابراین ما هندل poll را متوقف کرده و آزاد می‌کنیم. .sp بسته به اینکه libcurl می‌خواهد چه رویدادهایی را نظارت کند، نظارت را با \fBUV_READABLE\fP یا \fBUV_WRITABLE\fP شروع می‌کنیم. اکنون هر زمان که سوکت برای خواندن یا نوشتن آماده باشد، libuv فراخوان poll را اجرا خواهد کرد. فراخوانی چندباره \fBuv_poll_start\fP روی یک هندل یکسان مجاز است، زیرا فقط ماسک رویدادها را با مقدار جدید به‌روزرسانی می‌کند. تابع \fBcurl_perform\fP بخش اصلی این برنامه است. .sp uvwget/main.c \- هدایت libcurl .INDENT 0.0 .INDENT 3.5 .sp .EX void curl_perform(uv_poll_t *req, int status, int events) { uv_timer_stop(&timeout); int running_handles; int flags = 0; if (status < 0) flags = CURL_CSELECT_ERR; if (!status && events & UV_READABLE) flags |= CURL_CSELECT_IN; if (!status && events & UV_WRITABLE) flags |= CURL_CSELECT_OUT; curl_context_t *context; context = (curl_context_t*)req; curl_multi_socket_action(curl_handle, context\->sockfd, flags, &running_handles); check_multi_info(); } .EE .UNINDENT .UNINDENT .sp اولین کاری که انجام می‌دهیم متوقف کردن تایمر است، زیرا در این بازه زمانی مقداری پیشرفت حاصل شده است. سپس بسته به اینکه چه رویدادی باعث فراخوانی شده، پرچم‌های مناسب را تنظیم می‌کنیم. سپس \fBcurl_multi_socket_action\fP را با سوکتی که پیشرفت داشته و پرچم‌هایی که رویدادهای رخ‌داده را اعلام می‌کنند فراخوانی می‌نماییم. در این مرحله libcurl تمام وظایف داخلی خود را در بخش‌های کوچک انجام داده و تلاش می‌کند در سریع‌ترین زمان ممکن برگردد، که دقیقاً همان چیزی است که یک برنامه رویدادمحور در ریسه اصلی خود نیاز دارد. کتابخانه libcurl پیام‌های پیشرفت انتقال را در صف مخصوص خود قرار می‌دهد. در مورد ما، ما فقط به انتقال‌هایی علاقه‌مندیم که تکمیل شده باشند. بنابراین این پیام‌ها را استخراج کرده و هندل‌هایی را که انتقال آنها انجام شده است پاکسازی می‌کنیم. .sp uvwget/main.c \- خواندن وضعیت انتقال .INDENT 0.0 .INDENT 3.5 .sp .EX void check_multi_info(void) { char *done_url; CURLMsg *message; int pending; while ((message = curl_multi_info_read(curl_handle, &pending))) { switch (message\->msg) { case CURLMSG_DONE: curl_easy_getinfo(message\->easy_handle, CURLINFO_EFFECTIVE_URL, &done_url); printf(\(dq%s DONE\en\(dq, done_url); curl_multi_remove_handle(curl_handle, message\->easy_handle); curl_easy_cleanup(message\->easy_handle); break; default: fprintf(stderr, \(dqCURLMSG default\en\(dq); abort(); } } } .EE .UNINDENT .UNINDENT .SS "ناظران Check و Prepare (Check & Prepare watchers)" .sp در دست تکمیل (TODO) .SS "بارگذاری کتابخانه‌ها (Loading libraries)" .sp کتابخانه libuv یک رابط چندسکویی برای بارگذاری پویای کتابخانه‌های اشتراکی در نشانی \% فراهم می‌کند. این قابلیت می‌تواند برای پیاده‌سازی سیستم افزونه/پلاگین/ماژول اختصاصی شما استفاده شود و توسط node.js برای پیاده‌سازی پشتیبانی از \fBrequire()\fP در بایندینگ‌ها به کار می‌رود. استفاده از آن تا زمانی که کتابخانه شما نمادهای (symbols) مناسب را صادر کند بسیار ساده است. هنگام بارگذاری کدهای شخص ثالث مراقب بررسی‌های امنیتی و صحت‌سنجی باشید، در غیر این صورت برنامه شما رفتاری غیرقابل پیش‌بینی خواهد داشت. این مثال یک سیستم افزونه بسیار ساده را پیاده‌سازی می‌کند که کاری جز چاپ نام افزونه انجام نمی‌دهد. .sp بیایید ابتدا به رابط ارائه شده به توسعه‌دهندگان افزونه نگاه کنیم. .sp plugin/plugin.h .INDENT 0.0 .INDENT 3.5 .sp .EX #ifndef UVBOOK_PLUGIN_SYSTEM #define UVBOOK_PLUGIN_SYSTEM // Plugin authors should use this to register their plugins with mfp. void mfp_register(const char *name); #endif .EE .UNINDENT .UNINDENT .sp شما می‌توانید به طور مشابه توابع بیشتری اضافه کنید که توسعه‌دهندگان افزونه بتوانند کارهای مفیدی در برنامه شما انجام دهند [2]\&. یک نمونه افزونه با استفاده از این رابط: .sp plugin/hello.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include \(dqplugin.h\(dq void initialize() { mfp_register(\(dqHello World!\(dq); } .EE .UNINDENT .UNINDENT .sp رابط ما تعریف می‌کند که همه افزونه‌ها باید یک تابع \fBinitialize\fP داشته باشند که توسط برنامه فراخوانی خواهد شد. این افزونه به عنوان یک کتابخانه اشتراکی کامپایل شده و می‌تواند با اجرای برنامه ما بارگذاری شود: .INDENT 0.0 .INDENT 3.5 .sp .EX $ ./plugin libhello.dylib Loading libhello.dylib Registered plugin \(dqHello World!\(dq .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 نام فایل کتابخانه اشتراکی بسته به پلتفرم متفاوت خواهد بود. در لینوکس \fBlibhello.so\fP است. .UNINDENT .UNINDENT .sp این کار با استفاده از \fBuv_dlopen\fP برای بارگذاری اولیه کتابخانه اشتراکی \fBlibhello.dylib\fP انجام می‌شود. سپس با استفاده از \fBuv_dlsym\fP به تابع \fBinitialize\fP دسترسی پیدا کرده و آن را فراخوانی می‌کنیم. .sp plugin/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include \(dqplugin.h\(dq typedef void (*init_plugin_function)(); void mfp_register(const char *name) { fprintf(stderr, \(dqRegistered plugin \e\(dq%s\e\(dq\en\(dq, name); } int main(int argc, char **argv) { if (argc == 1) { fprintf(stderr, \(dqUsage: %s [plugin1] [plugin2] ...\en\(dq, argv[0]); return 0; } uv_lib_t lib; while (\-\-argc) { fprintf(stderr, \(dqLoading %s\en\(dq, argv[argc]); if (uv_dlopen(argv[argc], &lib)) { fprintf(stderr, \(dqError: %s\en\(dq, uv_dlerror(&lib)); continue; } init_plugin_function init_plugin; if (uv_dlsym(&lib, \(dqinitialize\(dq, (void **) &init_plugin)) { fprintf(stderr, \(dqdlsym error: %s\en\(dq, uv_dlerror(&lib)); continue; } init_plugin(); } return 0; } .EE .UNINDENT .UNINDENT .sp تابع \fBuv_dlopen\fP مسیری به کتابخانه اشتراکی را دریافت کرده و اشاره‌گر مات \fBuv_lib_t\fP را مقداردهی می‌کند. در صورت موفقیت 0 و در صورت بروز خطا \-1 را برمی‌گرداند. از \fBuv_dlerror\fP برای دریافت پیام خطا استفاده کنید. .sp تابع \fBuv_dlsym\fP اشاره‌گری به نماد موجود در آرگومان دوم را در آرگومان سوم ذخیره می‌کند. نوع \fBinit_plugin_function\fP اشاره‌گری تابعی به نوع تابعی است که ما در افزونه‌های برنامه به دنبال آن هستیم. .SS "واسط TTY" .sp ترمینال‌های متنی برای مدت طولانی از قالب‌بندی اولیه با یک مجموعه دستور نسبتاً استاندارد در نشانی \% پشتیبانی کرده‌اند. این قالب‌بندی اغلب توسط برنامه‌ها برای بهبود خوانایی خروجی ترمینال استفاده می‌شود. به عنوان مثال \fBgrep \-\-colour\fP\&. کتابخانه libuv انتزاع \fBuv_tty_t\fP (یک stream) و توابع مربوطه را برای پیاده‌سازی کدهای گریز ANSI در تمام پلتفرم‌ها فراهم می‌کند. منظور از این کار این است که libuv کدهای ANSI را به معادل آنها در ویندوز تبدیل کرده و توابعی را برای دریافت اطلاعات ترمینال ارائه می‌دهد. .sp اولین کاری که باید انجام شود مقداردهی اولیه یک \fBuv_tty_t\fP با توصیف‌گر فایلی است که از آن می‌خواند یا در آن می‌نویسد. این کار با دستور زیر انجام می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int unused) .EE .UNINDENT .UNINDENT .sp پارامتر \fBunused\fP اکنون به طور خودکار تشخیص داده شده و نادیده گرفته می‌شود. پیش از این برای استفاده از \fBuv_read_start()\fP روی stream لازم بود مقداردهی شود. .sp سپس بهتر است از \fBuv_tty_set_mode\fP برای تنظیم حالت روی \fInormal\fP استفاده کنید که بیشتر قابلیت‌های قالب‌بندی، کنترل جریان و سایر تنظیمات TTY را فعال می‌کند. حالت‌های دیگر در نشانی \% نیز در دسترس هستند. .sp به یاد داشته باشید که هنگام خروج برنامه، \fBuv_tty_reset_mode\fP را فراخوانی کنید تا وضعیت ترمینال بازیابی شود؛ این یک رفتار استاندارد و حرفه‌ای است. یک نکته حرفه‌ای دیگر این است که به هدایت مجدد (redirection) خروجی توجه داشته باشید. اگر کاربر خروجی دستور شما را به یک فایل هدایت کند، دنباله‌های کنترلی نباید نوشته شوند زیرا خوانایی و کار با \fBgrep\fP را مختل می‌کنند. برای بررسی اینکه آیا توصیف‌گر فایل واقعاً یک TTY است، \fBuv_guess_handle\fP را با توصیف‌گر فایل فراخوانی کرده و مقدار بازگشتی را با \fBUV_TTY\fP مقایسه کنید. .sp در اینجا یک مثال ساده آورده شده است که متن سفید را روی پس‌زمینه قرمز چاپ می‌کند: .sp tty/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include #include uv_loop_t *loop; uv_tty_t tty; int main() { uv_write_t req; uv_buf_t buf; uv_write_t req1; uv_buf_t buf1; loop = uv_default_loop(); uv_tty_init(loop, &tty, STDOUT_FILENO, 0); uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL); if (uv_guess_handle(1) == UV_TTY) { buf1.base = \(dq\e033[41;37m\(dq; buf1.len = strlen(buf1.base); uv_write(&req1, (uv_stream_t*) &tty, &buf1, 1, NULL); } buf.base = \(dqHello TTY\en\(dq; buf.len = strlen(buf.base); uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL); uv_tty_reset_mode(); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp آخرین تابع کمکی TTY تابع \fBuv_tty_get_winsize()\fP است که برای دریافت عرض و ارتفاع ترمینال استفاده می‌شود و در صورت موفقیت مقدار \fB0\fP را برمی‌گرداند. در اینجا یک برنامه کوچک وجود دارد که با استفاده از این تابع و کدهای گریز موقعیت کاراکتر، مقداری انیمیشن انجام می‌دهد. .sp tty\-gravity/main.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include #include uv_loop_t *loop; uv_tty_t tty; uv_timer_t tick; uv_write_t write_req; int width, height; int pos = 0; char *message = \(dq Hello TTY \(dq; void update(uv_timer_t *req) { char data[500]; uv_buf_t buf; buf.base = data; buf.len = sprintf(data, \(dq\e033[2J\e033[H\e033[%dB\e033[%luC\e033[42;37m%s\(dq, pos, (unsigned long) (width\-strlen(message))/2, message); uv_write(&write_req, (uv_stream_t*) &tty, &buf, 1, NULL); pos++; if (pos > height) { uv_tty_reset_mode(); uv_timer_stop(&tick); } } int main() { loop = uv_default_loop(); uv_tty_init(loop, &tty, STDOUT_FILENO, 0); uv_tty_set_mode(&tty, 0); if (uv_tty_get_winsize(&tty, &width, &height)) { fprintf(stderr, \(dqCould not get TTY information\en\(dq); uv_tty_reset_mode(); return 1; } fprintf(stderr, \(dqWidth %d, height %d\en\(dq, width, height); uv_timer_init(loop, &tick); uv_timer_start(&tick, update, 200, 200); return uv_run(loop, UV_RUN_DEFAULT); } .EE .UNINDENT .UNINDENT .sp کدهای گریز عبارتند از: .TS box center; l|l. T{ کد T} T{ معنی T} _ T{ \fI2\fP J T} T{ پاکسازی بخشی از صفحه، مقدار 2 کل صفحه است T} _ T{ H T} T{ انتقال مکان‌نما به یک موقعیت خاص، پیش‌فرض بالا\-چپ T} _ T{ \fIn\fP B T} T{ انتقال مکان‌نما به پایین به اندازه n خط T} _ T{ \fIn\fP C T} T{ انتقال مکان‌نما به راست به اندازه n ستون T} _ T{ m T} T{ پیروی از رشته تنظیمات نمایشگر، در این حالت پس‌زمینه سبز (40+2)، متن سفید (30+7) T} .TE .sp همانطور که می‌بینید این کار برای تولید خروجی با قالب‌بندی زیبا بسیار مفید است، یا حتی بازی‌های آرکید مبتنی بر کنسول اگر علاقه‌مند باشید. برای کنترل‌های پیشرفته‌تر می‌توانید ncurses را در نشانی \% امتحان کنید. .sp تغییر یافته در نسخه 1.23.1:: پارامتر \fIreadable\fP اکنون استفاده نشده و نادیده گرفته می‌شود. مقدار مناسب اکنون به طور خودکار از هسته سیستم‌عامل تشخیص داده خواهد شد. .sp .ce ---- .ce 0 .sp .IP [1] 5 من اولین بار با اصطلاح baton در این زمینه، در اسلایدهای عالی Konstantin Käfer درباره نوشتن بایندینگ‌های node.js آشنا شدم \-\- \% .IP [2] 5 عبارت mfp مخفف My Fancy Plugin است. .SS "درباره (About)" .sp آقای Nikhil Marathe در نشانی \% یک بعدازظهر (۱۶ ژوئن ۲۰۱۲) زمانی که تمایلی به برنامه‌نویسی نداشت شروع به نوشتن این کتاب کرد. او اخیراً هنگام کار روی node\-taglib در نشانی \% از کمبود مستندات خوب برای libuv آسیب دیده بود. اگرچه مستندات مرجع وجود داشت، اما هیچ آموزش جامعی موجود نبود. این کتاب حاصل آن نیاز است و تلاش می‌کند دقیق باشد. با این حال، کتاب ممکن است اشتباهاتی داشته باشد. از ارسال Pull Request استقبال می‌شود. .sp نیخیل مدیون صفحه راهنمای جامع Marc Lehmann در نشانی \% درباره libev است که بخش زیادی از معناشناسی این دو کتابخانه را شرح می‌دهد. .sp این کتاب با استفاده از Sphinx در نشانی \% و vim در نشانی \% ساخته شده است. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در سال ۲۰۱۷ پروژه libuv کارهای Nikhil را در مستندات رسمی گنجاند و از آن زمان به بعد در آنجا نگهداری می‌شود. .UNINDENT .UNINDENT .SS "ارتقا (Upgrading)" .sp راهنماهای مهاجرت برای نسخه‌های مختلف libuv، با شروع از نسخه 1.0. .SS "راهنمای مهاجرت از libuv 0.10 به 1.0.0 (libuv 0.10 -> 1.0.0 migration guide)" .sp برخی از APIها در طول فرآیند توسعه 1.0.0 تغییرات زیادی کردند. در اینجا یک راهنمای مهاجرت برای مهم‌ترین تغییراتی که پس از انتشار 0.10 رخ داده آورده شده است. .SS "مقداردهی اولیه و بستن حلقه (Loop initialization and closing)" .sp در libuv 0.10 (و نسخه‌های قبلی)، حلقه‌ها با \fIuv_loop_new\fP ایجاد می‌شدند که حافظه را برای یک حلقه جدید تخصیص می‌داد و آن را مقداردهی می‌کرد؛ و با \fIuv_loop_delete\fP تخریب می‌شدند که حلقه را از بین برده و حافظه را آزاد می‌کرد. با شروع از نسخه 1.0، این توابع منسوخ شده‌اند و کاربر مسئول تخصیص حافظه و سپس مقداردهی اولیه حلقه است. .sp کتابخانه libuv 0.10 .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t* loop = uv_loop_new(); \&... uv_loop_delete(loop); .EE .UNINDENT .UNINDENT .sp کتابخانه libuv 1.0 .INDENT 0.0 .INDENT 3.5 .sp .EX uv_loop_t* loop = malloc(sizeof *loop); uv_loop_init(loop); \&... uv_loop_close(loop); free(loop); .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 مدیریت خطا برای رعایت اختصار حذف شد. مستندات مربوط به \fBuv_loop_init()\fP در \%<#\:c\:.uv_loop_init> و \fBuv_loop_close()\fP در \%<#\:c\:.uv_loop_close> را بررسی کنید. .UNINDENT .UNINDENT .SS "مدیریت خطاها (Error handling)" .sp مدیریت خطا در libuv 1.0 دستخوش بازنگری اساسی شد. به طور کلی، در libuv 0.10 توابع و پارامترهای وضعیت در صورت موفقیت مقدار 0 و در صورت شکست مقدار \-1 دریافت می‌کردند و کاربر باید از \fIuv_last_error\fP برای واکشی کد خطا که یک عدد مثبت بود استفاده می‌کرد. .sp در نسخه 1.0، توابع و پارامترهای وضعیت حاوی کد خطای واقعی هستند که برای موفقیت برابر با 0 و در صورت بروز خطا یک عدد منفی است. .sp کتابخانه libuv 0.10 .INDENT 0.0 .INDENT 3.5 .sp .EX \&... assume \(aqserver\(aq is a TCP server which is already listening r = uv_listen((uv_stream_t*) server, 511, NULL); if (r == \-1) { uv_err_t err = uv_last_error(uv_default_loop()); /* err.code contains UV_EADDRINUSE */ } .EE .UNINDENT .UNINDENT .sp کتابخانه libuv 1.0 .INDENT 0.0 .INDENT 3.5 .sp .EX \&... assume \(aqserver\(aq is a TCP server which is already listening r = uv_listen((uv_stream_t*) server, 511, NULL); if (r < 0) { /* r contains UV_EADDRINUSE */ } .EE .UNINDENT .UNINDENT .SS "تغییرات مخزن ریسه‌ها (Threadpool changes)" .sp در libuv 0.10 سیستم‌های یونیکس از یک threadpool استفاده می‌کردند که به طور پیش‌فرض دارای ۴ ریسه بود، در حالی که ویندوز از API مربوط به \fIQueueUserWorkItem\fP استفاده می‌کرد که از threadpool داخلی ویندوز با پیش‌فرض ۵۱۲ ریسه برای هر فرآیند بهره می‌برد. .sp در نسخه 1.0، هر دو پیاده‌سازی را یکپارچه کردیم، بنابراین ویندوز اکنون از همان پیاده‌سازی یونیکس استفاده می‌کند. اندازه threadpool را می‌توان با اکسپورت کردن متغیر محیطی \fBUV_THREADPOOL_SIZE\fP تنظیم کرد. بخش زمان‌بندی کار مخزن ریسه در \%<#\:threadpool> را ببینید. .SS "تغییر رابط برنامه‌نویسی فراخوان تخصیص (Allocation callback API change)" .sp در libuv 0.10 تابع فراخوان باید یک ساختار \fBuv_buf_t\fP در \%<#\:c\:.uv_buf_t> پرشده را بر اساس مقدار (by value) برمی‌گرداند: .INDENT 0.0 .INDENT 3.5 .sp .EX uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) { return uv_buf_init(malloc(size), size); } .EE .UNINDENT .UNINDENT .sp در libuv 1.0 یک اشاره‌گر به بافر به تابع فراخوان ارسال می‌شود که کاربر باید آن را مقداردهی و پر کند: .INDENT 0.0 .INDENT 3.5 .sp .EX void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { buf\->base = malloc(size); buf\->len = size; } .EE .UNINDENT .UNINDENT .SS "یکپارچه‌سازی رابط‌های IPv4 و IPv6 (Unification of IPv4 / IPv6 APIs)" .sp نسخه 1.0 کتابخانه libuv رابط‌های IPv4 و IPv6 را یکپارچه کرد. دیگر دوگانگی بین \fIuv_tcp_bind\fP و \fIuv_tcp_bind6\fP وجود ندارد و اکنون فقط \fBuv_tcp_bind()\fP در \%<#\:c\:.uv_tcp_bind> در دسترس است. .sp توابع IPv4 ساختارهای \fBstruct sockaddr_in\fP را بر اساس مقدار دریافت می‌کردند و توابع IPv6 ساختار \fBstruct sockaddr_in6\fP را می‌گرفتند. اکنون توابع یک \fBstruct sockaddr*\fP (توجه داشته باشید که یک اشاره‌گر است) دریافت می‌کنند. این ساختار می‌تواند روی پشته (stack) تخصیص یابد. .sp کتابخانه libuv 0.10 .INDENT 0.0 .INDENT 3.5 .sp .EX struct sockaddr_in addr = uv_ip4_addr(\(dq0.0.0.0\(dq, 1234); \&... uv_tcp_bind(&server, addr) .EE .UNINDENT .UNINDENT .sp کتابخانه libuv 1.0 .INDENT 0.0 .INDENT 3.5 .sp .EX struct sockaddr_in addr; uv_ip4_addr(\(dq0.0.0.0\(dq, 1234, &addr) \&... uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); .EE .UNINDENT .UNINDENT .sp توابع ایجاد ساختارهای IPv4 و IPv6 (توابع \fBuv_ip4_addr()\fP در \%<#\:c\:.uv_ip4_addr> و \fBuv_ip6_addr()\fP در \%<#\:c\:.uv_ip6_addr>) نیز تغییر کرده‌اند، حتماً مستندات آنها را بررسی کنید. .INDENT 0.0 .TP .B \&..note:: این تغییر برای تمامی توابعی که بین آدرس‌های IPv4 و IPv6 تمایز قائل می‌شدند اعمال می‌شود. .UNINDENT .SS "تغییر رابط فراخوان دریافت داده در Streams و UDP" .sp فراخوان‌های دریافت داده در streams و UDP اکنون اشاره‌گری به یک بافر \fBuv_buf_t\fP در \%<#\:c\:.uv_buf_t> دریافت می‌کنند، نه یک ساختار بر اساس مقدار. .sp کتابخانه libuv 0.10 .INDENT 0.0 .INDENT 3.5 .sp .EX void on_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { ... } void recv_cb(uv_udp_t* handle, ssize_t nread, uv_buf_t buf, struct sockaddr* addr, unsigned flags) { ... } .EE .UNINDENT .UNINDENT .sp کتابخانه libuv 1.0 .INDENT 0.0 .INDENT 3.5 .sp .EX void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { ... } void recv_cb(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { ... } .EE .UNINDENT .UNINDENT .SS "تغییر رابط دریافت هندل‌ها از طریق Pipeها" .sp در libuv 0.10 (و نسخه‌های پیشین) تابع \fIuv_read2_start\fP برای شروع خواندن داده‌ها روی یک pipe استفاده می‌شد که می‌توانست منجر به دریافت هندل‌ها از طریق آن نیز شود. تابع فراخوان برای چنین تابعی به شکل زیر بود: .INDENT 0.0 .INDENT 3.5 .sp .EX void on_read(uv_pipe_t* pipe, ssize_t nread, uv_buf_t buf, uv_handle_type pending) { ... } .EE .UNINDENT .UNINDENT .sp در libuv 1.0 تابع \fIuv_read2_start\fP حذف شد و کاربر باید در حین اجرای فراخوان خواندن، با استفاده از \fBuv_pipe_pending_count()\fP در \%<#\:c\:.uv_pipe_pending_count> و \fBuv_pipe_pending_type()\fP در \%<#\:c\:.uv_pipe_pending_type> بررسی کند که آیا هندل‌های معلقی وجود دارند یا خیر: .INDENT 0.0 .INDENT 3.5 .sp .EX void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { ... while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) { pending = uv_pipe_pending_type((uv_pipe_t*) handle); ... } ... } .EE .UNINDENT .UNINDENT .SS "استخراج توصیف‌گر فایل از یک هندل (Extracting the file descriptor out of a handle)" .sp اگرچه این کار توسط API پشتیبانی نمی‌شد، اما کاربران اغلب به بخش‌های داخلی libuv دسترسی پیدا می‌کردند تا مثلاً به توصیف‌گر فایل یک هندل TCP دسترسی یابند. .INDENT 0.0 .INDENT 3.5 .sp .EX fd = handle\->io_watcher.fd; .EE .UNINDENT .UNINDENT .sp این قابلیت اکنون به درستی از طریق تابع \fBuv_fileno()\fP در \%<#\:c\:.uv_fileno> در دسترس قرار گرفته است. .SS "تغییر نام و رابط تابع uv_fs_readdir" .sp تابع \fIuv_fs_readdir\fP در libuv 0.10 پس از اتمام لیستی از رشته‌ها را در فیلد \fIreq\->ptr\fP برمی‌گرداند. در نسخه 1.0، نام این تابع به \fBuv_fs_scandir()\fP در \%<#\:c\:.uv_fs_scandir> تغییر یافت، زیرا در واقع با استفاده از \fBscandir(3)\fP پیاده‌سازی شده است. .sp علاوه بر این، به جای تخصیص یک لیست کامل از رشته‌ها، کاربر می‌تواند با استفاده از تابع \fBuv_fs_scandir_next()\fP در \%<#\:c\:.uv_fs_scandir_next> هر بار یک نتیجه را دریافت کند. این تابع نیازی به رفت و برگشت به threadpool ندارد، زیرا libuv لیست \fIdents\fP بازگردانده شده توسط \fBscandir(3)\fP را نگه می‌دارد. .SH "دانلودها (DOWNLOADS)" .sp کتابخانه libuv می‌تواند از اینجا دانلود شود \%\&. .SH "نصب (INSTALLATION)" .sp دستورالعمل‌های نصب را می‌توان در فایل README در نشانی \% یافت. .SH "نویسنده (AUTHOR)" مشارکت‌کنندگان libuv .SH "حق نشر (COPYRIGHT)" 2014-present, مشارکت‌کنندگان libuv .\" End of generated man page.