POSIX
इनपुट / आउटपुट मल्टीप्लेक्सिंग
खोज…
परिचय
IO अवरुद्ध / गैर-अवरुद्ध और तुल्यकालिक / अतुल्यकालिक हो सकता है। POSIX API, सिंक्रोनस ब्लॉकिंग API (उदाहरण के लिए क्लासिक रीड, राइट, सेंड, कॉल रिवाइव) प्रदान करता है, सिंक्रोनस नॉन-ब्लॉकिंग एपीआई (एक ही फंक्शन, फाइल डिस्क्रिप्टर O_NONBLOCK
फ्लैग और IO-मल्टीप्लेक्सिंग कॉल के साथ खोला गया) और एसोचॉनस API ( aio_
साथ शुरू होने वाले aio_
)।
सिंक्रोनस एपीआई आमतौर पर "एक धागा / प्रक्रिया प्रति एफडी" शैली के साथ प्रयोग किया जाता है। यह संसाधनों के लिए भयानक है। गैर-अवरुद्ध एपीआई एक थ्रेड में एक सेट के साथ संचालित करने की अनुमति देता है।
मतदान
इस उदाहरण में हम कनेक्टेड सॉकेट की एक जोड़ी बनाते हैं और एक से दूसरे में 4 स्ट्रिंग्स भेजते हैं और प्राप्त स्ट्रिंग्स को कंसोल पर प्रिंट करते हैं। ध्यान दें, हम जितनी बार कॉल भेजेंगे, हम उतने समय के बराबर नहीं होंगे जितना कि हम कॉल करते हैं
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#define BUFSIZE 512
int main()
{
#define CKERR(msg) {if(ret < 0) { perror(msg); \
close(sockp[0]); close(sockp[1]); exit(EXIT_FAILURE); } }
const char* strs_to_write[] = {"hello ", "from ", "other ", "side "};
int sockp[2] = {-1, -1};
ssize_t ret = socketpair (AF_UNIX, SOCK_STREAM, 0, sockp);
CKERR("Socket pair creation error")
struct pollfd pfds[2];
for(int i=0; i<2; ++i) {
pfds[i] = (struct pollfd){sockp[i], POLLIN|POLLOUT, 0};
fcntl(sockp[i], F_SETFL|O_NONBLOCK); // nonblocking fds are
// literally mandatory for IO multiplexing; non-portable
}
char buf[BUFSIZE];
size_t snt = 0, msgs = sizeof(strs_to_write)/sizeof(char*);
while(1) {
int ret = poll(pfds,
2 /*length of pollfd array*/,
5 /*milliseconds to wait*/);
CKERR("Poll error")
if (pfds[0].revents & POLLOUT && snt < msgs) {
// Checking POLLOUT before writing to ensure there is space
// available in socket's kernel buffer to write, otherwise we
// may face EWOULDBLOCK / EAGAIN error
ssize_t ret = send(sockp[0], strs_to_write[snt], strlen(strs_to_write[snt]), 0);
if(++snt >= msgs)
close(sockp[0]);
CKERR("send error")
if (ret == 0) {
puts("Connection closed");
break;
}
if (ret > 0) {
// assuming that all bytes were written
// if ret != %sent bytes number%, send other bytes later
}
}
if (pfds[1].revents & POLLIN) {
// There is something to read
ssize_t ret = recv(sockp[1], buf, BUFSIZE, 0);
CKERR("receive error")
if (ret == 0) {
puts("Connection closed");
break;
}
if (ret > 0) {
printf("received str: %.*s\n", (int)ret, buf);
}
}
}
close(sockp[1]);
return EXIT_SUCCESS;
}
चुनते हैं
I / O मल्टीप्लेक्सिंग करने के लिए चयन एक और तरीका है। यह फायदे में से एक है winsock एपीआई में एक अस्तित्व। इसके अलावा, लिनक्स पर, चयन करें () समय की मात्रा को प्रतिबिंबित करता है ताकि समय पर नींद न आए; अधिकांश अन्य कार्यान्वयन ऐसा नहीं करते हैं। (POSIX.1 या तो व्यवहार की अनुमति देता है।)
मतदान और चयन दोनों में ppoll और pselect विकल्प हैं, जो घटना की प्रतीक्षा के दौरान आने वाले संकेतों को संभालने की अनुमति देते हैं। और वे दोनों बड़ी मात्रा में फ़ाइल डिस्क्रिप्टर (एक सौ और अधिक) के साथ धीमा हो जाते हैं, इसलिए प्लेटफ़ॉर्म विशिष्ट कॉल का चयन करना बुद्धिमान होगा, उदाहरण के लिए लिनक्स पर epoll
और kqueue
पर kqueue
। या अतुल्यकालिक एपीआई (POSIX aio
उदा या IO पूर्णता पोर्ट की तरह कुछ विशिष्ट) पर स्विच करें।
चयन कॉल में निम्नलिखित प्रोटोटाइप हैं:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
fd_set
फ़ाइल डिस्क्रिप्टर का एक बिटमास्क ऐरे है,
nfds
सेट + 1 में सभी फ़ाइल डिस्क्रिप्टर की अधिकतम संख्या है।
चयन के साथ काम करने का स्निपेट:
fd_set active_fd_set, read_fd_set;
FD_ZERO (&active_fd_set); // set fd_set to zeros
FD_SET (sock, &active_fd_set); // add sock to the set
// # define FD_SETSIZE sock + 1
while (1) {
/* Block until input arrives on one or more active sockets. */
read_fd_set = active_fd_set; // read_fd_set gets overriden each time
if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
// handle error
}
// Service all file descriptors with input pending.
for (i = 0; i < FD_SETSIZE; ++i) {
if (FD_ISSET (i, &read_fd_set)) {
// there is data for i
}
}
ध्यान दें, कि ज्यादातर POSIX इम्प्लाईमेटेशन पर डिस्क पर फ़ाइलों के साथ जुड़े फाइल डिस्क्रिप्टर ब्लॉक हो रहे हैं। इसलिए फाइल को लिखना, भले ही यह फाइल writefds
में सेट की गई writefds
, तब तक ब्लॉक हो जाएगी जब तक कि सभी बाइट्स डिस्क पर डंप नहीं होंगे