ããã»ã¹ééä¿¡ã®æ¯è¼
デバイスドライバによるプロセス間通信 - ka2yanの日記ã®ããã¤ã¹ãã©ã¤ãã¯ãæ¢åã®ããã»ã¹ééä¿¡ã¨æ¯ã¹ã¦æ¬å½ã«æ©ãã®ããã測å®ããã
調ã¹ããã¨
100ãã¤ãç¨åº¦ã®ã¡ãã»ã¼ã¸ï¼ç»åãã¼ã¿çã®å¤§å®¹éãã¼ã¿ã対象ã«ãã¦ããã®ã§ã¯ãªãï¼ãããã¨ãããããã»ã¹ééä¿¡ã§ä¸çªæ©ãã®ã¯ä½ãï¼
測å®ããããã»ã¹ééä¿¡ã¯ãååã®æ¥è¨ã«æ¸ããããã¤ã¹ãã©ã¤ãï¼å
±æã¡ã¢ãªæ¹å¼ï¼ã¨ããã¤ã¹ãã©ã¤ãï¼ã¡ãã»ã¼ã¸Read/Writeï¼ãããã¦ãã¡ãã»ã¼ã¸ãã¥ã¼ï¼POSIXï¼ãUNIXãã¡ã¤ã³ã½ã±ãããååä»ãã¤ãï¼FIFOï¼ã®ï¼ç¨®é¡ã
ã¡ãã»ã¼ã¸ãã¥ã¼ï¼System Vï¼ã¯ãfd ã¨ãã¦æ±ããªãã®ã§ã測å®ããªãã
測å®ããã°ã©ã ã®æ¦è¦
âï¼ããã»ã¹éã§128ãã¤ãã®ã¡ãã»ã¼ã¸ãéåä¿¡ãç¹°ãè¿ãããã°ã©ã
âï¼ããã»ã¹ã¯ãNON_BLOCKING ã§ã¡ãã»ã¼ã¸ãread/write
âread/writeããåã«ãselect()ãã
測å®å 容
âã¡ãã»ã¼ã¸ã®éåä¿¡åæ° 1000,000å
âtimeã³ãã³ãã§ã®ã³ãã³ãå®è¡æéï¼å³å¯ãªéåä¿¡æéã§ã¯ãªãï¼
測å®ç°å¢
âCentOS5.2 (2.6.18)
âCPU:Pentium4 2.8GHzãMemory:2GB
çµæ
ããã»ã¹ééä¿¡ | real[s] | user[s] | sys[s] |
---|---|---|---|
ããã¤ã¹ãã©ã¤ãï¼å ±æã¡ã¢ãªæ¹å¼ï¼ | 7.322 | 0.716 | 2.922 |
ããã¤ã¹ãã©ã¤ãï¼ã¡ãã»ã¼ã¸Read/Writeæ¹å¼ï¼ | 7.663 | 0.715 | 3.124 |
ã¡ãã»ã¼ã¸ãã¥ã¼ï¼POSIXï¼ | 6.935 | 0.792 | 2.755 |
UNIXãã¡ã¤ã³ã½ã±ãã | 9.679 | 1.716 | 7.956 |
ååä»ãã¤ãï¼FIFOï¼ | 8.272 | 1.465 | 6.801 |
real ï¼å®æéï¼ã³ãã³ããèµ·åãã¦ããçµäºããã¾ã§ã®æéï¼
user ï¼ã¦ã¼ã¶CPUæéï¼ã¦ã¼ã¶ã¼ããã»ã¹ãåä½ãã¦ããæéï¼
sys ï¼ã·ã¹ãã CPUæéï¼ã«ã¼ãã«ã§ã®åä½æéï¼
ãªãã¨ãã¡ãã»ã¼ã¸ãã¥ã¼ï¼POSIXï¼ãä¸çªæ©ãï¼
ããã¤ã¹ãã©ã¤ããä¸çªæ©ããã¨ãæå¾
ãã¦ããã®ã ããæ®å¿µã
ãã ãããã¤ã¹ãã©ã¤ãï¼ã¡ãã»ã¼ã¸Read/Writeæ¹å¼ï¼ã¯ãã¡ãã»ã¼ã¸ãã¥ã¼ï¼POSIXï¼ãã
é度ãï¼å²ç¨åº¦é
ãã¦ããããã»ã¹ééä¿¡ã®ãã°ãåããã¨ããã¡ãªãããããã
ãããªã«é
ãã¯ãªããã©ããªãã¨ãããå°ãæ©ããªããªãããªãã
TODO
ããã¤ã¹ãã©ã¤ãï¼ã¡ãã»ã¼ã¸Read/Writeæ¹å¼ï¼ãããå°ã使ãããã©ã¤ãã«ããã
# ããå°ã2.6ãã©ã¤ãã¼ããããã
# è¤æ°ããã»ã¹å¯¾å¿
ä»ã¯ãï¼ããã»ã¹ã§ãã使ããªãã
# è¤æ°ã¡ãã»ã¼ã¸å¯¾å¿
ä»ã¯ãï¼ã¡ãã»ã¼ã¸ããä¿æã§ããªã
# ã·ã§ã«ã¹ã¯ãªããããã®ã¡ãã»ã¼ã¸åä¿¡å¦çã®å®è£
測å®ã«ä½¿ã£ãããã°ã©ã é
å®è¡é åºã¯ãããã¤ã¹ãã©ã¤ãã¨åæ§ã§ãread å´ãå®è¡ãã¦ãããwrite å´ã®å¼æ°ã«1000000ã渡ãã
ããã°ã©ã ãå¤ãã®ã§ãMakefile 㨠å®è¡ä¾ã¯çç¥ããã
ããã¤ã¹ãã©ã¤ãï¼å ±æã¡ã¢ãªæ¹å¼ï¼
ããã¤ã¹ãã©ã¤ãï¼ã¡ãã»ã¼ã¸Read/Writeæ¹å¼ï¼
ã¡ãã»ã¼ã¸ãã¥ã¼ï¼POSIXï¼
mqread.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/select.h> #include <mqueue.h> #include <fcntl.h> #include <errno.h> #define DPRINTF(...) //#define DPRINTF(...) printf(__VA_ARGS__) int main(int argc, char *argv[]) { mqd_t fd1, fd2; fd_set rfds, wfds; char buf[128]; int read_start; unsigned int prio=10; struct mq_attr attr; char *rbuf; memset(&attr, 0, sizeof(attr)); mq_unlink("/mq1"); mq_unlink("/mq2"); if ((fd1 = mq_open("/mq1", O_RDONLY|O_NONBLOCK|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) { perror("open /mq1"); exit(-1); } if ((fd2 = mq_open("/mq2", O_WRONLY|O_NONBLOCK|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) { perror("open /mq2"); exit(-1); } mq_getattr(fd1,&attr); if((rbuf = malloc(attr.mq_msgsize)) == NULL) { fprintf(stderr, "malloc error\n"); exit(-1); } read_start=1; while (1) { if (read_start) { buf[0] = '\0'; FD_ZERO(&rfds); FD_SET(fd1, &rfds); DPRINTF("selecting read...\n"); if (select(fd1+1, &rfds, NULL, NULL, NULL) == -1) { perror("select"); } if (FD_ISSET(fd1, &rfds)) { int n; n = mq_receive(fd1, rbuf, attr.mq_msgsize, &prio); if (n > 0 ) { DPRINTF("%d = read [%s] prio=%d\n", n, rbuf, prio); } else { perror("read"); exit(-1); } } read_start = 0; } else { memset(buf, 'r', sizeof(buf)); buf[sizeof(buf)-1] = '\0'; FD_ZERO(&wfds); FD_SET(fd2, &wfds); DPRINTF("selecting write...\n"); if (select(fd2+1, NULL, &wfds, NULL, NULL) == -1) { perror("select"); exit(-1); } if (FD_ISSET(fd2, &wfds)) { if (mq_send(fd2, buf, sizeof(buf), prio) != 0) { perror("write"); exit(-1); } } read_start = 1; // sleep(1); } } mq_close(fd1); mq_close(fd2); return 0; }
mqwrite.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/select.h> #include <mqueue.h> #include <fcntl.h> #include <errno.h> #define DPRINTF(...) //#define DPRINTF(...) printf(__VA_ARGS__) int main(int argc, char *argv[]) { mqd_t fd1, fd2; fd_set rfds, wfds; char buf[128]; int read_start; unsigned int prio=10; int nloop, i; struct mq_attr attr; char *rbuf; if (argc != 2) { printf("usage:\n./mqwrite <NLOOP>\n"); exit(-1); } nloop = atoi(argv[1]); memset(&attr, 0, sizeof(attr)); if ((fd1 = mq_open("/mq2", O_RDONLY|O_NONBLOCK)) == -1) { perror("open /mq2"); exit(-1); } if ((fd2 = mq_open("/mq1", O_WRONLY|O_NONBLOCK)) == -1) { perror("open /mq1"); exit(-1); } mq_getattr(fd1,&attr); if((rbuf = malloc(attr.mq_msgsize)) == NULL) { fprintf(stderr, "malloc error\n"); exit(-1); } read_start=0; for(i=0; i<nloop; i++) { if (read_start) { buf[0] = '\0'; FD_ZERO(&rfds); FD_SET(fd1, &rfds); DPRINTF("selecting read...\n"); if (select(fd1+1, &rfds, NULL, NULL, NULL) == -1) { perror("select"); } if (FD_ISSET(fd1, &rfds)) { int n; n = mq_receive(fd1, rbuf, attr.mq_msgsize, &prio); if (n > 0 ) { DPRINTF("%d = read [%s] prio=%d\n", n, rbuf, prio); } else { perror("read"); exit(-1); } } read_start = 0; } else { memset(buf, 'w', sizeof(buf)); buf[sizeof(buf)-1] = '\0'; FD_ZERO(&wfds); FD_SET(fd2, &wfds); DPRINTF("selecting write...\n"); if (select(fd2+1, NULL, &wfds, NULL, NULL) == -1) { perror("select"); exit(-1); } if (FD_ISSET(fd2, &wfds)) { if (mq_send(fd2, buf, sizeof(buf), prio) != 0) { perror("write"); exit(-1); } } read_start = 1; // sleep(1); } } printf("write loop= %d\n", i/2); mq_close(fd1); mq_close(fd2); return 0; }
UNIXãã¡ã¤ã³ã½ã±ãã
sread.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/select.h> #include <sys/ioctl.h> #include <errno.h> #define DPRINTF(...) //#define DPRINTF(...) printf(__VA_ARGS__) #define SOCK_NAME "/tmp/test_socket" int main(int argc, char *argv[]) { int fd1, fd2; struct sockaddr_un saddr; struct sockaddr_un caddr; int len, val; fd_set rfds, wfds; char buf[128]; int read_start; if ((fd1 = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(-1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sun_family = AF_UNIX; strcpy(saddr.sun_path, SOCK_NAME); unlink(SOCK_NAME); if (bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr.sun_family) + strlen(SOCK_NAME)) < 0){ perror("bind"); exit(-1); } if (listen(fd1, 1) < 0) { perror("listen"); exit(-1); } len = sizeof(caddr); if ((fd2 = accept(fd1, (struct sockaddr *)&caddr, (socklen_t *)&len)) < 0) { perror("accept"); exit(-1); } close(fd1); /* set non-blocking */ val = 1; ioctl(fd2, FIONBIO, &val); read_start=1; while (1) { if (read_start) { buf[0] = '\0'; FD_ZERO(&rfds); FD_SET(fd2, &rfds); DPRINTF("selecting read...\n"); if (select(fd2+1, &rfds, NULL, NULL, NULL) == -1) { perror("select"); } if (FD_ISSET(fd2, &rfds)) { int n; n = read(fd2, buf, sizeof(buf)); if (n > 0 ) { DPRINTF("%d = read [%s]\n", n, buf); } else { perror("read"); exit(-1); } } read_start = 0; } else { memset(buf, 'r', sizeof(buf)); buf[sizeof(buf)-1] = '\0'; FD_ZERO(&wfds); FD_SET(fd2, &wfds); DPRINTF("selecting write...\n"); if (select(fd2+1, NULL, &wfds, NULL, NULL) == -1) { perror("select"); exit(-1); } if (FD_ISSET(fd2, &wfds)) { if (write(fd2, buf, sizeof(buf)) != sizeof(buf)) { perror("write"); exit(-1); } } read_start = 1; // sleep(1); } } close(fd2); return 0; }
swrite.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/select.h> #include <sys/ioctl.h> #include <errno.h> #define DPRINTF(...) //#define DPRINTF(...) printf(__VA_ARGS__) #define SOCK_NAME "/tmp/test_socket" int main(int argc, char *argv[]) { int fd; struct sockaddr_un addr; int len, val; fd_set rfds, wfds; char buf[128]; int i, nloop; int read_start; if (argc != 2) { printf("usage:\n./swrite <NLOOP>\n"); exit(-1); } nloop = atoi(argv[1]); if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(-1); } memset((char *)&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, SOCK_NAME); /* set non-blocking */ val = 1; ioctl(fd, FIONBIO, &val); if (connect(fd, (struct sockaddr *)&addr, sizeof(addr.sun_family) + strlen(SOCK_NAME)) < 0){ perror("connect"); exit(1); } read_start=0; for (i=0; i<nloop; i++) { if (read_start) { buf[0] = '\0'; FD_ZERO(&rfds); FD_SET(fd, &rfds); DPRINTF("selecting read...\n"); if (select(fd+1, &rfds, NULL, NULL, NULL) == -1) { perror("select"); } if (FD_ISSET(fd, &rfds)) { int n; n = read(fd, buf, sizeof(buf)); if (n > 0 ) { DPRINTF("%d = read [%s]\n", n, buf); } else { perror("read"); exit(-1); } } read_start = 0; } else { memset(buf, 'w', sizeof(buf)); buf[sizeof(buf)-1] = '\0'; FD_ZERO(&wfds); FD_SET(fd, &wfds); DPRINTF("selecting write...\n"); if (select(fd+1, NULL, &wfds, NULL, NULL) == -1) { perror("select"); exit(-1); } if (FD_ISSET(fd, &wfds)) { if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { perror("write"); exit(-1); } } read_start = 1; // sleep(1); } } printf("write loop= %d\n", i/2); close(fd); return 0; }
ååä»ããã¤ãï¼FIFOï¼
fread.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include <sys/select.h> #include <fcntl.h> #include <errno.h> #define DPRINTF(...) //#define DPRINTF(...) printf(__VA_ARGS__) int main(int argc, char *argv[]) { int fd1, fd2; fd_set rfds, wfds; char buf[128]; int read_start; unlink("/tmp/fifo1"); unlink("/tmp/fifo2"); if (mkfifo("/tmp/fifo1", 0666) == -1) { perror("mkfifo /tmp/fifo1"); exit(-1); } if (mkfifo("/tmp/fifo2", 0777) == -1) { perror("mkfifo /tmp/fifo2"); exit(-1); } if ((fd1 = open("/tmp/fifo1", O_RDONLY|O_NONBLOCK)) == -1) { perror("open /tmp/fifo1"); exit(-1); } if ((fd2 = open("/tmp/fifo2", O_RDWR|O_NONBLOCK)) == -1) { perror("open /tmp/fifo2"); exit(-1); } read_start=1; while (1) { if (read_start) { buf[0] = '\0'; FD_ZERO(&rfds); FD_SET(fd1, &rfds); DPRINTF("selecting read...\n"); if (select(fd1+1, &rfds, NULL, NULL, NULL) == -1) { perror("select"); } if (FD_ISSET(fd1, &rfds)) { int n; n = read(fd1, buf, sizeof(buf)); if (n > 0 ) { DPRINTF("%d = read [%s]\n", n, buf); } else { perror("read"); exit(-1); } } read_start = 0; } else { memset(buf, 'r', sizeof(buf)); buf[sizeof(buf)-1] = '\0'; FD_ZERO(&wfds); FD_SET(fd2, &wfds); DPRINTF("selecting write...\n"); if (select(fd2+1, NULL, &wfds, NULL, NULL) == -1) { perror("select"); exit(-1); } if (FD_ISSET(fd2, &wfds)) { if (write(fd2, buf, sizeof(buf)) != sizeof(buf)) { perror("write"); exit(-1); } } read_start = 1; // sleep(1); } } close(fd1); close(fd2); return 0; }
fwrite.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include <sys/select.h> #include <fcntl.h> #include <errno.h> #define DPRINTF(...) //#define DPRINTF(...) printf(__VA_ARGS__) int main(int argc, char *argv[]) { int fd1, fd2; fd_set rfds, wfds; char buf[128]; int read_start; int nloop, i; if (argc != 2) { printf("usage:\n./fwrite <NLOOP>\n"); exit(-1); } nloop = atoi(argv[1]); if ((fd1 = open("/tmp/fifo2", O_RDONLY|O_NONBLOCK)) == -1) { perror("open /tmp/fifo2"); exit(-1); } if ((fd2 = open("/tmp/fifo1", O_WRONLY|O_NONBLOCK)) == -1) { perror("open /tmp/fifo1"); exit(-1); } read_start=0; for (i=0; i<nloop; i++) { if (read_start) { buf[0] = '\0'; FD_ZERO(&rfds); FD_SET(fd1, &rfds); DPRINTF("selecting read...\n"); if (select(fd1+1, &rfds, NULL, NULL, NULL) == -1) { perror("select"); } if (FD_ISSET(fd1, &rfds)) { int n; n = read(fd1, buf, sizeof(buf)); if (n > 0 ) { DPRINTF("%d = read [%s]\n", n, buf); } else { perror("read"); exit(-1); } } read_start = 0; } else { memset(buf, 'w', sizeof(buf)); buf[sizeof(buf)-1] = '\0'; FD_ZERO(&wfds); FD_SET(fd2, &wfds); DPRINTF("selecting write...\n"); if (select(fd2+1, NULL, &wfds, NULL, NULL) == -1) { perror("select"); exit(-1); } if (FD_ISSET(fd2, &wfds)) { if (write(fd2, buf, sizeof(buf)) != sizeof(buf)) { perror("write"); exit(-1); } } read_start = 1; // sleep(1); } } printf("write loop= %d\n", i/2); close(fd1); close(fd2); return 0; }