다음 소스코드는 여러 개의 클라이언트가 서버에 접속해서 이벤트를 보내며, 서버는 이벤트를 순차적으로 처리합니다. 유닉스 소켓보다 빠른 공유 메모리를 사용하였으며 동기적으로 처리하기 위해 세마포어를 활용합니다. 이 구현이 유닉스 소켓을 사용한 것보다 실제로 빠른지는 테스트하지 않았습니다.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <semaphore.h>
#include <string.h>
typedef struct {
sem_t sem_in;
sem_t sem_out;
time_t time;
pid_t pid;
} SharedData;
int main (int argc, char **argv)
{
int fd;
SharedData *data = NULL;
const size_t len = sizeof (SharedData);
/* struct timespec abstime; */
/* abstime.tv_nsec = 0; */
fd = shm_open ("/tmp/example", O_RDWR | O_CREAT, 0600);
if ((fd < 0) ||
(ftruncate (fd, len) < 0))
goto finally;
data = mmap (0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
sem_init (&data->sem_in, 1, 0);
sem_init (&data->sem_out, 1, 1);
while (1)
{
int retval;
retval = sem_wait (&data->sem_in);
/* abstime.tv_sec = time (NULL) + 1; */
/* retval = sem_timedwait (&data->sem_in, &abstime); */
if (retval == 0)
{
printf ("%d: %ld\n", data->pid, data->time);
}
else
{
printf ("error: %s\n", strerror (errno));
}
int sval;
sem_getvalue (&data->sem_out, &sval);
if (sval == 0)
sem_post (&data->sem_out);
puts ("continue");
}
finally:
sem_destroy (&data->sem_in);
if (data)
munmap (data, len);
if (fd > 0)
close (fd);
if (errno)
perror ("");
shm_unlink ("/tmp/example");
return errno;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <semaphore.h>
typedef struct {
sem_t sem_in;
sem_t sem_out;
time_t time;
pid_t pid;
} SharedData;
int main (int argc, char **argv)
{
int fd;
SharedData *data = NULL;
const size_t len = sizeof (SharedData);
fd = shm_open ("/tmp/example", O_RDWR, 0600);
if ((fd < 0) ||
(ftruncate (fd, len) < 0))
goto finally;
data = mmap (0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
while (1)
{
sem_wait (&data->sem_out);
data->time = time (NULL);
data->pid = getpid ();
int sval;
sem_getvalue (&data->sem_in, &sval);
if (sval == 0)
sem_post (&data->sem_in);
printf ("%d, %ld\n", data->pid, data->time);
sleep (1);
}
finally:
if (data)
munmap (data, len);
if (fd > 0)
close (fd);
if (errno)
perror ("");
return errno;
}
Makefile
all: client.c server.c Makefile
cc -Wall -Werror -o client client.c
cc -Wall -Werror -o server server.c