patron 10 ヶ月 前
コミット
8c37c99e5f
3 ファイル変更271 行追加0 行削除
  1. 25 0
      sharedmemory/LICENSE
  2. 7 0
      sharedmemory/Makefile
  3. 239 0
      sharedmemory/main.c

+ 25 - 0
sharedmemory/LICENSE

@@ -0,0 +1,25 @@
+BSD 2-Clause License
+
+Copyright (c) 2017, David Marec
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 7 - 0
sharedmemory/Makefile

@@ -0,0 +1,7 @@
+PROG_CXX=   shareMemory
+NO_OBJ=
+SRCS= main.c
+LDADD= ${LIBRT} ${LIBPTHREAD}
+CFLAGS= -O2
+MAN= 
+.include <bsd.prog.mk>

+ 239 - 0
sharedmemory/main.c

@@ -0,0 +1,239 @@
+#include <unistd.h>
+#include <err.h>                                                                                          
+#include <errno.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <netinet/in.h>		/* bind */
+#include <fcntl.h> // O_xxxx
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>  //bzero
+
+const char* pathname="/rats";
+
+static void *udpController(void *dummy)
+{
+	/* 
+	 *
+	 * block SIGINT 
+	 * to make sure this signal
+	 * will be handled by the main thread
+	 * because this is this thread's way to terminate
+	 * the process
+	 *
+	 */
+
+	sigset_t sigmask;
+	sigemptyset(&sigmask);
+	sigaddset(&sigmask,SIGINT);
+	if(sigprocmask(SIG_BLOCK,&sigmask,NULL))
+		perror("sigprocmask");
+
+	/* 
+	 *
+	 * create share memory segment
+	 *
+	 */
+
+	// may use SHM_ANON running FreeBSD while called by the same process
+	int fd=shm_open(pathname,O_RDWR,0600);
+	if (fd < 0){
+		warn("%s: shm_open", __func__);
+		pthread_exit(NULL);
+	}
+	if (ftruncate(fd, getpagesize()) < 0){
+		warn("%s: ftruncate", __func__);
+		pthread_exit(NULL);
+	}
+
+	/* 
+	 *
+	 * open an UDP socket
+	 *
+	 */
+
+	int s=socket(PF_INET,SOCK_DGRAM,0);
+	if(-1==s){
+		warn("socket");
+		pthread_exit(NULL);
+	}
+
+	/*
+	 * Socket address, internet style.
+	 */
+
+	struct sockaddr_in sa;
+	bzero(&sa,sizeof sa);
+	sa.sin_len=sizeof sa;
+	sa.sin_family=AF_INET;
+	sa.sin_port=htons(5514);
+	//sa.sin_addr.s_addr = htonl((((((127 << 8) | 0) << 8) | 0) << 8) | 1);
+	sa.sin_addr.s_addr = INADDR_ANY;
+	uint32_t cursor;
+	if(!bind(s,(struct sockaddr*)&sa,sizeof sa)){
+
+		for(;;){
+			char buffer[getpagesize()];
+			int n=read(s,&buffer[4],getpagesize()-4);
+			if(n==-1){
+				break;
+			}
+
+			if(n>0){
+				if(!bcmp((char*)&buffer[4],"quit",4)){
+					printf("kill request\n");
+					/* bye */
+					kill(getpid(),SIGINT);
+					break;
+				}
+
+				/* prepend length into the buffer */
+				cursor=n+4;		
+				buffer[0]= (n>> 24);
+				buffer[1]= (n>> 16);
+				buffer[2]= (n>> 8);
+				buffer[3]= (n);
+
+				ssize_t len = pwrite(fd, buffer, cursor, 0);	
+
+				if(len<0){
+					warn("%s: pwrite failure", __func__);
+				}
+				if(len!=cursor){
+					warn("%zu vs %du, %s: pwrite length mismatch",len,cursor, __func__);
+				}
+
+			}
+		}
+
+	}else
+		warn("bind failure");
+
+	close (s);
+	pthread_exit(NULL);
+}
+
+static void showmem()
+{
+	int fd = shm_open(pathname, O_RDONLY, 0600);
+
+	if (fd < 0) {
+		warn("%s: shm_open", __func__);
+		return;
+	}
+
+	/* extract length */
+	uint8_t curbuf[4];
+	ssize_t len=pread(fd, &curbuf, 4, 0);
+	if (len == 4) {
+		uint32_t l = (uint32_t)curbuf[0] << 24 |
+			(uint32_t)curbuf[1] << 16 |
+			(uint32_t)curbuf[2] << 8  |
+			(uint32_t)curbuf[3];
+		if (l > 0) {
+			uint8_t* buf = malloc(l);
+			if (buf) {
+				/* data */
+				ssize_t total=pread(fd,buf,l,4);
+				printf("%zu:\t %s",total,buf);
+				free(buf);
+			} else {
+				warn("malloc");
+			}
+
+		}
+	} else {
+		printf("nothing.\n");
+	}
+}
+
+void
+sigHandler(int signo, siginfo_t *si, void * /* ucontext_t */ uap)
+{
+	switch (signo) {
+		case SIGINFO:
+			printf("no need to panic.\n");
+			  __attribute__((fallthrough));
+		case SIGALRM:
+			showmem();
+			break;
+		default:
+			printf("sig:%d received.", signo);
+			break;
+	}
+
+}
+
+int main(int argc, char* argv[])
+{
+	timer_t		timerid;
+	int fd = shm_open(pathname, O_CREAT | O_RDWR, 0600);
+
+	if (fd < 0)
+		err(EPERM, "%s: shm_open", __func__);
+	if (ftruncate(fd, getpagesize()) < 0)
+		err(EIO, "%s: ftruncate", __func__);
+
+	pthread_t pidudp;
+	pthread_create(&pidudp, NULL, &udpController, NULL);
+	/* signal */
+	struct sigaction sa;
+	sa.sa_handler = NULL;
+	sa.sa_sigaction = &sigHandler;
+	sa.sa_flags = SA_SIGINFO;
+	sigemptyset(&sa.sa_mask);
+	// Block every signal during the handler
+	sigfillset(&sa.sa_mask);
+	if (sigaction(SIGINFO, &sa, NULL)) {
+		warn("SIGNFO not caught.");
+	}
+	if (sigaction(SIGALRM, &sa, NULL)) {
+		err(2, "sigaction:ALARM");
+	}
+
+	/* timer */
+	if (timer_create(CLOCK_REALTIME, NULL, &timerid)) {
+		err(2,"timer_create failed.");
+	}
+	/* 3 -> TIMER_MAX stored into timerid->oshandle */
+	printf("Timer #%d now created at address %p.\n", timer_oshandle_np(timerid), timerid);
+	/* Set values and start timer */
+	struct itimerspec its;
+	its.it_interval.tv_sec = 2;
+	its.it_interval.tv_nsec = 0;
+	its.it_value.tv_sec = its.it_interval.tv_sec;
+	its.it_value.tv_nsec = 0;
+
+	if (timer_settime(timerid, 0, &its, NULL)) {
+		warn("timer_settime failed.");
+	}
+
+	printf("waiting...\n");
+	sigset_t sigmask;
+	sigemptyset(&sigmask);
+	sigaddset(&sigmask,SIGINT);
+	sigprocmask(SIG_BLOCK,&sigmask,NULL);
+
+	int sigpending;
+	if(sigwait(&sigmask,&sigpending))
+		warn("sigwait failure.\n");
+	//brutal thread killing, I know it s bad. but I 'm punk btw.
+	printf("bye\n");
+	timer_delete(timerid);
+	struct timespec t;
+	if (!clock_gettime(CLOCK_REALTIME, &t)) {
+		t.tv_sec += 5;
+		if (pthread_timedjoin_np(pidudp, NULL, &t)) {
+			pthread_cancel(pidudp);
+		}
+	} else {
+		warn("clock_gettime");
+	}
+
+	// required until SHM_ANON is used, or shm remains (persistent until reboot)
+	shm_unlink(pathname); 
+}